Removing local copy of lookup. Will use openide-util for now and switch to org.openide.util.lookup when available.
1.1 --- a/anagramdemo/anagramapp/pom.xml Wed Jan 27 17:46:23 2010 -0500
1.2 +++ b/anagramdemo/anagramapp/pom.xml Wed Feb 03 00:04:30 2010 +0100
1.3 @@ -33,13 +33,13 @@
1.4 <dependency>
1.5 <groupId>org.netbeans.api</groupId>
1.6 <artifactId>org-netbeans-modules-nbjunit</artifactId>
1.7 - <version>RELEASE65</version>
1.8 + <version>RELEASE68</version>
1.9 <scope>test</scope>
1.10 </dependency>
1.11 <dependency>
1.12 <groupId>org.netbeans.modules</groupId>
1.13 <artifactId>org-netbeans-insane</artifactId>
1.14 - <version>RELEASE65</version>
1.15 + <version>RELEASE68</version>
1.16 <scope>test</scope>
1.17 </dependency>
1.18 </dependencies>
2.1 --- a/anagramdemo/anagrambase/pom.xml Wed Jan 27 17:46:23 2010 -0500
2.2 +++ b/anagramdemo/anagrambase/pom.xml Wed Feb 03 00:04:30 2010 +0100
2.3 @@ -44,11 +44,6 @@
2.4 </build>
2.5 <dependencies>
2.6 <dependency>
2.7 - <groupId>org.apidesign</groupId>
2.8 - <artifactId>lookup</artifactId>
2.9 - <version>7.22.0</version>
2.10 - </dependency>
2.11 - <dependency>
2.12 <groupId>org.springframework</groupId>
2.13 <artifactId>spring-core</artifactId>
2.14 <version>2.5.6</version>
3.1 --- a/anagramdemo/simplescrambler/pom.xml Wed Jan 27 17:46:23 2010 -0500
3.2 +++ b/anagramdemo/simplescrambler/pom.xml Wed Feb 03 00:04:30 2010 +0100
3.3 @@ -44,11 +44,6 @@
3.4 <artifactId>anagram-spring-lookup</artifactId>
3.5 <version>1.0</version>
3.6 </dependency>
3.7 - <dependency>
3.8 - <groupId>org.apidesign</groupId>
3.9 - <artifactId>lookup</artifactId>
3.10 - <version>7.22.0</version>
3.11 - </dependency>
3.12 </dependencies>
3.13 <name>Simple Scrambler</name>
3.14 <description>Replaces two letters in provided words.</description>
4.1 --- a/anagramdemo/staticwordlibrary/pom.xml Wed Jan 27 17:46:23 2010 -0500
4.2 +++ b/anagramdemo/staticwordlibrary/pom.xml Wed Feb 03 00:04:30 2010 +0100
4.3 @@ -19,15 +19,10 @@
4.4 <scope>test</scope>
4.5 </dependency>
4.6 <dependency>
4.7 - <groupId>org.apidesign</groupId>
4.8 - <artifactId>lookup</artifactId>
4.9 - <version>7.22.0</version>
4.10 - </dependency>
4.11 - <dependency>
4.12 <groupId>org.apidesign</groupId>
4.13 <artifactId>anagram-spring-lookup</artifactId>
4.14 <version>1.0</version>
4.15 - </dependency>
4.16 + </dependency>
4.17 </dependencies>
4.18 <name>Static Word Library</name>
4.19 <description>Provides an implementation of WordLibrary interface and registers it
5.1 --- a/lookup/apichanges.xml Wed Jan 27 17:46:23 2010 -0500
5.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
5.3 @@ -1,170 +0,0 @@
5.4 -<?xml version="1.0" encoding="UTF-8"?>
5.5 -<!--
5.6 -DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
5.7 -
5.8 -Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
5.9 -
5.10 -
5.11 -The contents of this file are subject to the terms of either the GNU
5.12 -General Public License Version 2 only ("GPL") or the Common
5.13 -Development and Distribution License("CDDL") (collectively, the
5.14 -"License"). You may not use this file except in compliance with the
5.15 -License. You can obtain a copy of the License at
5.16 -http://www.netbeans.org/cddl-gplv2.html
5.17 -or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
5.18 -specific language governing permissions and limitations under the
5.19 -License. When distributing the software, include this License Header
5.20 -Notice in each file and include the License file at
5.21 -nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
5.22 -particular file as subject to the "Classpath" exception as provided
5.23 -by Sun in the GPL Version 2 section of the License file that
5.24 -accompanied this code. If applicable, add the following below the
5.25 -License Header, with the fields enclosed by brackets [] replaced by
5.26 -your own identifying information:
5.27 -"Portions Copyrighted [year] [name of copyright owner]"
5.28 -
5.29 -Contributor(s):
5.30 -
5.31 -The Original Software is NetBeans. The Initial Developer of the Original
5.32 -Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
5.33 -Microsystems, Inc. All Rights Reserved.
5.34 -
5.35 -If you wish your version of this file to be governed by only the CDDL
5.36 -or only the GPL Version 2, indicate your decision by adding
5.37 -"[Contributor] elects to include this software in this distribution
5.38 -under the [CDDL or GPL Version 2] license." If you do not indicate a
5.39 -single choice of license, a recipient has the option to distribute
5.40 -your version of this file under either the CDDL, the GPL Version 2 or
5.41 -to extend the choice of license to its licensees as provided above.
5.42 -However, if you add GPL Version 2 code and therefore, elected the GPL
5.43 -Version 2 license, then the option applies only if the new code is
5.44 -made subject to such option by the copyright holder.
5.45 --->
5.46 -<!DOCTYPE apichanges PUBLIC "-//NetBeans//DTD API changes list 1.0//EN" "../nbbuild/javadoctools/apichanges.dtd">
5.47 -<apichanges>
5.48 -<apidefs>
5.49 -</apidefs>
5.50 -<changes>
5.51 - <change id="lookup.is.free">
5.52 - <api name="lookup"/>
5.53 - <summary>Separate module for Lookup API</summary>
5.54 - <version major="8" minor="0"/>
5.55 - <date day="20" month="12" year="2009"/>
5.56 - <author login="jtulach"/>
5.57 - <compatibility modification="yes">
5.58 - <p>
5.59 - Runtime compatibility remains, compile time compatibility is
5.60 - mostly preserved too. It is however recommended to upgrade
5.61 - dependencies of your modules. Try running
5.62 - <code>ant fix-dependencies</code> in your Ant module.
5.63 - </p>
5.64 - </compatibility>
5.65 - <description>
5.66 - <p>
5.67 - <a href="@org-openide-util-lookup@/org/openide/util/Lookup.html">Lookup</a>
5.68 - and its associated interfaces are now available as a
5.69 - <a href="@org-openide-util-lookup@/overview-summary.html">separate module</a>.
5.70 - </p>
5.71 - </description>
5.72 - <issue number="170056"/>
5.73 - </change>
5.74 - <p>
5.75 - Runtime compatibility remains, compile time compatibility is
5.76 - mostly preserved too. It is however recommended to upgrade
5.77 - dependencies of your modules. Try running
5.78 - <code>ant fix-dependencies</code> in your Ant module.
5.79 - </p>
5.80 - </compatibility>
5.81 - <description>
5.82 - <p>
5.83 - <a href="@org-openide-util-lookup@/org/openide/util/Lookup.html">Lookup</a>
5.84 - and its associated interfaces are now available as a
5.85 - <a href="@org-openide-util-lookup@/overview-summary.html">separate module</a>.
5.86 - </p>
5.87 - </description>
5.88 - <class package="org.openide.util" name="Lookup"/>
5.89 - <class package="org.openide.util.lookup" name="AbstractLookup"/>
5.90 - <class package="org.openide.util.lookup" name="ProxyLookup"/>
5.91 - <class package="org.openide.util.lookup" name="Lookups"/>
5.92 - <issue number="170056"/>
5.93 - </change>
5.94 -
5.95 - <api name="lookup"/>
5.96 -
5.97 -
5.98 -
5.99 - <change>
5.100 - <change>
5.101 - <change>
5.102 - <change>
5.103 - <change id="meta-inf-services">
5.104 - <api name="lookup"/>
5.105 - <change id="AbstractLookup.Content-ProxyLookup.beforeLookup">
5.106 - <change>
5.107 - <change>
5.108 - <change>
5.109 - <change>
5.110 - <api name="util"/>
5.111 - <summary>
5.112 - <code>ErrorManager.isNotifiable</code> added</summary>
5.113 - <version major="3" minor="18"/>
5.114 - <date day="3" month="11" year="2002"/>
5.115 - <author login="jglick"/>
5.116 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no">
5.117 - Existing code which assumes (incorrectly) that <code>isLoggable</code>
5.118 - can be used for this purpose, or which calls <code>notify</code> at a low
5.119 - level such as <code>INFORMATIONAL</code> without first checking
5.120 - <code>isNotifiable</code> for efficiency, should be revised.
5.121 - </compatibility>
5.122 - <description>
5.123 - The method <code>ErrorManager.isNotifiable</code> was added to capture
5.124 - the fact that an error manager implementation might be more aggressive
5.125 - about displaying stack traces than log messages.
5.126 - </description>
5.127 - <class package="org.openide" name="ErrorManager"/>
5.128 - <issue number="24056"/>
5.129 - </change>
5.130 - <change>
5.131 - <api name="util"/>
5.132 - <summary>
5.133 - <code>ServiceType.createClone</code> added</summary>
5.134 - <date day="30" month="11" year="2000"/>
5.135 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no">Subclasses are encouraged to implement <code>Cloneable</code>.</compatibility>
5.136 - <description>
5.137 - <code>public final ServiceType createClone()</code> added.
5.138 - </description>
5.139 - <class package="org.openide" name="ServiceType"/>
5.140 - </change>
5.141 -</changes>
5.142 -<htmlcontents>
5.143 -<head>
5.144 -<title>Change History for the Lookup API</title>
5.145 -<link rel="stylesheet" href="prose.css" type="text/css"/>
5.146 -</head>
5.147 -<body>
5.148 -<p class="overviewlink">
5.149 -<a href="overview-summary.html">Overview</a>
5.150 -</p>
5.151 -<h1>Introduction</h1>
5.152 -<h2>What do the Dates Mean?</h2>
5.153 -<p>The supplied dates indicate when the API change was made, on the CVS
5.154 -trunk. From this you can generally tell whether the change should be
5.155 -present in a given build or not; for trunk builds, simply whether it
5.156 -was made before or after the change; for builds on a stabilization
5.157 -branch, whether the branch was made before or after the given date. In
5.158 -some cases corresponding API changes have been made both in the trunk
5.159 -and in an in-progress stabilization branch, if they were needed for a
5.160 -bug fix; this ought to be marked in this list.</p>
5.161 -<ul>
5.162 -<li>The <code>release41</code> branch was made on Apr 03 '05 for use in the NetBeans 4.1 release.
5.163 -Specification versions: 6.0 begins after this point.</li>
5.164 -<li>The <code>release40</code> branch was made on Nov 01 '04 for use in the NetBeans 4.0 release.
5.165 -Specification versions: 5.0 begins after this point.</li>
5.166 -</ul>
5.167 -<hr/>
5.168 -<standard-changelists module-code-name="$codebase"/>
5.169 -<hr/>
5.170 -<p>@FOOTER@</p>
5.171 -</body>
5.172 -</htmlcontents>
5.173 -</apichanges>
6.1 --- a/lookup/arch.xml Wed Jan 27 17:46:23 2010 -0500
6.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
6.3 @@ -1,615 +0,0 @@
6.4 -<?xml version="1.0" encoding="UTF-8"?>
6.5 -<!--
6.6 -DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
6.7 -
6.8 -Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
6.9 -
6.10 -
6.11 -The contents of this file are subject to the terms of either the GNU
6.12 -General Public License Version 2 only ("GPL") or the Common
6.13 -Development and Distribution License("CDDL") (collectively, the
6.14 -"License"). You may not use this file except in compliance with the
6.15 -License. You can obtain a copy of the License at
6.16 -http://www.netbeans.org/cddl-gplv2.html
6.17 -or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
6.18 -specific language governing permissions and limitations under the
6.19 -License. When distributing the software, include this License Header
6.20 -Notice in each file and include the License file at
6.21 -nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
6.22 -particular file as subject to the "Classpath" exception as provided
6.23 -by Sun in the GPL Version 2 section of the License file that
6.24 -accompanied this code. If applicable, add the following below the
6.25 -License Header, with the fields enclosed by brackets [] replaced by
6.26 -your own identifying information:
6.27 -"Portions Copyrighted [year] [name of copyright owner]"
6.28 -
6.29 -Contributor(s):
6.30 -
6.31 -The Original Software is NetBeans. The Initial Developer of the Original
6.32 -Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
6.33 -Microsystems, Inc. All Rights Reserved.
6.34 -
6.35 -If you wish your version of this file to be governed by only the CDDL
6.36 -or only the GPL Version 2, indicate your decision by adding
6.37 -"[Contributor] elects to include this software in this distribution
6.38 -under the [CDDL or GPL Version 2] license." If you do not indicate a
6.39 -single choice of license, a recipient has the option to distribute
6.40 -your version of this file under either the CDDL, the GPL Version 2 or
6.41 -to extend the choice of license to its licensees as provided above.
6.42 -However, if you add GPL Version 2 code and therefore, elected the GPL
6.43 -Version 2 license, then the option applies only if the new code is
6.44 -made subject to such option by the copyright holder.
6.45 --->
6.46 -<!DOCTYPE api-answers PUBLIC "-//NetBeans//DTD Arch Answers//EN" "../nbbuild/antsrc/org/netbeans/nbbuild/Arch.dtd" [
6.47 - <!ENTITY api-questions SYSTEM "../nbbuild/antsrc/org/netbeans/nbbuild/Arch-api-questions.xml">
6.48 -]>
6.49 -
6.50 -<api-answers
6.51 - question-version="1.25"
6.52 - author="jtulach@netbeans.org"
6.53 ->
6.54 -
6.55 - &api-questions;
6.56 -
6.57 - <answer id="arch-overall">
6.58 - <p>
6.59 - This module defines the <a href="@TOP@/org/openide/util/Lookup.html">
6.60 - Lookup</a> which is the NetBeans way for dynamic registration
6.61 - </answer>
6.62 -
6.63 -
6.64 - <answer id="arch-quality">
6.65 - <p>
6.66 - There is a lot of unit tests in
6.67 - <a href="http://hg.netbeans.org/main-golden/openide.util.lookup/test/unit/src/">version control</a>
6.68 - system.
6.69 - </p>
6.70 - </answer>
6.71 -
6.72 - <answer id="arch-time">
6.73 - <p>
6.74 - The module has been around since 1997 and is continously being improved
6.75 - from time to time.
6.76 - </p>
6.77 - </answer>
6.78 -
6.79 -
6.80 -
6.81 - <answer id="arch-usecases">
6.82 - <a href="@org-openide-util@/org/openide/util/doc-files/api.html#service-lookup">META-INF/services</a> directory and it
6.83 - <a href="@org-openide-util@/org/openide/util/doc-files/api.html#ido-methodvalue">services
6.84 - your want or <code>null</code> depending on result of <a href="@org-openide-util@/org/openide/util/Utilities.html#isWindows()">
6.85 - </answer>
6.86 -
6.87 -
6.88 -
6.89 - <answer id="arch-what">
6.90 - <p>
6.91 - Described in the <a href="@TOP@/architecture-summary.html#answer-arch-overall">overall</a> answer.
6.92 - </p>
6.93 - </answer>
6.94 -
6.95 -
6.96 -
6.97 - url="@org-openide-util@/org/openide/util/doc-files/api.html#service-lookup"
6.98 - <answer id="compat-version">
6.99 - <p>
6.100 - This module has no settings.
6.101 - </p>
6.102 - </answer>
6.103 -
6.104 -
6.105 -
6.106 - <answer id="dep-jre">
6.107 - <p>
6.108 - Currently JRE 1.5 is needed.
6.109 - </p>
6.110 - </answer>
6.111 -
6.112 -
6.113 -
6.114 - <answer id="dep-jrejdk">
6.115 - <p>
6.116 - JRE is enough.
6.117 - </p>
6.118 - </answer>
6.119 -
6.120 -
6.121 - <answer id="dep-nb">
6.122 - <p>N/A</p>
6.123 - </answer>
6.124 -
6.125 - <answer id="dep-platform">
6.126 - <p>
6.127 - Platform independent.
6.128 - </p>
6.129 - </answer>
6.130 -
6.131 -
6.132 - <answer id="deploy-dependencies">
6.133 - <p>
6.134 - Nothing.
6.135 - </p>
6.136 - </answer>
6.137 -
6.138 -
6.139 -
6.140 - <answer id="deploy-jar">
6.141 - <p>
6.142 - <api category="devel" group="java.io.File" name="FileLocation" type="export" >
6.143 - the JAR file is located in platform cluster under <code>lib/org-openide-util-lookup.jar</code>
6.144 - </api>.
6.145 - </p>
6.146 - </answer>
6.147 -
6.148 - <answer id="deploy-shared">
6.149 - <p>
6.150 - Module is on real java classpath and as such it has to be in the shared directory.
6.151 - </p>
6.152 - </answer>
6.153 -
6.154 -
6.155 - <answer id="exec-ant-tasks">
6.156 - <p>
6.157 - No.
6.158 - </p>
6.159 - </answer>
6.160 -
6.161 -
6.162 -
6.163 - <answer id="exec-classloader">
6.164 - <p>
6.165 - No, we do not create own classloader.
6.166 - </p>
6.167 - </answer>
6.168 -
6.169 -
6.170 -
6.171 -<answer id="exec-privateaccess">
6.172 - <p>
6.173 - No.
6.174 - </p>
6.175 - </answer>
6.176 -
6.177 - <answer id="exec-process">
6.178 - <p>
6.179 - No external processes executed.
6.180 - </p>
6.181 - </answer>
6.182 -
6.183 -
6.184 - <answer id="exec-property">
6.185 - <ul>
6.186 - </ul>
6.187 - </answer>
6.188 -
6.189 -
6.190 -
6.191 - <answer id="exec-reflection">
6.192 - <p>
6.193 - </p>
6.194 - </answer>
6.195 -
6.196 - <answer id="exec-threading">
6.197 - <p>
6.198 - Everything is synchronous, except pluggable use of <code>java.util.concurrent.Executor</code>
6.199 - that allows to make calls asynchronous. The default implementation only delivers
6.200 - changes from <a href="@TOP@/org/openide/util/lookup/Lookups.html#metaInfServices(java.lang.ClassLoader)">metaInfServices</a>
6.201 - lookup in asynchronous thread.
6.202 - </p>
6.203 - </answer>
6.204 -
6.205 -
6.206 -
6.207 - <answer id="format-clipboard">
6.208 - <p>
6.209 - Not used.
6.210 - </p>
6.211 - </answer>
6.212 -
6.213 -
6.214 -
6.215 - <answer id="format-dnd">
6.216 - <p>
6.217 - The same as for clipboard.
6.218 - </p>
6.219 - </answer>
6.220 -
6.221 - <answer id="format-types">
6.222 - <p>
6.223 - No.
6.224 - </p>
6.225 - </answer>
6.226 -
6.227 -
6.228 -
6.229 - <answer id="lookup-lookup">
6.230 - <ul>
6.231 -
6.232 - <li><api name="LookupSharedClassObject" category="devel" group="lookup" type="export">
6.233 - singleton subclasses of <a href="@org-openide-util@/org/openide/util/SharedClassObject.html">SharedClassObject</a>
6.234 - are searched for using Lookup.
6.235 - </api>.</li>
6.236 -
6.237 - <li><api name="LookupClassLoader" category="devel" group="lookup" type="export">
6.238 - Nearly all resource looking functions and reflective code
6.239 - uses <a href="@JDK@/java/lang/ClassLoader.html">ClassLoader</a>
6.240 - obtained from <a href="@org-openide-util-lookup@/org/openide/util/Lookup.html#getDefault()">Lookup.getDefault()</a>
6.241 - for loading system wide resources.
6.242 - </api>.</li>
6.243 -
6.244 - </ul>
6.245 - </answer>
6.246 -
6.247 -
6.248 -
6.249 - <answer id="lookup-register">
6.250 - <p>
6.251 - No.
6.252 - </p>
6.253 - </answer>
6.254 -
6.255 -
6.256 -
6.257 -<!--
6.258 - <question id="lookup-remove" when="final">
6.259 - Do you remove entries of other modules from lookup?
6.260 - <hint>
6.261 - Why? Of course, that is possible, but it can be dangerous. Is the module
6.262 - your are masking resource from aware of what you are doing?
6.263 - </hint>
6.264 - </question>
6.265 --->
6.266 - <answer id="lookup-remove">
6.267 - <p>
6.268 - No.
6.269 - </p>
6.270 - </answer>
6.271 -
6.272 -
6.273 -
6.274 -<!--
6.275 - <question id="perf-exit" when="final">
6.276 - Does your module run any code on exit?
6.277 - </question>
6.278 --->
6.279 - <answer id="perf-exit">
6.280 - <p>
6.281 - Nothing.
6.282 - </p>
6.283 - </answer>
6.284 -
6.285 -
6.286 -
6.287 -<!--
6.288 - <question id="perf-huge_dialogs" when="final">
6.289 - Does your module contain any dialogs or wizards with a large number of
6.290 - GUI controls such as combo boxes, lists, trees, or text areas?
6.291 - </question>
6.292 --->
6.293 - <answer id="perf-huge_dialogs">
6.294 - <p>
6.295 - No.
6.296 - </p>
6.297 - </answer>
6.298 -
6.299 -
6.300 -
6.301 -<!--
6.302 - <question id="perf-limit" when="init">
6.303 - Are there any hard-coded or practical limits in the number or size of
6.304 - elements your code can handle?
6.305 - </question>
6.306 --->
6.307 - <answer id="perf-limit">
6.308 - <p>
6.309 - </p>
6.310 - </answer>
6.311 -
6.312 -
6.313 -
6.314 -<!--
6.315 - <question id="perf-mem" when="final">
6.316 - How much memory does your component consume? Estimate
6.317 - with a relation to the number of windows, etc.
6.318 - </question>
6.319 --->
6.320 - <answer id="perf-mem">
6.321 - <p>
6.322 - There are no big data structures.
6.323 - </p>
6.324 - </answer>
6.325 -
6.326 -
6.327 -
6.328 -<!--
6.329 - <question id="perf-menus" when="final">
6.330 - Does your module use dynamically updated context menus, or
6.331 - context-sensitive actions with complicated and slow enablement logic?
6.332 - <hint>
6.333 - If you do a lot of tricks when adding actions to regular or context menus, you can significantly
6.334 - slow down display of the menu, even when the user is not using your action. Pay attention to
6.335 - actions you add to the main menu bar, and to context menus of foreign nodes or components. If
6.336 - the action is conditionally enabled, or changes its display dynamically, you need to check the
6.337 - impact on performance. In some cases it may be more appropriate to make a simple action that is
6.338 - always enabled but does more detailed checks in a dialog if it is actually run.
6.339 - </hint>
6.340 - </question>
6.341 --->
6.342 - <answer id="perf-menus">
6.343 - <p>
6.344 - There are no menus.
6.345 - </p>
6.346 - </answer>
6.347 -
6.348 -
6.349 -
6.350 -<!--
6.351 - <question id="perf-progress" when="final">
6.352 - Does your module execute any long-running tasks?
6.353 -
6.354 - <hint>Long running tasks should never block
6.355 - AWT thread as it badly hurts the UI
6.356 - <a href="http://performance.netbeans.org/responsiveness/issues.html">
6.357 - responsiveness</a>.
6.358 - Tasks like connecting over
6.359 - network, computing huge amount of data, compilation
6.360 - be done asynchronously (for example
6.361 - using <code>RequestProcessor</code>), definitively it should
6.362 - not block AWT thread.
6.363 - </hint>
6.364 - </question>
6.365 --->
6.366 - <answer id="perf-progress">
6.367 - <p>
6.368 - No.
6.369 - </p>
6.370 - </answer>
6.371 -
6.372 -
6.373 -
6.374 -<!--
6.375 - <question id="perf-scale" when="init">
6.376 - Which external criteria influence the performance of your
6.377 - program (size of file in editor, number of files in menu,
6.378 - in source directory, etc.) and how well your code scales?
6.379 - <hint>
6.380 - Please include some estimates, there are other more detailed
6.381 - questions to answer in later phases of implementation.
6.382 - </hint>
6.383 - </question>
6.384 --->
6.385 - <answer id="perf-scale">
6.386 - <p>
6.387 - Lookup code scales linearily.
6.388 - </p>
6.389 - </answer>
6.390 -
6.391 -
6.392 -
6.393 -<!--
6.394 - <question id="perf-spi" when="init">
6.395 - How the performance of the plugged in code will be enforced?
6.396 - <hint>
6.397 - If you allow foreign code to be plugged into your own module, how
6.398 - do you enforce that it will behave correctly and quickly and will not
6.399 - negatively influence the performance of your own module?
6.400 - </hint>
6.401 - </question>
6.402 --->
6.403 - <answer id="perf-spi">
6.404 - <p>
6.405 - No enforcing is done.
6.406 - </p>
6.407 - </answer>
6.408 -
6.409 -
6.410 -
6.411 -<!--
6.412 - <question id="perf-startup" when="final">
6.413 - Does your module run any code on startup?
6.414 - </question>
6.415 --->
6.416 - <answer id="perf-startup">
6.417 - <p>
6.418 - No.
6.419 - </p>
6.420 - </answer>
6.421 -
6.422 -
6.423 -
6.424 -<!--
6.425 - <question id="perf-wakeup" when="final">
6.426 - Does any piece of your code wake up periodically and do something
6.427 - even when the system is otherwise idle (no user interaction)?
6.428 - </question>
6.429 --->
6.430 - <answer id="perf-wakeup">
6.431 - <p>
6.432 - No.
6.433 - </p>
6.434 - </answer>
6.435 -
6.436 -
6.437 -
6.438 -<!--
6.439 - <question id="resources-file" when="final">
6.440 - Does your module use <code>java.io.File</code> directly?
6.441 -
6.442 - <hint>
6.443 - NetBeans provide a logical wrapper over plain files called
6.444 - <code>org.openide.filesystems.FileObject</code> that
6.445 - provides uniform access to such resources and is the preferred
6.446 - way that should be used. But of course there can be situations when
6.447 - this is not suitable.
6.448 - </hint>
6.449 - </question>
6.450 --->
6.451 - <answer id="resources-file">
6.452 - <p>
6.453 - No.
6.454 - </p>
6.455 - </answer>
6.456 -
6.457 -
6.458 -
6.459 -<!--
6.460 - <question id="resources-layer" when="final">
6.461 - Does your module provide own layer? Does it create any files or
6.462 - folders in it? What it is trying to communicate by that and with which
6.463 - components?
6.464 -
6.465 - <hint>
6.466 - NetBeans allows automatic and declarative installation of resources
6.467 - by module layers. Module register files into appropriate places
6.468 - and other components use that information to perform their task
6.469 - (build menu, toolbar, window layout, list of templates, set of
6.470 - options, etc.).
6.471 - </hint>
6.472 - </question>
6.473 --->
6.474 - <answer id="resources-layer">
6.475 - <p>
6.476 - No.
6.477 - </p>
6.478 - </answer>
6.479 -
6.480 -
6.481 -
6.482 -<!--
6.483 - <question id="resources-mask" when="final">
6.484 - Does your module mask/hide/override any resources provided by other modules in
6.485 - their layers?
6.486 -
6.487 - <hint>
6.488 - If you mask a file provided by another module, you probably depend
6.489 - on that and do not want the other module to (for example) change
6.490 - the file's name. That module shall thus make that file available as an API
6.491 - of some stability category.
6.492 - </hint>
6.493 - </question>
6.494 --->
6.495 - <answer id="resources-mask">
6.496 - <p>
6.497 - No.
6.498 - </p>
6.499 - </answer>
6.500 -
6.501 -
6.502 -
6.503 -<!--
6.504 - <question id="resources-read" when="final">
6.505 - Does your module read any resources from layers? For what purpose?
6.506 -
6.507 - <hint>
6.508 - As this is some kind of intermodule dependency, it is a kind of API.
6.509 - Please describe it and classify according to
6.510 - <a href="http://openide.netbeans.org/tutorial/api-design.html#categories">
6.511 - common stability categories</a>.
6.512 - </hint>
6.513 - </question>
6.514 --->
6.515 - <answer id="resources-read">
6.516 - <p>
6.517 - No.
6.518 - </p>
6.519 - </answer>
6.520 -
6.521 -
6.522 -
6.523 -<!--
6.524 - <question id="security-grant" when="final">
6.525 - Does your code grant additional rights to some other code?
6.526 - <hint>Avoid using a class loader that adds extra
6.527 - permissions to loaded code unless really necessary.
6.528 - Also note that your API implementation
6.529 - can also expose unneeded permissions to enemy code by
6.530 - calling AccessController.doPrivileged().</hint>
6.531 - </question>
6.532 --->
6.533 - <answer id="security-grant">
6.534 - <p>
6.535 - No security permitions manipulated.
6.536 - </p>
6.537 - </answer>
6.538 -
6.539 -
6.540 -
6.541 -<!--
6.542 - <question id="security-policy" when="final">
6.543 - Does your functionality require modifications to the standard policy file?
6.544 - <hint>Your code might pass control to third-party code not
6.545 - coming from trusted domains. This could be code downloaded over the
6.546 - network or code coming from libraries that are not bundled
6.547 - with NetBeans. Which permissions need to be granted to which domains?</hint>
6.548 - </question>
6.549 --->
6.550 - <answer id="security-policy">
6.551 - <p>
6.552 - No security permissions manipulated.
6.553 - </p>
6.554 - </answer>
6.555 -
6.556 -
6.557 -
6.558 -
6.559 -<!--
6.560 - <question id="arch-where" when="init">
6.561 - Where one can find sources for your module?
6.562 - <hint>
6.563 - Please provide link to the CVS web client at
6.564 - http://www.netbeans.org/download/source_browse.html
6.565 - or just use tag defaultanswer generate='here'
6.566 - </hint>
6.567 - </question>
6.568 --->
6.569 - <answer id="arch-where">
6.570 - <defaultanswer generate='here' />
6.571 - </answer>
6.572 -
6.573 -
6.574 -
6.575 -
6.576 -<!--
6.577 - <question id="compat-deprecation" when="init">
6.578 - How the introduction of your project influences functionality
6.579 - provided by previous version of the product?
6.580 - <hint>
6.581 - If you are planning to deprecate/remove/change any existing APIs,
6.582 - list them here accompanied with the reason explaining why you
6.583 - are doing so.
6.584 - </hint>
6.585 - </question>
6.586 --->
6.587 - <answer id="compat-deprecation">
6.588 - <p>
6.589 - XXX no answer for compat-deprecation
6.590 - </p>
6.591 - </answer>
6.592 -
6.593 -
6.594 -
6.595 -<!--
6.596 - <question id="resources-preferences" when="final">
6.597 - Does your module uses preferences via Preferences API? Does your module use NbPreferences or
6.598 - or regular JDK Preferences ? Does it read, write or both ?
6.599 - Does it share preferences with other modules ? If so, then why ?
6.600 - <hint>
6.601 - You may use
6.602 - <api type="export" group="preferences"
6.603 - name="preference node name" category="private">
6.604 - description of individual keys, where it is used, what it
6.605 - influences, whether the module reads/write it, etc.
6.606 - </api>
6.607 - Due to XML ID restrictions, rather than /org/netbeans/modules/foo give the "name" as org.netbeans.modules.foo.
6.608 - Note that if you use NbPreferences this name will then be the same as the code name base of the module.
6.609 - </hint>
6.610 - </question>
6.611 --->
6.612 - <answer id="resources-preferences">
6.613 - <p>
6.614 - XXX no answer for resources-preferences
6.615 - </p>
6.616 - </answer>
6.617 -
6.618 -</api-answers>
7.1 --- a/lookup/manifest.mf Wed Jan 27 17:46:23 2010 -0500
7.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
7.3 @@ -1,5 +0,0 @@
7.4 -Manifest-Version: 1.0
7.5 -OpenIDE-Module: org.openide.util.lookup
7.6 -OpenIDE-Module-Implementation-Version: 1
7.7 -OpenIDE-Module-Localizing-Bundle: org/openide/util/lookup/Bundle.properties
7.8 -
8.1 --- a/lookup/pom.xml Wed Jan 27 17:46:23 2010 -0500
8.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
8.3 @@ -1,85 +0,0 @@
8.4 -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
8.5 - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
8.6 - <modelVersion>4.0.0</modelVersion>
8.7 - <groupId>org.apidesign</groupId>
8.8 - <artifactId>lookup</artifactId>
8.9 - <packaging>jar</packaging>
8.10 - <version>7.29.0</version>
8.11 - <url>http://lookup.apidesign.org</url>
8.12 - <parent>
8.13 - <groupId>org.apidesign</groupId>
8.14 - <artifactId>all-lookup</artifactId>
8.15 - <relativePath>..</relativePath>
8.16 - <version>2.0</version>
8.17 - </parent>
8.18 - <ciManagement>
8.19 - <system>hudson</system>
8.20 - <url>http://hudson.apidesign.org/hudson/job/lookup</url>
8.21 - </ciManagement>
8.22 - <issueManagement>
8.23 - <system>issuezilla</system>
8.24 - <url>http://platform.netbeans.org/issues/</url>
8.25 - </issueManagement>
8.26 - <mailingLists>
8.27 - <mailingList>
8.28 - <name>Using the NetBeans Platform</name>
8.29 - <archive>http://openide.netbeans.org/servlets/SummarizeList?listName=dev</archive>
8.30 - <post>dev@openide.netbeans.org</post>
8.31 - </mailingList>
8.32 - </mailingLists>
8.33 - <build>
8.34 - <plugins>
8.35 - <plugin>
8.36 - <groupId>org.apache.maven.plugins</groupId>
8.37 - <artifactId>maven-compiler-plugin</artifactId>
8.38 - <version>2.0.2</version>
8.39 - <executions>
8.40 - <execution>
8.41 - <id>default</id>
8.42 - <goals>
8.43 - <goal>compile</goal>
8.44 - </goals>
8.45 - <phase>process-resources</phase>
8.46 - <configuration>
8.47 - <compilerArgument>-proc:none</compilerArgument>
8.48 - </configuration>
8.49 - </execution>
8.50 - </executions>
8.51 - <configuration>
8.52 - <source>1.5</source>
8.53 - <target>1.5</target>
8.54 - </configuration>
8.55 - </plugin>
8.56 - <plugin>
8.57 - <groupId>org.apache.maven.plugins</groupId>
8.58 - <artifactId>maven-javadoc-plugin</artifactId>
8.59 - <version>2.5</version>
8.60 - <configuration>
8.61 - <excludePackageNames>org.netbeans.modules.openide.util</excludePackageNames>
8.62 - <overview>${basedir}/src/main/java/org/openide/util/lookup/doc-files/index.html</overview>
8.63 - </configuration>
8.64 - </plugin>
8.65 - </plugins>
8.66 - </build>
8.67 - <dependencies>
8.68 - <dependency>
8.69 - <groupId>org.netbeans.api</groupId>
8.70 - <artifactId>org-netbeans-modules-nbjunit</artifactId>
8.71 - <version>RELEASE65</version>
8.72 - <scope>test</scope>
8.73 - </dependency>
8.74 - <dependency>
8.75 - <groupId>org.netbeans.modules</groupId>
8.76 - <artifactId>org-netbeans-insane</artifactId>
8.77 - <version>RELEASE65</version>
8.78 - <scope>test</scope>
8.79 - </dependency>
8.80 - </dependencies>
8.81 - <name>Lookup Library</name>
8.82 - <description>Lookup library is a general tool for component injection as well as
8.83 -adaptable pattern. Originating from the heart of NetBeans project,
8.84 -it is a general purpose library that can be used in any application.
8.85 -
8.86 -See http://lookup.apidesign.org
8.87 -</description>
8.88 -</project>
9.1 --- a/lookup/src/main/java/org/netbeans/modules/openide/util/AbstractServiceProviderProcessor.java Wed Jan 27 17:46:23 2010 -0500
9.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
9.3 @@ -1,296 +0,0 @@
9.4 -/*
9.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
9.6 - *
9.7 - * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
9.8 - *
9.9 - * The contents of this file are subject to the terms of either the GNU
9.10 - * General Public License Version 2 only ("GPL") or the Common
9.11 - * Development and Distribution License("CDDL") (collectively, the
9.12 - * "License"). You may not use this file except in compliance with the
9.13 - * License. You can obtain a copy of the License at
9.14 - * http://www.netbeans.org/cddl-gplv2.html
9.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
9.16 - * specific language governing permissions and limitations under the
9.17 - * License. When distributing the software, include this License Header
9.18 - * Notice in each file and include the License file at
9.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
9.20 - * particular file as subject to the "Classpath" exception as provided
9.21 - * by Sun in the GPL Version 2 section of the License file that
9.22 - * accompanied this code. If applicable, add the following below the
9.23 - * License Header, with the fields enclosed by brackets [] replaced by
9.24 - * your own identifying information:
9.25 - * "Portions Copyrighted [year] [name of copyright owner]"
9.26 - *
9.27 - * If you wish your version of this file to be governed by only the CDDL
9.28 - * or only the GPL Version 2, indicate your decision by adding
9.29 - * "[Contributor] elects to include this software in this distribution
9.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
9.31 - * single choice of license, a recipient has the option to distribute
9.32 - * your version of this file under either the CDDL, the GPL Version 2 or
9.33 - * to extend the choice of license to its licensees as provided above.
9.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
9.35 - * Version 2 license, then the option applies only if the new code is
9.36 - * made subject to such option by the copyright holder.
9.37 - *
9.38 - * Contributor(s):
9.39 - *
9.40 - * Portions Copyrighted 2009 Sun Microsystems, Inc.
9.41 - */
9.42 -
9.43 -package org.netbeans.modules.openide.util;
9.44 -
9.45 -import java.io.BufferedReader;
9.46 -import java.io.FileNotFoundException;
9.47 -import java.io.IOException;
9.48 -import java.io.InputStream;
9.49 -import java.io.InputStreamReader;
9.50 -import java.io.OutputStream;
9.51 -import java.io.OutputStreamWriter;
9.52 -import java.io.PrintWriter;
9.53 -import java.lang.annotation.Annotation;
9.54 -import java.util.ArrayList;
9.55 -import java.util.HashMap;
9.56 -import java.util.List;
9.57 -import java.util.Map;
9.58 -import java.util.Set;
9.59 -import java.util.WeakHashMap;
9.60 -import javax.annotation.processing.AbstractProcessor;
9.61 -import javax.annotation.processing.ProcessingEnvironment;
9.62 -import javax.annotation.processing.RoundEnvironment;
9.63 -import javax.lang.model.element.AnnotationMirror;
9.64 -import javax.lang.model.element.AnnotationValue;
9.65 -import javax.lang.model.element.Element;
9.66 -import javax.lang.model.element.ExecutableElement;
9.67 -import javax.lang.model.element.Modifier;
9.68 -import javax.lang.model.element.TypeElement;
9.69 -import javax.lang.model.type.TypeMirror;
9.70 -import javax.lang.model.util.ElementFilter;
9.71 -import javax.tools.Diagnostic.Kind;
9.72 -import javax.tools.FileObject;
9.73 -import javax.tools.StandardLocation;
9.74 -
9.75 -/**
9.76 - * Infrastructure for generating {@code META-INF/services/*} and
9.77 - * {@code META-INF/namedservices/*} registrations from annotations.
9.78 - */
9.79 -public abstract class AbstractServiceProviderProcessor extends AbstractProcessor {
9.80 -
9.81 - private final Map<ProcessingEnvironment,Map<String,List<String>>> outputFilesByProcessor = new WeakHashMap<ProcessingEnvironment,Map<String,List<String>>>();
9.82 - private final Map<ProcessingEnvironment,Map<String,List<Element>>> originatingElementsByProcessor = new WeakHashMap<ProcessingEnvironment,Map<String,List<Element>>>();
9.83 - private final Map<TypeElement,Boolean> verifiedClasses = new WeakHashMap<TypeElement,Boolean>();
9.84 -
9.85 - /** For access by subclasses. */
9.86 - protected AbstractServiceProviderProcessor() {}
9.87 -
9.88 - public @Override final boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
9.89 - if (roundEnv.errorRaised()) {
9.90 - return false;
9.91 - }
9.92 - if (roundEnv.processingOver()) {
9.93 - writeServices();
9.94 - outputFilesByProcessor.clear();
9.95 - originatingElementsByProcessor.clear();
9.96 - return true;
9.97 - } else {
9.98 - return handleProcess(annotations, roundEnv);
9.99 - }
9.100 - }
9.101 -
9.102 - /**
9.103 - * The regular body of {@link #process}.
9.104 - * Called during regular rounds if there are no outstanding errors.
9.105 - * In the last round, one of the processors will write out generated registrations.
9.106 - * @param annotations as in {@link #process}
9.107 - * @param roundEnv as in {@link #process}
9.108 - * @return as in {@link #process}
9.109 - */
9.110 - protected abstract boolean handleProcess(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv);
9.111 -
9.112 - /**
9.113 - * Register a service.
9.114 - * If the class does not have an appropriate signature, an error will be printed and the registration skipped.
9.115 - * @param clazz the service implementation type
9.116 - * @param annotation the (top-level) annotation registering the service, for diagnostic purposes
9.117 - * @param type the type to which the implementation must be assignable
9.118 - * @param path a path under which to register, or "" if inapplicable
9.119 - * @param position a position at which to register, or {@link Integer#MAX_VALUE} to skip
9.120 - * @param supersedes possibly empty list of implementation to supersede
9.121 - */
9.122 - protected final void register(TypeElement clazz, Class<? extends Annotation> annotation,
9.123 - TypeMirror type, String path, int position, String[] supersedes) {
9.124 - Boolean verify = verifiedClasses.get(clazz);
9.125 - if (verify == null) {
9.126 - verify = verifyServiceProviderSignature(clazz, annotation);
9.127 - verifiedClasses.put(clazz, verify);
9.128 - }
9.129 - if (!verify) {
9.130 - return;
9.131 - }
9.132 - String impl = processingEnv.getElementUtils().getBinaryName(clazz).toString();
9.133 - String xface = processingEnv.getElementUtils().getBinaryName((TypeElement) processingEnv.getTypeUtils().asElement(type)).toString();
9.134 - if (!processingEnv.getTypeUtils().isAssignable(clazz.asType(), type)) {
9.135 - AnnotationMirror ann = findAnnotationMirror(clazz, annotation);
9.136 - processingEnv.getMessager().printMessage(Kind.ERROR, impl + " is not assignable to " + xface,
9.137 - clazz, ann, findAnnotationValue(ann, "service"));
9.138 - return;
9.139 - }
9.140 - processingEnv.getMessager().printMessage(Kind.NOTE,
9.141 - impl + " to be registered as a " + xface + (path.length() > 0 ? " under " + path : ""));
9.142 - String rsrc = (path.length() > 0 ? "META-INF/namedservices/" + path + "/" : "META-INF/services/") + xface;
9.143 - {
9.144 - Map<String,List<Element>> originatingElements = originatingElementsByProcessor.get(processingEnv);
9.145 - if (originatingElements == null) {
9.146 - originatingElements = new HashMap<String,List<Element>>();
9.147 - originatingElementsByProcessor.put(processingEnv, originatingElements);
9.148 - }
9.149 - List<Element> origEls = originatingElements.get(rsrc);
9.150 - if (origEls == null) {
9.151 - origEls = new ArrayList<Element>();
9.152 - originatingElements.put(rsrc, origEls);
9.153 - }
9.154 - origEls.add(clazz);
9.155 - }
9.156 - Map<String,List<String>> outputFiles = outputFilesByProcessor.get(processingEnv);
9.157 - if (outputFiles == null) {
9.158 - outputFiles = new HashMap<String,List<String>>();
9.159 - outputFilesByProcessor.put(processingEnv, outputFiles);
9.160 - }
9.161 - List<String> lines = outputFiles.get(rsrc);
9.162 - if (lines == null) {
9.163 - lines = new ArrayList<String>();
9.164 - try {
9.165 - try {
9.166 - FileObject in = processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, "", rsrc);
9.167 - in.openInputStream().close();
9.168 - processingEnv.getMessager().printMessage(Kind.ERROR,
9.169 - "Cannot generate " + rsrc + " because it already exists in sources: " + in.toUri());
9.170 - return;
9.171 - } catch (NullPointerException ex) {
9.172 - // trying to prevent java.lang.NullPointerException
9.173 - // at com.sun.tools.javac.util.DefaultFileManager.getFileForOutput(DefaultFileManager.java:1078)
9.174 - // at com.sun.tools.javac.util.DefaultFileManager.getFileForOutput(DefaultFileManager.java:1054)
9.175 - // at com.sun.tools.javac.processing.JavacFiler.getResource(JavacFiler.java:434)
9.176 - // at org.netbeans.modules.openide.util.AbstractServiceProviderProcessor.register(AbstractServiceProviderProcessor.java:163)
9.177 - // at org.netbeans.modules.openide.util.ServiceProviderProcessor.register(ServiceProviderProcessor.java:99)
9.178 - } catch (FileNotFoundException x) {
9.179 - // Good.
9.180 - }
9.181 - try {
9.182 - FileObject in = processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", rsrc);
9.183 - InputStream is = in.openInputStream();
9.184 - try {
9.185 - BufferedReader r = new BufferedReader(new InputStreamReader(is, "UTF-8"));
9.186 - String line;
9.187 - while ((line = r.readLine()) != null) {
9.188 - lines.add(line);
9.189 - }
9.190 - } finally {
9.191 - is.close();
9.192 - }
9.193 - } catch (FileNotFoundException x) {
9.194 - // OK, created for the first time
9.195 - }
9.196 - } catch (IOException x) {
9.197 - processingEnv.getMessager().printMessage(Kind.ERROR, x.toString());
9.198 - return;
9.199 - }
9.200 - outputFiles.put(rsrc, lines);
9.201 - }
9.202 - int idx = lines.indexOf(impl);
9.203 - if (idx != -1) {
9.204 - lines.remove(idx);
9.205 - while (lines.size() > idx && lines.get(idx).matches("#position=.+|#-.+")) {
9.206 - lines.remove(idx);
9.207 - }
9.208 - }
9.209 - lines.add(impl);
9.210 - if (position != Integer.MAX_VALUE) {
9.211 - lines.add("#position=" + position);
9.212 - }
9.213 - for (String exclude : supersedes) {
9.214 - lines.add("#-" + exclude);
9.215 - }
9.216 - }
9.217 -
9.218 - /**
9.219 - * @param element a source element
9.220 - * @param annotation a type of annotation
9.221 - * @return the instance of that annotation on the element, or null if not found
9.222 - */
9.223 - private AnnotationMirror findAnnotationMirror(Element element, Class<? extends Annotation> annotation) {
9.224 - for (AnnotationMirror ann : element.getAnnotationMirrors()) {
9.225 - if (processingEnv.getElementUtils().getBinaryName((TypeElement) ann.getAnnotationType().asElement()).
9.226 - contentEquals(annotation.getName())) {
9.227 - return ann;
9.228 - }
9.229 - }
9.230 - return null;
9.231 - }
9.232 -
9.233 - /**
9.234 - * @param annotation an annotation instance (null permitted)
9.235 - * @param name the name of an attribute of that annotation
9.236 - * @return the corresponding value if found
9.237 - */
9.238 - private AnnotationValue findAnnotationValue(AnnotationMirror annotation, String name) {
9.239 - if (annotation != null) {
9.240 - for (Map.Entry<? extends ExecutableElement,? extends AnnotationValue> entry : annotation.getElementValues().entrySet()) {
9.241 - if (entry.getKey().getSimpleName().contentEquals(name)) {
9.242 - return entry.getValue();
9.243 - }
9.244 - }
9.245 - }
9.246 - return null;
9.247 - }
9.248 -
9.249 - private final boolean verifyServiceProviderSignature(TypeElement clazz, Class<? extends Annotation> annotation) {
9.250 - AnnotationMirror ann = findAnnotationMirror(clazz, annotation);
9.251 - if (!clazz.getModifiers().contains(Modifier.PUBLIC)) {
9.252 - processingEnv.getMessager().printMessage(Kind.ERROR, clazz + " must be public", clazz, ann);
9.253 - return false;
9.254 - }
9.255 - if (clazz.getModifiers().contains(Modifier.ABSTRACT)) {
9.256 - processingEnv.getMessager().printMessage(Kind.ERROR, clazz + " must not be abstract", clazz, ann);
9.257 - return false;
9.258 - }
9.259 - {
9.260 - boolean hasDefaultCtor = false;
9.261 - for (ExecutableElement constructor : ElementFilter.constructorsIn(clazz.getEnclosedElements())) {
9.262 - if (constructor.getModifiers().contains(Modifier.PUBLIC) && constructor.getParameters().isEmpty()) {
9.263 - hasDefaultCtor = true;
9.264 - break;
9.265 - }
9.266 - }
9.267 - if (!hasDefaultCtor) {
9.268 - processingEnv.getMessager().printMessage(Kind.ERROR, clazz + " must have a public no-argument constructor", clazz, ann);
9.269 - return false;
9.270 - }
9.271 - }
9.272 - return true;
9.273 - }
9.274 -
9.275 - private void writeServices() {
9.276 - for (Map.Entry<ProcessingEnvironment,Map<String,List<String>>> outputFiles : outputFilesByProcessor.entrySet()) {
9.277 - for (Map.Entry<String, List<String>> entry : outputFiles.getValue().entrySet()) {
9.278 - try {
9.279 - FileObject out = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", entry.getKey(),
9.280 - originatingElementsByProcessor.get(outputFiles.getKey()).get(entry.getKey()).toArray(new Element[0]));
9.281 - OutputStream os = out.openOutputStream();
9.282 - try {
9.283 - PrintWriter w = new PrintWriter(new OutputStreamWriter(os, "UTF-8"));
9.284 - for (String line : entry.getValue()) {
9.285 - w.println(line);
9.286 - }
9.287 - w.flush();
9.288 - w.close();
9.289 - } finally {
9.290 - os.close();
9.291 - }
9.292 - } catch (IOException x) {
9.293 - processingEnv.getMessager().printMessage(Kind.ERROR, "Failed to write to " + entry.getKey() + ": " + x.toString());
9.294 - }
9.295 - }
9.296 - }
9.297 - }
9.298 -
9.299 -}
10.1 --- a/lookup/src/main/java/org/netbeans/modules/openide/util/ActiveQueue.java Wed Jan 27 17:46:23 2010 -0500
10.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
10.3 @@ -1,108 +0,0 @@
10.4 -package org.netbeans.modules.openide.util;
10.5 -
10.6 -import java.lang.ref.Reference;
10.7 -import java.lang.ref.ReferenceQueue;
10.8 -import java.util.logging.Level;
10.9 -import java.util.logging.Logger;
10.10 -
10.11 -/**
10.12 - * Implementation of the active reference queue.
10.13 - */
10.14 -public final class ActiveQueue extends ReferenceQueue<Object> implements Runnable {
10.15 -
10.16 - private static final Logger LOGGER = Logger.getLogger(ActiveQueue.class.getName().replace('$', '.'));
10.17 - private static ActiveQueue activeReferenceQueue;
10.18 -
10.19 - /** number of known outstanding references */
10.20 - private int count;
10.21 - private boolean deprecated;
10.22 -
10.23 - ActiveQueue(boolean deprecated) {
10.24 - super();
10.25 - this.deprecated = deprecated;
10.26 - }
10.27 -
10.28 - public static synchronized ReferenceQueue<Object> queue() {
10.29 - if (activeReferenceQueue == null) {
10.30 - activeReferenceQueue = new ActiveQueue(false);
10.31 - }
10.32 -
10.33 - activeReferenceQueue.ping();
10.34 -
10.35 - return activeReferenceQueue;
10.36 - }
10.37 -
10.38 - @Override
10.39 - public Reference<Object> poll() {
10.40 - throw new UnsupportedOperationException();
10.41 - }
10.42 -
10.43 - @Override
10.44 - public Reference<Object> remove(long timeout) throws IllegalArgumentException, InterruptedException {
10.45 - throw new InterruptedException();
10.46 - }
10.47 -
10.48 - @Override
10.49 - public Reference<Object> remove() throws InterruptedException {
10.50 - throw new InterruptedException();
10.51 - }
10.52 -
10.53 - public void run() {
10.54 - while (true) {
10.55 - try {
10.56 - Reference<?> ref = super.remove(0);
10.57 - LOGGER.finer("dequeued reference");
10.58 - if (!(ref instanceof Runnable)) {
10.59 - LOGGER.warning("A reference not implementing runnable has been added to the Utilities.activeReferenceQueue(): " + ref.getClass());
10.60 - continue;
10.61 - }
10.62 - if (deprecated) {
10.63 - LOGGER.warning("Utilities.ACTIVE_REFERENCE_QUEUE has been deprecated for " + ref.getClass() + " use Utilities.activeReferenceQueue");
10.64 - }
10.65 - // do the cleanup
10.66 - try {
10.67 - ((Runnable) ref).run();
10.68 - } catch (ThreadDeath td) {
10.69 - throw td;
10.70 - } catch (Throwable t) {
10.71 - // Should not happen.
10.72 - // If it happens, it is a bug in client code, notify!
10.73 - LOGGER.log(Level.WARNING, null, t);
10.74 - } finally {
10.75 - // to allow GC
10.76 - ref = null;
10.77 - }
10.78 - } catch (InterruptedException ex) {
10.79 - // Can happen during VM shutdown, it seems. Ignore.
10.80 - continue;
10.81 - }
10.82 - synchronized (this) {
10.83 - assert count > 0;
10.84 - count--;
10.85 - if (count == 0) {
10.86 - // We have processed all we have to process (for now at least).
10.87 - // Could be restarted later if ping() called again.
10.88 - // This could also happen in case someone called queue() once and tried
10.89 - // to use it for several references; in that case run() might never be called on
10.90 - // the later ones to be collected. Can't really protect against that situation.
10.91 - // See issue #86625 for details.
10.92 - LOGGER.fine("stopping thread");
10.93 - break;
10.94 - }
10.95 - }
10.96 - }
10.97 - }
10.98 -
10.99 - synchronized void ping() {
10.100 - if (count == 0) {
10.101 - Thread t = new Thread(this, "Active Reference Queue Daemon");
10.102 - t.setPriority(Thread.MIN_PRIORITY);
10.103 - t.setDaemon(true);
10.104 - t.start();
10.105 - LOGGER.fine("starting thread");
10.106 - } else {
10.107 - LOGGER.finer("enqueuing reference");
10.108 - }
10.109 - count++;
10.110 - }
10.111 -}
11.1 --- a/lookup/src/main/java/org/netbeans/modules/openide/util/NamedServicesProvider.java Wed Jan 27 17:46:23 2010 -0500
11.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
11.3 @@ -1,87 +0,0 @@
11.4 -/*
11.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
11.6 - *
11.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
11.8 - *
11.9 - * The contents of this file are subject to the terms of either the GNU
11.10 - * General Public License Version 2 only ("GPL") or the Common
11.11 - * Development and Distribution License("CDDL") (collectively, the
11.12 - * "License"). You may not use this file except in compliance with the
11.13 - * License. You can obtain a copy of the License at
11.14 - * http://www.netbeans.org/cddl-gplv2.html
11.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
11.16 - * specific language governing permissions and limitations under the
11.17 - * License. When distributing the software, include this License Header
11.18 - * Notice in each file and include the License file at
11.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
11.20 - * particular file as subject to the "Classpath" exception as provided
11.21 - * by Sun in the GPL Version 2 section of the License file that
11.22 - * accompanied this code. If applicable, add the following below the
11.23 - * License Header, with the fields enclosed by brackets [] replaced by
11.24 - * your own identifying information:
11.25 - * "Portions Copyrighted [year] [name of copyright owner]"
11.26 - *
11.27 - * Contributor(s):
11.28 - *
11.29 - * The Original Software is NetBeans. The Initial Developer of the Original
11.30 - * Software is Sun Microsystems, Inc.
11.31 - *
11.32 - * Portions Copyrighted 2006 Sun Microsystems, Inc.
11.33 - */
11.34 -
11.35 -package org.netbeans.modules.openide.util;
11.36 -
11.37 -import java.lang.ref.Reference;
11.38 -import java.lang.ref.WeakReference;
11.39 -import java.util.Collections;
11.40 -import java.util.HashMap;
11.41 -import java.util.Map;
11.42 -import org.openide.util.Lookup;
11.43 -import org.openide.util.lookup.Lookups;
11.44 -
11.45 -/** Interface for core/startup and core/settings
11.46 - * to provide lookup over system filesystem.
11.47 - *
11.48 - * @author Jaroslav Tulach
11.49 - */
11.50 -public abstract class NamedServicesProvider {
11.51 -
11.52 - private static final Map<String,Reference<Lookup>> map = Collections.synchronizedMap(new HashMap<String,Reference<Lookup>>());
11.53 -
11.54 - public abstract Lookup create(String path);
11.55 -
11.56 - public static Lookup find(String path) {
11.57 - if (!path.endsWith("/")) {
11.58 - path = path + "/";
11.59 - }
11.60 -
11.61 - Reference<Lookup> ref = map.get(path);
11.62 - Lookup lkp = ref == null ? null : ref.get();
11.63 - if (lkp != null) {
11.64 - return lkp;
11.65 - }
11.66 - NamedServicesProvider prov = Lookup.getDefault().lookup(NamedServicesProvider.class);
11.67 - if (prov != null &&
11.68 - /* avoid stack overflow during initialization */
11.69 - !path.startsWith(
11.70 - "URLStreamHandler/"
11.71 - /*URLStreamHandlerRegistrationProcessor.REGISTRATION_PREFIX*/
11.72 - )
11.73 - ) {
11.74 - lkp = prov.create(path);
11.75 - } else {
11.76 - ClassLoader l = Lookup.getDefault().lookup(ClassLoader.class);
11.77 - if (l == null) {
11.78 - l = Thread.currentThread().getContextClassLoader();
11.79 - if (l == null) {
11.80 - l = NamedServicesProvider.class.getClassLoader();
11.81 - }
11.82 - }
11.83 - lkp = Lookups.metaInfServices(l, "META-INF/namedservices/" + path);
11.84 - }
11.85 -
11.86 - map.put(path, new WeakReference<Lookup>(lkp));
11.87 - return lkp;
11.88 - }
11.89 -
11.90 -}
12.1 --- a/lookup/src/main/java/org/netbeans/modules/openide/util/ServiceProviderProcessor.java Wed Jan 27 17:46:23 2010 -0500
12.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
12.3 @@ -1,173 +0,0 @@
12.4 -/*
12.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
12.6 - *
12.7 - * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
12.8 - *
12.9 - * The contents of this file are subject to the terms of either the GNU
12.10 - * General Public License Version 2 only ("GPL") or the Common
12.11 - * Development and Distribution License("CDDL") (collectively, the
12.12 - * "License"). You may not use this file except in compliance with the
12.13 - * License. You can obtain a copy of the License at
12.14 - * http://www.netbeans.org/cddl-gplv2.html
12.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
12.16 - * specific language governing permissions and limitations under the
12.17 - * License. When distributing the software, include this License Header
12.18 - * Notice in each file and include the License file at
12.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
12.20 - * particular file as subject to the "Classpath" exception as provided
12.21 - * by Sun in the GPL Version 2 section of the License file that
12.22 - * accompanied this code. If applicable, add the following below the
12.23 - * License Header, with the fields enclosed by brackets [] replaced by
12.24 - * your own identifying information:
12.25 - * "Portions Copyrighted [year] [name of copyright owner]"
12.26 - *
12.27 - * If you wish your version of this file to be governed by only the CDDL
12.28 - * or only the GPL Version 2, indicate your decision by adding
12.29 - * "[Contributor] elects to include this software in this distribution
12.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
12.31 - * single choice of license, a recipient has the option to distribute
12.32 - * your version of this file under either the CDDL, the GPL Version 2 or
12.33 - * to extend the choice of license to its licensees as provided above.
12.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
12.35 - * Version 2 license, then the option applies only if the new code is
12.36 - * made subject to such option by the copyright holder.
12.37 - *
12.38 - * Contributor(s):
12.39 - *
12.40 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
12.41 - */
12.42 -
12.43 -package org.netbeans.modules.openide.util;
12.44 -
12.45 -import java.lang.annotation.Annotation;
12.46 -import java.util.Arrays;
12.47 -import java.util.Collection;
12.48 -import java.util.Collections;
12.49 -import java.util.HashSet;
12.50 -import java.util.LinkedList;
12.51 -import java.util.List;
12.52 -import java.util.Set;
12.53 -import javax.annotation.processing.Completion;
12.54 -import javax.annotation.processing.RoundEnvironment;
12.55 -import javax.annotation.processing.SupportedSourceVersion;
12.56 -import javax.lang.model.SourceVersion;
12.57 -import javax.lang.model.element.AnnotationMirror;
12.58 -import javax.lang.model.element.Element;
12.59 -import javax.lang.model.element.ExecutableElement;
12.60 -import javax.lang.model.element.TypeElement;
12.61 -import javax.lang.model.type.MirroredTypeException;
12.62 -import javax.lang.model.type.TypeKind;
12.63 -import javax.lang.model.type.TypeMirror;
12.64 -import org.openide.util.lookup.ServiceProvider;
12.65 -import org.openide.util.lookup.ServiceProviders;
12.66 -
12.67 -@SupportedSourceVersion(SourceVersion.RELEASE_6)
12.68 -public class ServiceProviderProcessor extends AbstractServiceProviderProcessor {
12.69 -
12.70 - public @Override Set<String> getSupportedAnnotationTypes() {
12.71 - return new HashSet<String>(Arrays.asList(
12.72 - ServiceProvider.class.getCanonicalName(),
12.73 - ServiceProviders.class.getCanonicalName()
12.74 - ));
12.75 - }
12.76 -
12.77 - /** public for ServiceLoader */
12.78 - public ServiceProviderProcessor() {}
12.79 -
12.80 - protected boolean handleProcess(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
12.81 - for (Element el : roundEnv.getElementsAnnotatedWith(ServiceProvider.class)) {
12.82 - TypeElement clazz = (TypeElement) el;
12.83 - ServiceProvider sp = clazz.getAnnotation(ServiceProvider.class);
12.84 - register(clazz, ServiceProvider.class, sp);
12.85 - }
12.86 - for (Element el : roundEnv.getElementsAnnotatedWith(ServiceProviders.class)) {
12.87 - TypeElement clazz = (TypeElement) el;
12.88 - ServiceProviders spp = clazz.getAnnotation(ServiceProviders.class);
12.89 - for (ServiceProvider sp : spp.value()) {
12.90 - register(clazz, ServiceProviders.class, sp);
12.91 - }
12.92 - }
12.93 - return true;
12.94 - }
12.95 -
12.96 - private void register(TypeElement clazz, Class<? extends Annotation> annotation, ServiceProvider svc) {
12.97 - try {
12.98 - svc.service();
12.99 - assert false;
12.100 - return;
12.101 - } catch (MirroredTypeException e) {
12.102 - register(clazz, annotation, e.getTypeMirror(), svc.path(), svc.position(), svc.supersedes());
12.103 - }
12.104 - }
12.105 -
12.106 - @Override
12.107 - public Iterable<? extends Completion> getCompletions(Element annotated, AnnotationMirror annotation, ExecutableElement attr, String userText) {
12.108 - if (processingEnv == null || annotated == null || !annotated.getKind().isClass()) {
12.109 - return Collections.emptyList();
12.110 - }
12.111 -
12.112 - if ( annotation == null
12.113 - || !"org.openide.util.lookup.ServiceProvider".contentEquals(((TypeElement) annotation.getAnnotationType().asElement()).getQualifiedName())) {
12.114 - return Collections.emptyList();
12.115 - }
12.116 -
12.117 - if (!"service".contentEquals(attr.getSimpleName())) {
12.118 - return Collections.emptyList();
12.119 - }
12.120 -
12.121 - TypeElement jlObject = processingEnv.getElementUtils().getTypeElement("java.lang.Object");
12.122 -
12.123 - if (jlObject == null) {
12.124 - return Collections.emptyList();
12.125 - }
12.126 -
12.127 - Collection<Completion> result = new LinkedList<Completion>();
12.128 - List<TypeElement> toProcess = new LinkedList<TypeElement>();
12.129 -
12.130 - toProcess.add((TypeElement) annotated);
12.131 -
12.132 - while (!toProcess.isEmpty()) {
12.133 - TypeElement c = toProcess.remove(0);
12.134 -
12.135 - result.add(new TypeCompletion(c.getQualifiedName().toString() + ".class"));
12.136 -
12.137 - List<TypeMirror> parents = new LinkedList<TypeMirror>();
12.138 -
12.139 - parents.add(c.getSuperclass());
12.140 - parents.addAll(c.getInterfaces());
12.141 -
12.142 - for (TypeMirror tm : parents) {
12.143 - if (tm == null || tm.getKind() != TypeKind.DECLARED) {
12.144 - continue;
12.145 - }
12.146 -
12.147 - TypeElement type = (TypeElement) processingEnv.getTypeUtils().asElement(tm);
12.148 -
12.149 - if (!jlObject.equals(type)) {
12.150 - toProcess.add(type);
12.151 - }
12.152 - }
12.153 - }
12.154 -
12.155 - return result;
12.156 - }
12.157 -
12.158 - private static final class TypeCompletion implements Completion {
12.159 -
12.160 - private final String type;
12.161 -
12.162 - public TypeCompletion(String type) {
12.163 - this.type = type;
12.164 - }
12.165 -
12.166 - public String getValue() {
12.167 - return type;
12.168 - }
12.169 -
12.170 - public String getMessage() {
12.171 - return null;
12.172 - }
12.173 -
12.174 - }
12.175 -
12.176 -}
13.1 --- a/lookup/src/main/java/org/openide/util/Lookup.java Wed Jan 27 17:46:23 2010 -0500
13.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
13.3 @@ -1,544 +0,0 @@
13.4 -/*
13.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
13.6 - *
13.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
13.8 - *
13.9 - * The contents of this file are subject to the terms of either the GNU
13.10 - * General Public License Version 2 only ("GPL") or the Common
13.11 - * Development and Distribution License("CDDL") (collectively, the
13.12 - * "License"). You may not use this file except in compliance with the
13.13 - * License. You can obtain a copy of the License at
13.14 - * http://www.netbeans.org/cddl-gplv2.html
13.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13.16 - * specific language governing permissions and limitations under the
13.17 - * License. When distributing the software, include this License Header
13.18 - * Notice in each file and include the License file at
13.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
13.20 - * particular file as subject to the "Classpath" exception as provided
13.21 - * by Sun in the GPL Version 2 section of the License file that
13.22 - * accompanied this code. If applicable, add the following below the
13.23 - * License Header, with the fields enclosed by brackets [] replaced by
13.24 - * your own identifying information:
13.25 - * "Portions Copyrighted [year] [name of copyright owner]"
13.26 - *
13.27 - * Contributor(s):
13.28 - *
13.29 - * The Original Software is NetBeans. The Initial Developer of the Original
13.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
13.31 - * Microsystems, Inc. All Rights Reserved.
13.32 - *
13.33 - * If you wish your version of this file to be governed by only the CDDL
13.34 - * or only the GPL Version 2, indicate your decision by adding
13.35 - * "[Contributor] elects to include this software in this distribution
13.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
13.37 - * single choice of license, a recipient has the option to distribute
13.38 - * your version of this file under either the CDDL, the GPL Version 2 or
13.39 - * to extend the choice of license to its licensees as provided above.
13.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
13.41 - * Version 2 license, then the option applies only if the new code is
13.42 - * made subject to such option by the copyright holder.
13.43 - */
13.44 -
13.45 -package org.openide.util;
13.46 -
13.47 -import java.util.ArrayList;
13.48 -import java.util.Collection;
13.49 -import java.util.Collections;
13.50 -import java.util.Iterator;
13.51 -import java.util.List;
13.52 -import java.util.Set;
13.53 -import org.openide.util.lookup.Lookups;
13.54 -import org.openide.util.lookup.ProxyLookup;
13.55 -import org.openide.util.lookup.ServiceProvider;
13.56 -
13.57 -/**
13.58 - * A general registry permitting clients to find instances of services
13.59 - * (implementation of a given interface).
13.60 - * This class is inspired by the
13.61 - * <a href="http://www.jini.org/">Jini</a>
13.62 - * registration and lookup mechanism. The difference is that the methods do
13.63 - * not throw checked exceptions (as they usually work only locally and not over the network)
13.64 - * and that the Lookup API concentrates on the lookup, not on the registration
13.65 - * (although {@link Lookup#getDefault} is strongly encouraged to support
13.66 - * {@link Lookups#metaInfServices} for registration in addition to whatever
13.67 - * else it decides to support).
13.68 - * <p>
13.69 - * For a general talk about the idea behind the lookup pattern please see
13.70 - * <UL>
13.71 - * <LI><a href="lookup/doc-files/index.html">The Solution to Communication Between Components</a>
13.72 - * page
13.73 - * <LI>the introduction to the <a href="lookup/doc-files/lookup-api.html">lookup API via
13.74 - * use cases</a>
13.75 - * <LI>the examples of <a href="lookup/doc-files/lookup-spi.html">how to write your own lookup</a>
13.76 - * </UL>
13.77 - *
13.78 - * @see org.openide.util.lookup.AbstractLookup
13.79 - * @see Lookups
13.80 - * @see LookupListener
13.81 - * @see LookupEvent
13.82 - * @author Jaroslav Tulach
13.83 - */
13.84 -public abstract class Lookup {
13.85 - /** A dummy lookup that never returns any results.
13.86 - */
13.87 - public static final Lookup EMPTY = new Empty();
13.88 -
13.89 - /** default instance */
13.90 - private static Lookup defaultLookup;
13.91 -
13.92 - /** Empty constructor for use by subclasses. */
13.93 - public Lookup() {
13.94 - }
13.95 -
13.96 - /** Static method to obtain the global lookup in the whole system.
13.97 - * The actual returned implementation can be different in different
13.98 - * systems, but the default one is based on
13.99 - * {@link org.openide.util.lookup.Lookups#metaInfServices}
13.100 - * with the context classloader of the first caller. Each system is
13.101 - * adviced to honor this and include some form of <code>metaInfServices</code>
13.102 - * implementation in the returned lookup as usage of <code>META-INF/services</code>
13.103 - * is a JDK standard.
13.104 - *
13.105 - * @return the global lookup in the system
13.106 - * @see ServiceProvider
13.107 - */
13.108 - public static synchronized Lookup getDefault() {
13.109 - if (defaultLookup != null) {
13.110 - return defaultLookup;
13.111 - }
13.112 -
13.113 - // You can specify a Lookup impl using a system property if you like.
13.114 - String className = System.getProperty("org.openide.util.Lookup" // NOI18N
13.115 - );
13.116 -
13.117 - if ("-".equals(className)) { // NOI18N
13.118 -
13.119 - // Suppress even MetaInfServicesLookup.
13.120 - return EMPTY;
13.121 - }
13.122 -
13.123 - ClassLoader l = Thread.currentThread().getContextClassLoader();
13.124 -
13.125 - try {
13.126 - if (className != null) {
13.127 - defaultLookup = (Lookup) Class.forName(className, true, l).newInstance();
13.128 -
13.129 - return defaultLookup;
13.130 - }
13.131 - } catch (Exception e) {
13.132 - // do not use ErrorManager because we are in the startup code
13.133 - // and ErrorManager might not be ready
13.134 - e.printStackTrace();
13.135 - }
13.136 -
13.137 - // OK, none specified (successfully) in a system property.
13.138 - // Try MetaInfServicesLookup as a default, which may also
13.139 - // have a org.openide.util.Lookup line specifying the lookup.
13.140 - Lookup misl = Lookups.metaInfServices(l);
13.141 - defaultLookup = misl.lookup(Lookup.class);
13.142 -
13.143 - if (defaultLookup != null) {
13.144 - return defaultLookup;
13.145 - }
13.146 -
13.147 - // You may also specify a Lookup.Provider.
13.148 - Lookup.Provider prov = misl.lookup(Lookup.Provider.class);
13.149 -
13.150 - if (prov != null) {
13.151 - defaultLookup = Lookups.proxy(prov);
13.152 -
13.153 - return defaultLookup;
13.154 - }
13.155 -
13.156 - DefLookup def = new DefLookup();
13.157 - def.init(l, misl, false);
13.158 - defaultLookup = def;
13.159 - def.init(l, misl, true);
13.160 - return defaultLookup;
13.161 - }
13.162 -
13.163 - private static final class DefLookup extends ProxyLookup {
13.164 - public DefLookup() {
13.165 - super(new Lookup[0]);
13.166 - }
13.167 -
13.168 - public void init(ClassLoader loader, Lookup metaInfLookup, boolean addPath) {
13.169 - // Had no such line, use simple impl.
13.170 - // It does however need to have ClassLoader available or many things will break.
13.171 - // Use the thread context classloader in effect now.
13.172 - Lookup clLookup = Lookups.singleton(loader);
13.173 - List<Lookup> arr = new ArrayList<Lookup>();
13.174 - arr.add(metaInfLookup);
13.175 - arr.add(clLookup);
13.176 - String paths = System.getProperty("org.openide.util.Lookup.paths"); // NOI18N
13.177 - if (addPath && paths != null) {
13.178 - for (String p : paths.split(":")) { // NOI18N
13.179 - arr.add(Lookups.forPath(p));
13.180 - }
13.181 - }
13.182 - setLookups(arr.toArray(new Lookup[0]));
13.183 - }
13.184 - }
13.185 -
13.186 - /** Called from MockServices to reset default lookup in case services change
13.187 - */
13.188 - private static void resetDefaultLookup() {
13.189 - if (defaultLookup instanceof DefLookup) {
13.190 - DefLookup def = (DefLookup)defaultLookup;
13.191 - ClassLoader l = Thread.currentThread().getContextClassLoader();
13.192 - def.init(l, Lookups.metaInfServices(l), true);
13.193 - }
13.194 - }
13.195 -
13.196 - /** Look up an object matching a given interface.
13.197 - * This is the simplest method to use.
13.198 - * If more than one object matches, the first will be returned.
13.199 - * The template class may be a class or interface; the instance is
13.200 - * guaranteed to be assignable to it.
13.201 - *
13.202 - * @param clazz class of the object we are searching for
13.203 - * @return an object implementing the given class or <code>null</code> if no such
13.204 - * implementation is found
13.205 - */
13.206 - public abstract <T> T lookup(Class<T> clazz);
13.207 -
13.208 - /** The general lookup method. Callers can get list of all instances and classes
13.209 - * that match the given <code>template</code>, request more info about
13.210 - * them in form of {@link Lookup.Item} and attach a listener to
13.211 - * this be notified about changes. The general interface does not
13.212 - * specify whether subsequent calls with the same template produce new
13.213 - * instance of the {@link Lookup.Result} or return shared instance. The
13.214 - * prefered behaviour however is to return shared one.
13.215 - *
13.216 - * @param template a template describing the services to look for
13.217 - * @return an object containing the results
13.218 - */
13.219 - public abstract <T> Result<T> lookup(Template<T> template);
13.220 -
13.221 - /** Look up the first item matching a given template.
13.222 - * Includes not only the instance but other associated information.
13.223 - * @param template the template to check
13.224 - * @return a matching item or <code>null</code>
13.225 - *
13.226 - * @since 1.8
13.227 - */
13.228 - public <T> Item<T> lookupItem(Template<T> template) {
13.229 - Result<T> res = lookup(template);
13.230 - Iterator<? extends Item<T>> it = res.allItems().iterator();
13.231 - return it.hasNext() ? it.next() : null;
13.232 - }
13.233 -
13.234 - /**
13.235 - * Find a result corresponding to a given class.
13.236 - * Equivalent to calling {@link #lookup(Lookup.Template)} but slightly more convenient.
13.237 - * Subclasses may override this method to produce the same semantics more efficiently.
13.238 - * @param clazz the supertype of the result
13.239 - * @return a live object representing instances of that type
13.240 - * @since org.openide.util 6.10
13.241 - */
13.242 - public <T> Lookup.Result<T> lookupResult(Class<T> clazz) {
13.243 - return lookup(new Lookup.Template<T>(clazz));
13.244 - }
13.245 -
13.246 - /**
13.247 - * Find all instances corresponding to a given class.
13.248 - * Equivalent to calling {@link #lookupResult} and asking for {@link Lookup.Result#allInstances} but slightly more convenient.
13.249 - * Subclasses may override this method to produce the same semantics more efficiently.
13.250 - * <div class="nonnormative">
13.251 - * <p>Example usage:</p>
13.252 - * <pre>
13.253 - * for (MyService svc : Lookup.getDefault().lookupAll(MyService.class)) {
13.254 - * svc.useMe();
13.255 - * }
13.256 - * </pre>
13.257 - * </div>
13.258 - * @param clazz the supertype of the result
13.259 - * @return all currently available instances of that type
13.260 - * @since org.openide.util 6.10
13.261 - */
13.262 - public <T> Collection<? extends T> lookupAll(Class<T> clazz) {
13.263 - return lookupResult(clazz).allInstances();
13.264 - }
13.265 -
13.266 - /**
13.267 - * Objects implementing interface Lookup.Provider are capable of
13.268 - * and willing to provide a lookup (usually bound to the object).
13.269 - * @since 3.6
13.270 - */
13.271 - public interface Provider {
13.272 - /**
13.273 - * Returns lookup associated with the object.
13.274 - * @return fully initialized lookup instance provided by this object
13.275 - */
13.276 - Lookup getLookup();
13.277 - }
13.278 -
13.279 - /*
13.280 - * I expect this class to grow in the future, but for now, it is
13.281 - * enough to start with something simple.
13.282 - */
13.283 -
13.284 - /** Template defining a pattern to filter instances by.
13.285 - */
13.286 - public static final class Template<T> extends Object {
13.287 - /** cached hash code */
13.288 - private int hashCode;
13.289 -
13.290 - /** type of the service */
13.291 - private Class<T> type;
13.292 -
13.293 - /** identity to search for */
13.294 - private String id;
13.295 -
13.296 - /** instance to search for */
13.297 - private T instance;
13.298 -
13.299 - /** General template to find all possible instances.
13.300 - * @deprecated Use <code>new Template (Object.class)</code> which
13.301 - * is going to be better typed with JDK1.5 templates and should produce
13.302 - * the same result.
13.303 - */
13.304 - @Deprecated
13.305 - public Template() {
13.306 - this(null);
13.307 - }
13.308 -
13.309 - /** Create a simple template matching by class.
13.310 - * @param type the class of service we are looking for (subclasses will match)
13.311 - */
13.312 - public Template(Class<T> type) {
13.313 - this(type, null, null);
13.314 - }
13.315 -
13.316 - /** Constructor to create new template.
13.317 - * @param type the class of service we are looking for or <code>null</code> to leave unspecified
13.318 - * @param id the ID of the item/service we are looking for or <code>null</code> to leave unspecified
13.319 - * @param instance a specific known instance to look for or <code>null</code> to leave unspecified
13.320 - */
13.321 - public Template(Class<T> type, String id, T instance) {
13.322 - this.type = extractType(type);
13.323 - this.id = id;
13.324 - this.instance = instance;
13.325 - }
13.326 -
13.327 - @SuppressWarnings("unchecked")
13.328 - private Class<T> extractType(Class<T> type) {
13.329 - return (type == null) ? (Class<T>)Object.class : type;
13.330 - }
13.331 -
13.332 - /** Get the class (or superclass or interface) to search for.
13.333 - * If it was not specified in the constructor, <code>Object</code> is used as
13.334 - * this will match any instance.
13.335 - * @return the class to search for
13.336 - */
13.337 - public Class<T> getType() {
13.338 - return type;
13.339 - }
13.340 -
13.341 - /** Get the persistent identifier being searched for, if any.
13.342 - * @return the ID or <code>null</code>
13.343 - * @see Lookup.Item#getId
13.344 - *
13.345 - * @since 1.8
13.346 - */
13.347 - public String getId() {
13.348 - return id;
13.349 - }
13.350 -
13.351 - /** Get the specific instance being searched for, if any.
13.352 - * Most useful for finding an <code>Item</code> when the instance
13.353 - * is already known.
13.354 - *
13.355 - * @return the object to find or <code>null</code>
13.356 - *
13.357 - * @since 1.8
13.358 - */
13.359 - public T getInstance() {
13.360 - return instance;
13.361 - }
13.362 -
13.363 - /* Computes hashcode for this template. The hashcode is cached.
13.364 - * @return hashcode
13.365 - */
13.366 - @Override
13.367 - public int hashCode() {
13.368 - if (hashCode != 0) {
13.369 - return hashCode;
13.370 - }
13.371 -
13.372 - hashCode = ((type == null) ? 1 : type.hashCode()) + ((id == null) ? 2 : id.hashCode()) +
13.373 - ((instance == null) ? 3 : 0);
13.374 -
13.375 - return hashCode;
13.376 - }
13.377 -
13.378 - /* Checks whether two templates represent the same query.
13.379 - * @param obj another template to check
13.380 - * @return true if so, false otherwise
13.381 - */
13.382 - @Override
13.383 - public boolean equals(Object obj) {
13.384 - if (!(obj instanceof Template)) {
13.385 - return false;
13.386 - }
13.387 -
13.388 - Template t = (Template) obj;
13.389 -
13.390 - if (hashCode() != t.hashCode()) {
13.391 - // this is an optimalization - the hashCodes should have been
13.392 - // precomputed
13.393 - return false;
13.394 - }
13.395 -
13.396 - if (type != t.type) {
13.397 - return false;
13.398 - }
13.399 -
13.400 - if (id == null) {
13.401 - if (t.id != null) {
13.402 - return false;
13.403 - }
13.404 - } else {
13.405 - if (!id.equals(t.id)) {
13.406 - return false;
13.407 - }
13.408 - }
13.409 -
13.410 - if (instance == null) {
13.411 - return (t.instance == null);
13.412 - } else {
13.413 - return instance.equals(t.instance);
13.414 - }
13.415 - }
13.416 -
13.417 - /* for debugging */
13.418 - @Override
13.419 - public String toString() {
13.420 - return "Lookup.Template[type=" + type + ",id=" + id + ",instance=" + instance + "]"; // NOI18N
13.421 - }
13.422 - }
13.423 -
13.424 - /** Result of a lookup request.
13.425 - * Allows access to all matching instances at once.
13.426 - * Also permits listening to changes in the result.
13.427 - * Result can contain duplicate items.
13.428 - */
13.429 - public static abstract class Result<T> extends Object {
13.430 - /** Registers a listener that is invoked when there is a possible
13.431 - * change in this result.
13.432 - *
13.433 - * @param l the listener to add
13.434 - */
13.435 - public abstract void addLookupListener(LookupListener l);
13.436 -
13.437 - /** Unregisters a listener previously added.
13.438 - * @param l the listener to remove
13.439 - */
13.440 - public abstract void removeLookupListener(LookupListener l);
13.441 -
13.442 - /** Get all instances in the result. The return value type
13.443 - * should be List instead of Collection, but it is too late to change it.
13.444 - * @return unmodifiable collection of all instances that will never change its content
13.445 - */
13.446 - public abstract Collection<? extends T> allInstances();
13.447 -
13.448 - /** Get all classes represented in the result.
13.449 - * That is, the set of concrete classes
13.450 - * used by instances present in the result.
13.451 - * All duplicate classes will be omitted.
13.452 - * @return unmodifiable set of <code>Class</code> objects that will never change its content
13.453 - *
13.454 - * @since 1.8
13.455 - */
13.456 - public Set<Class<? extends T>> allClasses() {
13.457 - return Collections.emptySet();
13.458 - }
13.459 -
13.460 - /** Get all registered items.
13.461 - * This should include all pairs of instances together
13.462 - * with their classes, IDs, and so on. The return value type
13.463 - * should be List instead of Collection, but it is too late to change it.
13.464 - * @return unmodifiable collection of {@link Lookup.Item} that will never change its content
13.465 - *
13.466 - * @since 1.8
13.467 - */
13.468 - public Collection<? extends Item<T>> allItems() {
13.469 - return Collections.emptyList();
13.470 - }
13.471 - }
13.472 -
13.473 - /** A single item in a lookup result.
13.474 - * This wrapper provides unified access to not just the instance,
13.475 - * but its class, a possible persistent identifier, and so on.
13.476 - *
13.477 - * @since 1.25
13.478 - */
13.479 - public static abstract class Item<T> extends Object {
13.480 - /** Get the instance itself.
13.481 - * @return the instance or null if the instance cannot be created
13.482 - */
13.483 - public abstract T getInstance();
13.484 -
13.485 - /** Get the implementing class of the instance.
13.486 - * @return the class of the item
13.487 - */
13.488 - public abstract Class<? extends T> getType();
13.489 -
13.490 - // XXX can it be null??
13.491 -
13.492 - /** Get a persistent indentifier for the item.
13.493 - * This identifier should uniquely represent the item
13.494 - * within its containing lookup (and if possible within the
13.495 - * global lookup as a whole). For example, it might represent
13.496 - * the source of the instance as a file name. The ID may be
13.497 - * persisted and in a later session used to find the same instance
13.498 - * as was encountered earlier, by means of passing it into a
13.499 - * lookup template.
13.500 - *
13.501 - * @return a string ID of the item
13.502 - */
13.503 - public abstract String getId();
13.504 -
13.505 - /** Get a human presentable name for the item.
13.506 - * This might be used when summarizing all the items found in a
13.507 - * lookup result in some part of a GUI.
13.508 - * @return the string suitable for presenting the object to a user
13.509 - */
13.510 - public abstract String getDisplayName();
13.511 -
13.512 - /* show ID for debugging */
13.513 - @Override
13.514 - public String toString() {
13.515 - return getId();
13.516 - }
13.517 - }
13.518 -
13.519 - //
13.520 - // Implementation of the default lookup
13.521 - //
13.522 - private static final class Empty extends Lookup {
13.523 - private static final Result NO_RESULT = new Result() {
13.524 - public void addLookupListener(LookupListener l) {
13.525 - }
13.526 -
13.527 - public void removeLookupListener(LookupListener l) {
13.528 - }
13.529 -
13.530 - public Collection allInstances() {
13.531 - return Collections.EMPTY_SET;
13.532 - }
13.533 - };
13.534 -
13.535 - Empty() {
13.536 - }
13.537 -
13.538 - public <T> T lookup(Class<T> clazz) {
13.539 - return null;
13.540 - }
13.541 -
13.542 - @SuppressWarnings("unchecked")
13.543 - public <T> Result<T> lookup(Template<T> template) {
13.544 - return NO_RESULT;
13.545 - }
13.546 - }
13.547 -}
14.1 --- a/lookup/src/main/java/org/openide/util/LookupEvent.java Wed Jan 27 17:46:23 2010 -0500
14.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
14.3 @@ -1,57 +0,0 @@
14.4 -/*
14.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
14.6 - *
14.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
14.8 - *
14.9 - * The contents of this file are subject to the terms of either the GNU
14.10 - * General Public License Version 2 only ("GPL") or the Common
14.11 - * Development and Distribution License("CDDL") (collectively, the
14.12 - * "License"). You may not use this file except in compliance with the
14.13 - * License. You can obtain a copy of the License at
14.14 - * http://www.netbeans.org/cddl-gplv2.html
14.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
14.16 - * specific language governing permissions and limitations under the
14.17 - * License. When distributing the software, include this License Header
14.18 - * Notice in each file and include the License file at
14.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
14.20 - * particular file as subject to the "Classpath" exception as provided
14.21 - * by Sun in the GPL Version 2 section of the License file that
14.22 - * accompanied this code. If applicable, add the following below the
14.23 - * License Header, with the fields enclosed by brackets [] replaced by
14.24 - * your own identifying information:
14.25 - * "Portions Copyrighted [year] [name of copyright owner]"
14.26 - *
14.27 - * Contributor(s):
14.28 - *
14.29 - * The Original Software is NetBeans. The Initial Developer of the Original
14.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
14.31 - * Microsystems, Inc. All Rights Reserved.
14.32 - *
14.33 - * If you wish your version of this file to be governed by only the CDDL
14.34 - * or only the GPL Version 2, indicate your decision by adding
14.35 - * "[Contributor] elects to include this software in this distribution
14.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
14.37 - * single choice of license, a recipient has the option to distribute
14.38 - * your version of this file under either the CDDL, the GPL Version 2 or
14.39 - * to extend the choice of license to its licensees as provided above.
14.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
14.41 - * Version 2 license, then the option applies only if the new code is
14.42 - * made subject to such option by the copyright holder.
14.43 - */
14.44 -package org.openide.util;
14.45 -
14.46 -import java.util.*;
14.47 -
14.48 -
14.49 -/** An event describing the change in the lookup's result.
14.50 - *
14.51 - * @author Jaroslav Tulach
14.52 - */
14.53 -public final class LookupEvent extends EventObject {
14.54 - /** Create a new lookup event.
14.55 - * @param source the lookup result which has changed
14.56 - */
14.57 - public LookupEvent(Lookup.Result source) {
14.58 - super(source);
14.59 - }
14.60 -}
15.1 --- a/lookup/src/main/java/org/openide/util/LookupListener.java Wed Jan 27 17:46:23 2010 -0500
15.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
15.3 @@ -1,59 +0,0 @@
15.4 -/*
15.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
15.6 - *
15.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
15.8 - *
15.9 - * The contents of this file are subject to the terms of either the GNU
15.10 - * General Public License Version 2 only ("GPL") or the Common
15.11 - * Development and Distribution License("CDDL") (collectively, the
15.12 - * "License"). You may not use this file except in compliance with the
15.13 - * License. You can obtain a copy of the License at
15.14 - * http://www.netbeans.org/cddl-gplv2.html
15.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
15.16 - * specific language governing permissions and limitations under the
15.17 - * License. When distributing the software, include this License Header
15.18 - * Notice in each file and include the License file at
15.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
15.20 - * particular file as subject to the "Classpath" exception as provided
15.21 - * by Sun in the GPL Version 2 section of the License file that
15.22 - * accompanied this code. If applicable, add the following below the
15.23 - * License Header, with the fields enclosed by brackets [] replaced by
15.24 - * your own identifying information:
15.25 - * "Portions Copyrighted [year] [name of copyright owner]"
15.26 - *
15.27 - * Contributor(s):
15.28 - *
15.29 - * The Original Software is NetBeans. The Initial Developer of the Original
15.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
15.31 - * Microsystems, Inc. All Rights Reserved.
15.32 - *
15.33 - * If you wish your version of this file to be governed by only the CDDL
15.34 - * or only the GPL Version 2, indicate your decision by adding
15.35 - * "[Contributor] elects to include this software in this distribution
15.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
15.37 - * single choice of license, a recipient has the option to distribute
15.38 - * your version of this file under either the CDDL, the GPL Version 2 or
15.39 - * to extend the choice of license to its licensees as provided above.
15.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
15.41 - * Version 2 license, then the option applies only if the new code is
15.42 - * made subject to such option by the copyright holder.
15.43 - */
15.44 -package org.openide.util;
15.45 -
15.46 -import java.util.*;
15.47 -
15.48 -
15.49 -/** General listener for changes in lookup.
15.50 - *
15.51 - * @author Jaroslav Tulach
15.52 - */
15.53 -public interface LookupListener extends EventListener {
15.54 - /** A change in lookup occured. Please note that this method
15.55 - * should never block since it might be called from lookup implementation
15.56 - * internal threads. If you block here you are in risk that the thread
15.57 - * you wait for might in turn to wait for the lookup internal thread to
15.58 - * finish its work.
15.59 - * @param ev event describing the change
15.60 - */
15.61 - public void resultChanged(LookupEvent ev);
15.62 -}
16.1 --- a/lookup/src/main/java/org/openide/util/lookup/ALPairComparator.java Wed Jan 27 17:46:23 2010 -0500
16.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
16.3 @@ -1,88 +0,0 @@
16.4 -/*
16.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
16.6 - *
16.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
16.8 - *
16.9 - * The contents of this file are subject to the terms of either the GNU
16.10 - * General Public License Version 2 only ("GPL") or the Common
16.11 - * Development and Distribution License("CDDL") (collectively, the
16.12 - * "License"). You may not use this file except in compliance with the
16.13 - * License. You can obtain a copy of the License at
16.14 - * http://www.netbeans.org/cddl-gplv2.html
16.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16.16 - * specific language governing permissions and limitations under the
16.17 - * License. When distributing the software, include this License Header
16.18 - * Notice in each file and include the License file at
16.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
16.20 - * particular file as subject to the "Classpath" exception as provided
16.21 - * by Sun in the GPL Version 2 section of the License file that
16.22 - * accompanied this code. If applicable, add the following below the
16.23 - * License Header, with the fields enclosed by brackets [] replaced by
16.24 - * your own identifying information:
16.25 - * "Portions Copyrighted [year] [name of copyright owner]"
16.26 - *
16.27 - * Contributor(s):
16.28 - *
16.29 - * The Original Software is NetBeans. The Initial Developer of the Original
16.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
16.31 - * Microsystems, Inc. All Rights Reserved.
16.32 - *
16.33 - * If you wish your version of this file to be governed by only the CDDL
16.34 - * or only the GPL Version 2, indicate your decision by adding
16.35 - * "[Contributor] elects to include this software in this distribution
16.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
16.37 - * single choice of license, a recipient has the option to distribute
16.38 - * your version of this file under either the CDDL, the GPL Version 2 or
16.39 - * to extend the choice of license to its licensees as provided above.
16.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
16.41 - * Version 2 license, then the option applies only if the new code is
16.42 - * made subject to such option by the copyright holder.
16.43 - */
16.44 -package org.openide.util.lookup;
16.45 -
16.46 -import java.util.Comparator;
16.47 -import org.openide.util.lookup.AbstractLookup.Pair;
16.48 -
16.49 -
16.50 -/** Implementation of comparator for AbstractLookup.Pair
16.51 - *
16.52 - * @author Jaroslav Tulach
16.53 - */
16.54 -final class ALPairComparator implements Comparator<Pair<?>> {
16.55 - public static final Comparator<Pair<?>> DEFAULT = new ALPairComparator();
16.56 -
16.57 - /** Creates a new instance of ALPairComparator */
16.58 - private ALPairComparator() {
16.59 - }
16.60 -
16.61 - /** Compares two items.
16.62 - */
16.63 - public int compare(Pair<?> i1, Pair<?> i2) {
16.64 - int result = i1.getIndex() - i2.getIndex();
16.65 -
16.66 - if (result == 0) {
16.67 - if (i1 != i2) {
16.68 - java.io.ByteArrayOutputStream bs = new java.io.ByteArrayOutputStream();
16.69 - java.io.PrintStream ps = new java.io.PrintStream(bs);
16.70 -
16.71 - ps.println(
16.72 - "Duplicate pair in tree" + // NOI18N
16.73 - "Pair1: " + i1 + " pair2: " + i2 + " index1: " + i1.getIndex() + " index2: " +
16.74 - i2.getIndex() // NOI18N
16.75 - +" item1: " + i1.getInstance() + " item2: " + i2.getInstance() // NOI18N
16.76 - +" id1: " + Integer.toHexString(System.identityHashCode(i1)) // NOI18N
16.77 - +" id2: " + Integer.toHexString(System.identityHashCode(i2)) // NOI18N
16.78 - );
16.79 -
16.80 - // print (ps, false);
16.81 - ps.close();
16.82 -
16.83 - throw new IllegalStateException(bs.toString());
16.84 - }
16.85 -
16.86 - return 0;
16.87 - }
16.88 -
16.89 - return result;
16.90 - }
16.91 -}
17.1 --- a/lookup/src/main/java/org/openide/util/lookup/AbstractLookup.java Wed Jan 27 17:46:23 2010 -0500
17.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
17.3 @@ -1,1467 +0,0 @@
17.4 -/*
17.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
17.6 - *
17.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
17.8 - *
17.9 - * The contents of this file are subject to the terms of either the GNU
17.10 - * General Public License Version 2 only ("GPL") or the Common
17.11 - * Development and Distribution License("CDDL") (collectively, the
17.12 - * "License"). You may not use this file except in compliance with the
17.13 - * License. You can obtain a copy of the License at
17.14 - * http://www.netbeans.org/cddl-gplv2.html
17.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
17.16 - * specific language governing permissions and limitations under the
17.17 - * License. When distributing the software, include this License Header
17.18 - * Notice in each file and include the License file at
17.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17.20 - * particular file as subject to the "Classpath" exception as provided
17.21 - * by Sun in the GPL Version 2 section of the License file that
17.22 - * accompanied this code. If applicable, add the following below the
17.23 - * License Header, with the fields enclosed by brackets [] replaced by
17.24 - * your own identifying information:
17.25 - * "Portions Copyrighted [year] [name of copyright owner]"
17.26 - *
17.27 - * Contributor(s):
17.28 - *
17.29 - * The Original Software is NetBeans. The Initial Developer of the Original
17.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17.31 - * Microsystems, Inc. All Rights Reserved.
17.32 - *
17.33 - * If you wish your version of this file to be governed by only the CDDL
17.34 - * or only the GPL Version 2, indicate your decision by adding
17.35 - * "[Contributor] elects to include this software in this distribution
17.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
17.37 - * single choice of license, a recipient has the option to distribute
17.38 - * your version of this file under either the CDDL, the GPL Version 2 or
17.39 - * to extend the choice of license to its licensees as provided above.
17.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
17.41 - * Version 2 license, then the option applies only if the new code is
17.42 - * made subject to such option by the copyright holder.
17.43 - */
17.44 -package org.openide.util.lookup;
17.45 -
17.46 -import java.io.PrintStream;
17.47 -import org.openide.util.Lookup;
17.48 -import org.openide.util.LookupEvent;
17.49 -import org.openide.util.LookupListener;
17.50 -
17.51 -import java.io.IOException;
17.52 -import java.io.ObjectOutputStream;
17.53 -import java.io.Serializable;
17.54 -
17.55 -import java.lang.ref.ReferenceQueue;
17.56 -import java.lang.ref.WeakReference;
17.57 -import java.util.ArrayList;
17.58 -import java.util.Arrays;
17.59 -import java.util.Collection;
17.60 -import java.util.Collections;
17.61 -import java.util.Enumeration;
17.62 -import java.util.HashMap;
17.63 -import java.util.HashSet;
17.64 -import java.util.Iterator;
17.65 -import java.util.LinkedHashSet;
17.66 -import java.util.Map;
17.67 -import java.util.Set;
17.68 -import java.util.TreeSet;
17.69 -
17.70 -import java.util.concurrent.Executor;
17.71 -import org.netbeans.modules.openide.util.ActiveQueue;
17.72 -
17.73 -
17.74 -/** Implementation of the lookup from OpenAPIs that is based on the
17.75 - * introduction of Item. This class should provide the default way
17.76 - * of how to store (Class, Object) pairs in the lookups. It offers
17.77 - * protected methods for subclasses to register the pairs.
17.78 - * <p>Serializable since 3.27.
17.79 - * @author Jaroslav Tulach
17.80 - * @since 1.9
17.81 - */
17.82 -public class AbstractLookup extends Lookup implements Serializable {
17.83 - static final long serialVersionUID = 5L;
17.84 -
17.85 - /** lock for initialization of the maps of lookups */
17.86 - private static final Object treeLock = new Object();
17.87 -
17.88 - /** the tree that registers all items (or Integer as a treshold size) */
17.89 - private Object tree;
17.90 -
17.91 - /** count of items in to lookup */
17.92 - private int count;
17.93 -
17.94 - /** Constructor to create this lookup and associate it with given
17.95 - * Content. The content than allows the creator to invoke protected
17.96 - * methods which are not accessible for any other user of the lookup.
17.97 - *
17.98 - * @param content the content to assciate with
17.99 - *
17.100 - * @since 1.25
17.101 - */
17.102 - public AbstractLookup(Content content) {
17.103 - content.attach(this);
17.104 - }
17.105 -
17.106 - /** Constructor for testing purposes that allows specification of storage
17.107 - * as mechanism as well.
17.108 - */
17.109 - AbstractLookup(Content content, Storage<?> storage) {
17.110 - this(content);
17.111 - this.tree = storage;
17.112 - initialize();
17.113 - }
17.114 -
17.115 - /** Constructor for testing purposes that allows specification of storage
17.116 - * as mechanism as well.
17.117 - * @param trashhold number of Pair to "remain small"
17.118 - */
17.119 - AbstractLookup(Content content, Integer trashhold) {
17.120 - this(content);
17.121 - this.tree = trashhold;
17.122 - }
17.123 -
17.124 - /** Default constructor for subclasses that do not need to provide a content
17.125 - */
17.126 - protected AbstractLookup() {
17.127 - }
17.128 -
17.129 - @Override
17.130 - public String toString() {
17.131 - if (tree instanceof Storage) {
17.132 - return "AbstractLookup" + lookup(new Lookup.Template<Object>(Object.class)).allItems(); // NOI18N
17.133 - } else {
17.134 - return super.toString();
17.135 - }
17.136 - }
17.137 -
17.138 - /** Entres the storage management system.
17.139 - */
17.140 - @SuppressWarnings("unchecked")
17.141 - private <T> AbstractLookup.Storage<T> enterStorage() {
17.142 - for (;;) {
17.143 - synchronized (treeLock) {
17.144 - if (tree instanceof AbstractLookup.Storage) {
17.145 - if (tree instanceof DelegatingStorage) {
17.146 - // somebody is using the lookup right now
17.147 - DelegatingStorage del = (DelegatingStorage) tree;
17.148 -
17.149 - // check whether there is not access from the same
17.150 - // thread (can throw exception)
17.151 - del.checkForTreeModification();
17.152 -
17.153 - try {
17.154 - treeLock.wait();
17.155 - } catch (InterruptedException ex) {
17.156 - // ignore and go on
17.157 - }
17.158 -
17.159 - continue;
17.160 - } else {
17.161 - // ok, tree is initialized and nobody is using it yet
17.162 - tree = new DelegatingStorage((Storage<T>) tree);
17.163 -
17.164 - return (Storage<T>) tree;
17.165 - }
17.166 - }
17.167 -
17.168 - // first time initialization of the tree
17.169 - if (tree instanceof Integer) {
17.170 - tree = new ArrayStorage((Integer) tree);
17.171 - } else {
17.172 - tree = new ArrayStorage();
17.173 - }
17.174 - }
17.175 -
17.176 - // the tree has not yet been initilized, initialize and go on again
17.177 - initialize();
17.178 - }
17.179 - }
17.180 -
17.181 - /** Exists tree ownership.
17.182 - */
17.183 - private AbstractLookup.Storage exitStorage() {
17.184 - synchronized (treeLock) {
17.185 - AbstractLookup.Storage stor = ((DelegatingStorage) tree).exitDelegate();
17.186 - tree = stor;
17.187 - treeLock.notifyAll();
17.188 -
17.189 - return stor;
17.190 - }
17.191 - }
17.192 -
17.193 - /** Method for subclasses to initialize them selves.
17.194 - */
17.195 - protected void initialize() {
17.196 - }
17.197 -
17.198 - /** Notifies subclasses that a query is about to be processed.
17.199 - * @param template the template
17.200 - */
17.201 - protected void beforeLookup(Template<?> template) {
17.202 - }
17.203 -
17.204 - /** The method to add instance to the lookup with.
17.205 - * @param pair class/instance pair
17.206 - */
17.207 - protected final void addPair(Pair<?> pair) {
17.208 - addPairImpl(pair, null);
17.209 - }
17.210 -
17.211 - /** The method to add instance to the lookup with.
17.212 - * @param pair class/instance pair
17.213 - * @param notifyIn the executor that will handle the notification of events
17.214 - * @since 7.16
17.215 - */
17.216 - protected final void addPair(Pair<?> pair, Executor notifyIn) {
17.217 - addPairImpl(pair, notifyIn);
17.218 - }
17.219 -
17.220 - private final <Transaction> void addPairImpl(Pair<?> pair, Executor notifyIn) {
17.221 - HashSet<R> toNotify = new HashSet<R>();
17.222 -
17.223 - AbstractLookup.Storage<Transaction> t = enterStorage();
17.224 - Transaction transaction = null;
17.225 -
17.226 - try {
17.227 - transaction = t.beginTransaction(-2);
17.228 -
17.229 - if (t.add(pair, transaction)) {
17.230 - try {
17.231 - pair.setIndex(t, count++);
17.232 - } catch (IllegalStateException ex) {
17.233 - // remove the pair
17.234 - t.remove(pair, transaction);
17.235 -
17.236 - // rethrow the exception
17.237 - throw ex;
17.238 - }
17.239 -
17.240 - // if the pair is newly added and was not there before
17.241 - t.endTransaction(transaction, toNotify);
17.242 - } else {
17.243 - // just finish the process by calling endTransaction
17.244 - t.endTransaction(transaction, new HashSet<R>());
17.245 - }
17.246 - } finally {
17.247 - exitStorage();
17.248 - }
17.249 -
17.250 - notifyIn(notifyIn, toNotify);
17.251 - }
17.252 -
17.253 - /** Remove instance.
17.254 - * @param pair class/instance pair
17.255 - */
17.256 - protected final void removePair(Pair<?> pair) {
17.257 - removePairImpl(pair, null);
17.258 - }
17.259 - /** Remove instance.
17.260 - * @param pair class/instance pair
17.261 - * @param notifyIn the executor that will handle the notification of events
17.262 - * @since 7.16
17.263 - */
17.264 - protected final void removePair(Pair<?> pair, Executor notifyIn) {
17.265 - removePairImpl(pair, notifyIn);
17.266 - }
17.267 -
17.268 - private <Transaction> void removePairImpl(Pair<?> pair, Executor notifyIn) {
17.269 - HashSet<R> toNotify = new HashSet<R>();
17.270 -
17.271 - AbstractLookup.Storage<Transaction> t = enterStorage();
17.272 - Transaction transaction = null;
17.273 -
17.274 - try {
17.275 - transaction = t.beginTransaction(-1);
17.276 - t.remove(pair, transaction);
17.277 - t.endTransaction(transaction, toNotify);
17.278 - } finally {
17.279 - exitStorage();
17.280 - }
17.281 -
17.282 - notifyIn(notifyIn, toNotify);
17.283 - }
17.284 -
17.285 - /** Changes all pairs in the lookup to new values.
17.286 - * @param collection the collection of (Pair) objects
17.287 - */
17.288 - protected final void setPairs(Collection<? extends Pair> collection) {
17.289 - setPairs(collection, null);
17.290 - }
17.291 -
17.292 - /** Changes all pairs in the lookup to new values, notifies listeners
17.293 - * using provided executor.
17.294 - *
17.295 - * @param collection the collection of (Pair) objects
17.296 - * @param notifyIn the executor that will handle the notification of events
17.297 - * @since 7.16
17.298 - */
17.299 - protected final void setPairs(Collection<? extends Pair> collection, Executor notifyIn) {
17.300 - HashSet<R> listeners = setPairsAndCollectListeners(collection);
17.301 - notifyIn(notifyIn, listeners);
17.302 - }
17.303 -
17.304 - private final void notifyIn(Executor notifyIn, final HashSet<R> listeners) {
17.305 - NotifyListeners notify = new NotifyListeners(listeners);
17.306 - if (notify.shallRun()) {
17.307 - if (notifyIn == null) {
17.308 - notify.run();
17.309 - } else {
17.310 - notifyIn.execute(notify);
17.311 - }
17.312 - }
17.313 - }
17.314 -
17.315 - /** Getter for set of pairs. Package private contract with MetaInfServicesLookup.
17.316 - * @return a LinkedHashSet that can be modified
17.317 - */
17.318 - final LinkedHashSet<Pair<?>> getPairsAsLHS() {
17.319 - AbstractLookup.Storage<?> t = enterStorage();
17.320 -
17.321 - try {
17.322 - Enumeration<Pair<Object>> en = t.lookup(Object.class);
17.323 - TreeSet<Pair<?>> arr = new TreeSet<Pair<?>>(ALPairComparator.DEFAULT);
17.324 - while (en.hasMoreElements()) {
17.325 - Pair<Object> item = en.nextElement();
17.326 - arr.add(item);
17.327 - }
17.328 - return new LinkedHashSet<Pair<?>>(arr);
17.329 - } finally {
17.330 - exitStorage();
17.331 - }
17.332 - }
17.333 -
17.334 - /** Collects listeners without notification. Needed in MetaInfServicesLookup
17.335 - * right now, but maybe will become an API later.
17.336 - */
17.337 - final <Transaction> HashSet<R> setPairsAndCollectListeners(Collection<? extends Pair> collection) {
17.338 - HashSet<R> toNotify = new HashSet<R>(27);
17.339 -
17.340 - AbstractLookup.Storage<Transaction> t = enterStorage();
17.341 - Transaction transaction = null;
17.342 -
17.343 - try {
17.344 - // map between the Items and their indexes (Integer)
17.345 - HashMap<Item<?>,Info> shouldBeThere = new HashMap<Item<?>,Info>(collection.size() * 2);
17.346 -
17.347 - count = 0;
17.348 -
17.349 - Iterator it = collection.iterator();
17.350 - transaction = t.beginTransaction(collection.size());
17.351 -
17.352 - while (it.hasNext()) {
17.353 - Pair item = (Pair) it.next();
17.354 -
17.355 - if (t.add(item, transaction)) {
17.356 - // the item has not been there yet
17.357 - //t.endTransaction(transaction, toNotify);
17.358 - }
17.359 -
17.360 - // remeber the item, because it should not be removed
17.361 - shouldBeThere.put(item, new Info(count++, transaction));
17.362 -
17.363 - // arr.clear ();
17.364 - }
17.365 -
17.366 - // Object transaction = t.beginTransaction ();
17.367 - // deletes all objects that should not be there and
17.368 - t.retainAll(shouldBeThere, transaction);
17.369 -
17.370 - // collect listeners
17.371 - t.endTransaction(transaction, toNotify);
17.372 -
17.373 - /*
17.374 - // check consistency
17.375 - Enumeration en = t.lookup (java.lang.Object.class);
17.376 - boolean[] max = new boolean[count];
17.377 - int mistake = -1;
17.378 - while (en.hasMoreElements ()) {
17.379 - Pair item = (Pair)en.nextElement ();
17.380 -
17.381 - if (max[item.index]) {
17.382 - mistake = item.index;
17.383 - }
17.384 - max[item.index] = true;
17.385 - }
17.386 -
17.387 - if (mistake != -1) {
17.388 - System.err.println ("Mistake at: " + mistake);
17.389 - tree.print (System.err, true);
17.390 - }
17.391 - */
17.392 - } finally {
17.393 - exitStorage();
17.394 - }
17.395 -
17.396 - return toNotify;
17.397 - }
17.398 -
17.399 - private final void writeObject(ObjectOutputStream oos)
17.400 - throws IOException {
17.401 - AbstractLookup.Storage s = enterStorage();
17.402 -
17.403 - try {
17.404 - // #36830: Serializing only InheritanceTree no ArrayStorage
17.405 - s.beginTransaction(Integer.MAX_VALUE);
17.406 -
17.407 - // #32040: don't write half-made changes
17.408 - oos.defaultWriteObject();
17.409 - } finally {
17.410 - exitStorage();
17.411 - }
17.412 - }
17.413 -
17.414 - public final <T> T lookup(Class<T> clazz) {
17.415 - Lookup.Item<T> item = lookupItem(new Lookup.Template<T>(clazz));
17.416 - return (item == null) ? null : item.getInstance();
17.417 - }
17.418 -
17.419 - @Override
17.420 - public final <T> Lookup.Item<T> lookupItem(Lookup.Template<T> template) {
17.421 - AbstractLookup.this.beforeLookup(template);
17.422 -
17.423 - ArrayList<Pair<T>> list = null;
17.424 - AbstractLookup.Storage<?> t = enterStorage();
17.425 -
17.426 - try {
17.427 - Enumeration<Pair<T>> en;
17.428 -
17.429 - try {
17.430 - en = t.lookup(template.getType());
17.431 -
17.432 - return findSmallest(en, template, false);
17.433 - } catch (AbstractLookup.ISE ex) {
17.434 - // not possible to enumerate the exception, ok, copy it
17.435 - // to create new
17.436 - list = new ArrayList<Pair<T>>();
17.437 - en = t.lookup(null); // this should get all the items without any checks
17.438 -
17.439 - // the checks will be done out side of the storage
17.440 - while (en.hasMoreElements()) {
17.441 - list.add(en.nextElement());
17.442 - }
17.443 - }
17.444 - } finally {
17.445 - exitStorage();
17.446 - }
17.447 -
17.448 - return findSmallest(Collections.enumeration(list), template, true);
17.449 - }
17.450 -
17.451 - private static <T> Pair<T> findSmallest(Enumeration<Pair<T>> en, Lookup.Template<T> template, boolean deepCheck) {
17.452 - int smallest = InheritanceTree.unsorted(en) ? Integer.MAX_VALUE : Integer.MIN_VALUE;
17.453 - Pair<T> res = null;
17.454 -
17.455 - while (en.hasMoreElements()) {
17.456 - Pair<T> item = en.nextElement();
17.457 -
17.458 - if (matches(template, item, deepCheck)) {
17.459 - if (smallest == Integer.MIN_VALUE) {
17.460 - // ok, sorted enumeration the first that matches is fine
17.461 - return item;
17.462 - } else {
17.463 - // check for the smallest item
17.464 - if (smallest > item.getIndex()) {
17.465 - smallest = item.getIndex();
17.466 - res = item;
17.467 - }
17.468 - }
17.469 - }
17.470 - }
17.471 -
17.472 - return res;
17.473 - }
17.474 -
17.475 - public final <T> Lookup.Result<T> lookup(Lookup.Template<T> template) {
17.476 - for (;;) {
17.477 - AbstractLookup.ISE toRun = null;
17.478 -
17.479 - AbstractLookup.Storage<?> t = enterStorage();
17.480 -
17.481 - try {
17.482 - R<T> r = new R<T>();
17.483 - ReferenceToResult<T> newRef = new ReferenceToResult<T>(r, this, template);
17.484 - newRef.next = t.registerReferenceToResult(newRef);
17.485 -
17.486 - return r;
17.487 - } catch (AbstractLookup.ISE ex) {
17.488 - toRun = ex;
17.489 - } finally {
17.490 - exitStorage();
17.491 - }
17.492 -
17.493 - toRun.recover(this);
17.494 -
17.495 - // and try again
17.496 - }
17.497 - }
17.498 -
17.499 - /** Notifies listeners.
17.500 - * @param allAffectedResults set of R
17.501 - */
17.502 - static final class NotifyListeners implements Runnable {
17.503 - private final ArrayList<Object> evAndListeners;
17.504 -
17.505 - public NotifyListeners(Set<R> allAffectedResults) {
17.506 - if (allAffectedResults.isEmpty()) {
17.507 - evAndListeners = null;
17.508 - return;
17.509 - }
17.510 -
17.511 - evAndListeners = new ArrayList<Object>();
17.512 - {
17.513 - for (R<?> result : allAffectedResults) {
17.514 - result.collectFires(evAndListeners);
17.515 - }
17.516 - }
17.517 - }
17.518 -
17.519 - public boolean shallRun() {
17.520 - return evAndListeners != null && !evAndListeners.isEmpty();
17.521 - }
17.522 -
17.523 - public void run() {
17.524 - Iterator it = evAndListeners.iterator();
17.525 - while (it.hasNext()) {
17.526 - LookupEvent ev = (LookupEvent)it.next();
17.527 - LookupListener l = (LookupListener)it.next();
17.528 - l.resultChanged(ev);
17.529 - }
17.530 - }
17.531 - }
17.532 -
17.533 - /**
17.534 - * Call resultChanged on all listeners.
17.535 - * @param listeners array of listeners in the format used by
17.536 - * javax.swing.EventListenerList. It means that there are Class
17.537 - * objects on even positions and the listeners on odd positions
17.538 - * @param ev the event to fire
17.539 - */
17.540 - static void notifyListeners(Object[] listeners, LookupEvent ev, Collection<Object> evAndListeners) {
17.541 - for (int i = listeners.length - 1; i >= 0; i--) {
17.542 - if (! (listeners[i] instanceof LookupListener)) {
17.543 - continue;
17.544 - }
17.545 - LookupListener ll = (LookupListener)listeners[i];
17.546 -
17.547 - try {
17.548 - if (evAndListeners != null) {
17.549 - if (ll instanceof WaitableResult) {
17.550 - WaitableResult<?> wr = (WaitableResult<?>)ll;
17.551 - wr.collectFires(evAndListeners);
17.552 - } else {
17.553 - evAndListeners.add(ev);
17.554 - evAndListeners.add(ll);
17.555 - }
17.556 - } else {
17.557 - ll.resultChanged(ev);
17.558 - }
17.559 - } catch (StackOverflowError err) {
17.560 - throw new CycleError(evAndListeners); // NOI18N
17.561 - } catch (RuntimeException e) {
17.562 - // Such as e.g. occurred in #32040. Do not halt other things.
17.563 - e.printStackTrace();
17.564 - }
17.565 - }
17.566 - }
17.567 -
17.568 - private static class CycleError extends StackOverflowError {
17.569 - private final Collection<Object> print;
17.570 - public CycleError(Collection<Object> evAndListeners) {
17.571 - this.print = evAndListeners;
17.572 - }
17.573 -
17.574 - @Override
17.575 - public String getMessage() {
17.576 - StringBuilder sb = new StringBuilder();
17.577 - sb.append("StackOverflowError, here are the listeners:\n"); // NOI18N
17.578 - for (Object o : print) {
17.579 - sb.append('\n').append(o);
17.580 - if (sb.length() > 10000) {
17.581 - break;
17.582 - }
17.583 - }
17.584 - return sb.toString();
17.585 - }
17.586 - } // end of CycleError
17.587 -
17.588 - /** A method that defines matching between Item and Template.
17.589 - * @param t template providing the criteria
17.590 - * @param item the item to match
17.591 - * @param deepCheck true if type of the pair should be tested, false if it is already has been tested
17.592 - * @return true if item matches the template requirements, false if not
17.593 - */
17.594 - static boolean matches(Template<?> t, Pair<?> item, boolean deepCheck) {
17.595 - String id = t.getId();
17.596 -
17.597 - if (id != null && !id.equals(item.getId())) {
17.598 - return false;
17.599 - }
17.600 -
17.601 - Object instance = t.getInstance();
17.602 -
17.603 - if ((instance != null) && !item.creatorOf(instance)) {
17.604 - return false;
17.605 - }
17.606 -
17.607 - if (deepCheck) {
17.608 - return item.instanceOf(t.getType());
17.609 - } else {
17.610 - return true;
17.611 - }
17.612 - }
17.613 -
17.614 - /**
17.615 - * Compares the array elements for equality.
17.616 - * @return true if all elements in the arrays are equal
17.617 - * (by calling equals(Object x) method)
17.618 - */
17.619 - private static boolean compareArrays(Object[] a, Object[] b) {
17.620 - // handle null values
17.621 - if (a == null) {
17.622 - return (b == null);
17.623 - } else {
17.624 - if (b == null) {
17.625 - return false;
17.626 - }
17.627 - }
17.628 -
17.629 - if (a.length != b.length) {
17.630 - return false;
17.631 - }
17.632 -
17.633 - for (int i = 0; i < a.length; i++) {
17.634 - // handle null values for individual elements
17.635 - if (a[i] == null) {
17.636 - if (b[i] != null) {
17.637 - return false;
17.638 - }
17.639 -
17.640 - // both are null --> ok, take next
17.641 - continue;
17.642 - } else {
17.643 - if (b[i] == null) {
17.644 - return false;
17.645 - }
17.646 - }
17.647 -
17.648 - // perform the comparison
17.649 - if (!a[i].equals(b[i])) {
17.650 - return false;
17.651 - }
17.652 - }
17.653 -
17.654 - return true;
17.655 - }
17.656 -
17.657 - /** Method to be called when a result is cleared to signal that the list
17.658 - * of all result should be checked for clearing.
17.659 - * @param template the template the result was for
17.660 - * @return true if the hash map with all items has been cleared
17.661 - */
17.662 - <T> boolean cleanUpResult(Lookup.Template<T> template) {
17.663 - AbstractLookup.Storage<?> t = enterStorage();
17.664 -
17.665 - try {
17.666 - return t.cleanUpResult(template) == null;
17.667 - } finally {
17.668 - exitStorage();
17.669 - }
17.670 - }
17.671 -
17.672 - /** Storage check for tests. */
17.673 - static boolean isSimple(AbstractLookup l) {
17.674 - return DelegatingStorage.isSimple((Storage)l.tree);
17.675 - }
17.676 -
17.677 - /** Generic support for listeners, so it can be used in other results
17.678 - * as well.
17.679 - * @param add true to add it, false to modify
17.680 - * @param l listener to modify
17.681 - * @param ref the value of the reference to listener or listener list
17.682 - * @return new value to the reference to listener or list
17.683 - */
17.684 - @SuppressWarnings("unchecked")
17.685 - static Object modifyListenerList(boolean add, LookupListener l, Object ref) {
17.686 - if (add) {
17.687 - if (ref == null) {
17.688 - return l;
17.689 - }
17.690 -
17.691 - if (ref instanceof LookupListener) {
17.692 - ArrayList arr = new ArrayList();
17.693 - arr.add(ref);
17.694 - ref = arr;
17.695 - }
17.696 -
17.697 - ((ArrayList) ref).add(l);
17.698 -
17.699 - return ref;
17.700 - } else {
17.701 - // remove
17.702 - if (ref == null) {
17.703 - return null;
17.704 - }
17.705 -
17.706 - if (ref == l) {
17.707 - return null;
17.708 - }
17.709 -
17.710 - ArrayList arr = (ArrayList) ref;
17.711 - arr.remove(l);
17.712 -
17.713 - if (arr.size() == 1) {
17.714 - return arr.iterator().next();
17.715 - } else {
17.716 - return arr;
17.717 - }
17.718 - }
17.719 - }
17.720 -
17.721 - private static ReferenceQueue<Object> activeQueue() {
17.722 - return ActiveQueue.queue();
17.723 - }
17.724 -
17.725 - /** Storage to keep the internal structure of Pairs and to answer
17.726 - * different queries.
17.727 - */
17.728 - interface Storage<Transaction> {
17.729 - /** Initializes a modification operation by creating an object
17.730 - * that will be passsed to all add, remove, retainAll methods
17.731 - * and should collect enough information about the change to
17.732 - * notify listeners about the transaction later
17.733 - *
17.734 - * @param ensure the amount of items that will appear in the storage
17.735 - * after the modifications (-1 == remove one, -2 == add one, >= 0
17.736 - * the amount of objects at the end
17.737 - * @return a token to identify the transaction
17.738 - */
17.739 - public Transaction beginTransaction(int ensure);
17.740 -
17.741 - /** Collects all affected results R that were modified in the
17.742 - * given transaction.
17.743 - *
17.744 - * @param modified place to add results R to
17.745 - * @param transaction the transaction indentification
17.746 - */
17.747 - public void endTransaction(Transaction transaction, Set<R> modifiedResults);
17.748 -
17.749 - /** Adds an item into the storage.
17.750 - * @param item to add
17.751 - * @param transaction transaction token
17.752 - * @return true if the Item has been added for the first time or false if some other
17.753 - * item equal to this one already existed in the lookup
17.754 - */
17.755 - public boolean add(AbstractLookup.Pair<?> item, Transaction transaction);
17.756 -
17.757 - /** Removes an item.
17.758 - */
17.759 - public void remove(AbstractLookup.Pair item, Transaction transaction);
17.760 -
17.761 - /** Removes all items that are not present in the provided collection.
17.762 - * @param retain collection of Pairs to keep them in
17.763 - * @param transaction the transaction context
17.764 - */
17.765 - public void retainAll(Map retain, Transaction transaction);
17.766 -
17.767 - /** Queries for instances of given class.
17.768 - * @param clazz the class to check
17.769 - * @return enumeration of Item
17.770 - * @see #unsorted
17.771 - */
17.772 - public <T> Enumeration<Pair<T>> lookup(Class<T> clazz);
17.773 -
17.774 - /** Registers another reference to a result with the storage. This method
17.775 - * has also a special meaning.
17.776 - *
17.777 - * @param newRef the new reference to remember
17.778 - * @return the previous reference that was kept (null if newRef is the first one)
17.779 - * the applications is expected to link from newRef to this returned
17.780 - * value to form a linked list
17.781 - */
17.782 - public ReferenceToResult<?> registerReferenceToResult(ReferenceToResult<?> newRef);
17.783 -
17.784 - /** Given the provided template, Do cleanup the results.
17.785 - * @param templ template of a result(s) that should be checked
17.786 - * @return null if all references for this template were cleared or one of them
17.787 - */
17.788 - public ReferenceToResult<?> cleanUpResult(Lookup.Template<?> templ);
17.789 - }
17.790 -
17.791 - /** Extension to the default lookup item that offers additional information
17.792 - * for the data structures use in AbstractLookup
17.793 - */
17.794 - public static abstract class Pair<T> extends Lookup.Item<T> implements Serializable {
17.795 - private static final long serialVersionUID = 1L;
17.796 -
17.797 - /** possition of this item in the lookup, manipulated in addPair, removePair, setPairs methods */
17.798 - private int index = -1;
17.799 -
17.800 - /** For use by subclasses. */
17.801 - protected Pair() {
17.802 - }
17.803 -
17.804 - final int getIndex() {
17.805 - return index;
17.806 - }
17.807 -
17.808 - final void setIndex(AbstractLookup.Storage<?> tree, int x) {
17.809 - if (tree == null) {
17.810 - this.index = x;
17.811 -
17.812 - return;
17.813 - }
17.814 -
17.815 - if (this.index == -1) {
17.816 - this.index = x;
17.817 - } else {
17.818 - throw new IllegalStateException("You cannot use " + this + " in more than one AbstractLookup. Prev: " + this.index + " new: " + x); // NOI18N
17.819 - }
17.820 - }
17.821 -
17.822 - /** Tests whether this item can produce object
17.823 - * of class c.
17.824 - */
17.825 - protected abstract boolean instanceOf(Class<?> c);
17.826 -
17.827 - /** Method that can test whether an instance of a class has been created
17.828 - * by this item.
17.829 - *
17.830 - * @param obj the instance
17.831 - * @return if the item has already create an instance and it is the same
17.832 - * as obj.
17.833 - */
17.834 - protected abstract boolean creatorOf(Object obj);
17.835 - }
17.836 -
17.837 - /** Result based on one instance returned.
17.838 - */
17.839 - static final class R<T> extends WaitableResult<T> {
17.840 - /** reference our result is attached to (do not modify) */
17.841 - public ReferenceToResult<T> reference;
17.842 -
17.843 - /** listeners on the results or pointer to one listener */
17.844 - private Object listeners;
17.845 -
17.846 - public R() {
17.847 - }
17.848 -
17.849 - /** Checks whether we have simple behaviour of complex.
17.850 - */
17.851 - private boolean isSimple() {
17.852 - Storage s = (Storage) reference.lookup.tree;
17.853 -
17.854 - return DelegatingStorage.isSimple(s);
17.855 - }
17.856 -
17.857 - //
17.858 - // Handling cache management for both cases, no caches
17.859 - // for simple (but mark that we needed them, so refresh can
17.860 - // be done in cloneList) and complex when all 3 types
17.861 - // of result are cached
17.862 - //
17.863 - private Object getFromCache(int indx) {
17.864 - if (isSimple()) {
17.865 - return null;
17.866 - }
17.867 -
17.868 - Object maybeArray = reference.caches;
17.869 -
17.870 - if (maybeArray instanceof Object[]) {
17.871 - return ((Object[]) maybeArray)[indx];
17.872 - }
17.873 -
17.874 - return null;
17.875 - }
17.876 -
17.877 - @SuppressWarnings("unchecked")
17.878 - private Set<Class<? extends T>> getClassesCache() {
17.879 - return (Set<Class<? extends T>>) getFromCache(0);
17.880 - }
17.881 -
17.882 - private void setClassesCache(Set s) {
17.883 - if (isSimple()) {
17.884 - // mark it as being used
17.885 - reference.caches = reference;
17.886 -
17.887 - return;
17.888 - }
17.889 -
17.890 - if (!(reference.caches instanceof Object[])) {
17.891 - reference.caches = new Object[3];
17.892 - }
17.893 -
17.894 - ((Object[]) reference.caches)[0] = s;
17.895 - }
17.896 -
17.897 - @SuppressWarnings("unchecked")
17.898 - private Collection<T> getInstancesCache() {
17.899 - return (Collection<T>) getFromCache(1);
17.900 - }
17.901 -
17.902 - private void setInstancesCache(Collection c) {
17.903 - if (isSimple()) {
17.904 - // mark it as being used
17.905 - reference.caches = reference;
17.906 -
17.907 - return;
17.908 - }
17.909 -
17.910 - if (!(reference.caches instanceof Object[])) {
17.911 - reference.caches = new Object[3];
17.912 - }
17.913 -
17.914 - ((Object[]) reference.caches)[1] = c;
17.915 - }
17.916 -
17.917 - @SuppressWarnings("unchecked")
17.918 - private Pair<T>[] getItemsCache() {
17.919 - return (Pair<T>[]) getFromCache(2);
17.920 - }
17.921 -
17.922 - private void setItemsCache(Collection<?> c) {
17.923 - if (isSimple()) {
17.924 - // mark it as being used
17.925 - reference.caches = reference;
17.926 -
17.927 - return;
17.928 - }
17.929 -
17.930 - if (!(reference.caches instanceof Object[])) {
17.931 - reference.caches = new Object[3];
17.932 - }
17.933 -
17.934 - ((Object[]) reference.caches)[2] = c.toArray(new Pair[0]);
17.935 - }
17.936 -
17.937 - private void clearCaches() {
17.938 - if (reference.caches instanceof Object[]) {
17.939 - reference.caches = new Object[3];
17.940 - }
17.941 - }
17.942 -
17.943 - /** Ok, register listeners to all classes and super classes.
17.944 - */
17.945 - public synchronized void addLookupListener(LookupListener l) {
17.946 - listeners = modifyListenerList(true, l, listeners);
17.947 - }
17.948 -
17.949 - /** Ok, register listeners to all classes and super classes.
17.950 - */
17.951 - public synchronized void removeLookupListener(LookupListener l) {
17.952 - listeners = modifyListenerList(false, l, listeners);
17.953 - }
17.954 -
17.955 - /** Delete all cached values, the template changed.
17.956 - */
17.957 - protected void collectFires(Collection<Object> evAndListeners) {
17.958 - Object[] previousItems = getItemsCache();
17.959 - clearCaches();
17.960 -
17.961 - if (previousItems != null) {
17.962 - Object[] newArray = allItemsWithoutBeforeLookup().toArray();
17.963 -
17.964 - if (compareArrays(previousItems, newArray)) {
17.965 - // do not fire any change if nothing has been changed
17.966 - return;
17.967 - }
17.968 - }
17.969 -
17.970 - LookupListener[] arr;
17.971 -
17.972 - synchronized (this) {
17.973 - if (listeners == null) {
17.974 - return;
17.975 - }
17.976 -
17.977 - if (listeners instanceof LookupListener) {
17.978 - arr = new LookupListener[] { (LookupListener) listeners };
17.979 - } else {
17.980 - ArrayList<?> l = (ArrayList<?>) listeners;
17.981 - arr = l.toArray(new LookupListener[l.size()]);
17.982 - }
17.983 - }
17.984 -
17.985 - final LookupListener[] ll = arr;
17.986 - final LookupEvent ev = new LookupEvent(this);
17.987 - notifyListeners(ll, ev, evAndListeners);
17.988 - }
17.989 -
17.990 - public Collection<T> allInstances() {
17.991 - reference.lookup.beforeLookup(reference.template);
17.992 -
17.993 - Collection<T> s = getInstancesCache();
17.994 -
17.995 - if (s != null) {
17.996 - return s;
17.997 - }
17.998 -
17.999 - Collection<Pair<T>> items = allItemsWithoutBeforeLookup();
17.1000 - ArrayList<T> list = new ArrayList<T>(items.size());
17.1001 -
17.1002 - Iterator<Pair<T>> it = items.iterator();
17.1003 -
17.1004 - while (it.hasNext()) {
17.1005 - Pair<T> item = it.next();
17.1006 - T obj = item.getInstance();
17.1007 -
17.1008 - if (reference.template.getType().isInstance(obj)) {
17.1009 - list.add(obj);
17.1010 - }
17.1011 - }
17.1012 -
17.1013 - s = Collections.unmodifiableList(list);
17.1014 - setInstancesCache(s);
17.1015 -
17.1016 - return s;
17.1017 - }
17.1018 -
17.1019 - /** Set of all classes.
17.1020 - *
17.1021 - */
17.1022 - @Override
17.1023 - public Set<Class<? extends T>> allClasses() {
17.1024 - reference.lookup.beforeLookup(reference.template);
17.1025 -
17.1026 - Set<Class<? extends T>> s = getClassesCache();
17.1027 -
17.1028 - if (s != null) {
17.1029 - return s;
17.1030 - }
17.1031 -
17.1032 - s = new HashSet<Class<? extends T>>();
17.1033 -
17.1034 - for (Pair<T> item : allItemsWithoutBeforeLookup()) {
17.1035 - Class<? extends T> clazz = item.getType();
17.1036 -
17.1037 - if (clazz != null) {
17.1038 - s.add(clazz);
17.1039 - }
17.1040 - }
17.1041 -
17.1042 - s = Collections.unmodifiableSet(s);
17.1043 - setClassesCache(s);
17.1044 -
17.1045 - return s;
17.1046 - }
17.1047 -
17.1048 - /** Items are stored directly in the allItems.
17.1049 - */
17.1050 - @Override
17.1051 - public Collection<? extends Item<T>> allItems() {
17.1052 - reference.lookup.beforeLookup(reference.template);
17.1053 -
17.1054 - return allItemsWithoutBeforeLookup();
17.1055 - }
17.1056 -
17.1057 - /** Implements the search for allItems, but without asking for before lookup */
17.1058 - private Collection<Pair<T>> allItemsWithoutBeforeLookup() {
17.1059 - Pair<T>[] c = getItemsCache();
17.1060 -
17.1061 - if (c != null) {
17.1062 - return Collections.unmodifiableList(Arrays.asList(c));
17.1063 - }
17.1064 -
17.1065 - ArrayList<Pair<Object>> saferCheck = null;
17.1066 - AbstractLookup.Storage<?> t = reference.lookup.enterStorage();
17.1067 -
17.1068 - try {
17.1069 - try {
17.1070 - return Collections.unmodifiableCollection(initItems(t));
17.1071 - } catch (AbstractLookup.ISE ex) {
17.1072 - // do less effective evaluation of items outside of the
17.1073 - // locked storage
17.1074 - saferCheck = new ArrayList<Pair<Object>>();
17.1075 -
17.1076 - Enumeration<Pair<Object>> en = t.lookup(null); // get all Pairs
17.1077 -
17.1078 - while (en.hasMoreElements()) {
17.1079 - Pair<Object> i = en.nextElement();
17.1080 - saferCheck.add(i);
17.1081 - }
17.1082 - }
17.1083 - } finally {
17.1084 - reference.lookup.exitStorage();
17.1085 - }
17.1086 - return extractPairs(saferCheck);
17.1087 - }
17.1088 -
17.1089 - @SuppressWarnings("unchecked")
17.1090 - private Collection<Pair<T>> extractPairs(final ArrayList<Pair<Object>> saferCheck) {
17.1091 - TreeSet<Pair<T>> items = new TreeSet<Pair<T>>(ALPairComparator.DEFAULT);
17.1092 - for (Pair<Object> i : saferCheck) {
17.1093 - if (matches(reference.template, i, false)) {
17.1094 - items.add((Pair<T>)i);
17.1095 - }
17.1096 - }
17.1097 - return Collections.unmodifiableCollection(items);
17.1098 - }
17.1099 -
17.1100 - /** Initializes items.
17.1101 - */
17.1102 - private Collection<Pair<T>> initItems(Storage<?> t) {
17.1103 - // manipulation with the tree must be synchronized
17.1104 - Enumeration<Pair<T>> en = t.lookup(reference.template.getType());
17.1105 -
17.1106 - // InheritanceTree is comparator for AbstractLookup.Pairs
17.1107 - TreeSet<Pair<T>> items = new TreeSet<Pair<T>>(ALPairComparator.DEFAULT);
17.1108 -
17.1109 - while (en.hasMoreElements()) {
17.1110 - Pair<T> i = en.nextElement();
17.1111 -
17.1112 - if (matches(reference.template, i, false)) {
17.1113 - items.add(i);
17.1114 - }
17.1115 - }
17.1116 -
17.1117 - // create a correctly sorted copy using the tree as the comparator
17.1118 - setItemsCache(items);
17.1119 -
17.1120 - return items;
17.1121 - }
17.1122 -
17.1123 - /** Used by proxy results to synchronize before lookup.
17.1124 - */
17.1125 - protected void beforeLookup(Lookup.Template t) {
17.1126 - if (t.getType() == reference.template.getType()) {
17.1127 - reference.lookup.beforeLookup(t);
17.1128 - }
17.1129 - }
17.1130 -
17.1131 - /* Do not need to implement it, the default way is ok.
17.1132 - public boolean equals(java.lang.Object obj) {
17.1133 - return obj == this;
17.1134 - }
17.1135 - */
17.1136 - @Override
17.1137 - public String toString() {
17.1138 - return super.toString() + " for " + reference.template;
17.1139 - }
17.1140 - }
17.1141 - // end of R
17.1142 -
17.1143 - /** A class that can be used by the creator of the AbstractLookup to
17.1144 - * control its content. It can be passed to AbstractLookup constructor
17.1145 - * and used to add and remove pairs.
17.1146 - *
17.1147 - * @since 1.25
17.1148 - */
17.1149 - public static class Content extends Object implements Serializable {
17.1150 - private static final long serialVersionUID = 1L;
17.1151 -
17.1152 - // one of them is always null (except attach stage)
17.1153 -
17.1154 - /** abstract lookup we are connected to */
17.1155 - private AbstractLookup al;
17.1156 - private transient Object notifyIn;
17.1157 -
17.1158 - /** Default constructor.
17.1159 - */
17.1160 - public Content() {
17.1161 - this(null);
17.1162 - }
17.1163 -
17.1164 - /** Creates a content associated with an executor to handle dispatch
17.1165 - * of changes.
17.1166 - * @param notifyIn the executor to notify changes in
17.1167 - * @since 7.16
17.1168 - */
17.1169 - public Content(Executor notifyIn) {
17.1170 - this.notifyIn = notifyIn;
17.1171 - }
17.1172 -
17.1173 - /** for testing purposes */
17.1174 - final void attachExecutor(Executor notifyIn) {
17.1175 - this.notifyIn = notifyIn;
17.1176 - }
17.1177 -
17.1178 - /** A lookup attaches to this object.
17.1179 - */
17.1180 - final synchronized void attach(AbstractLookup al) {
17.1181 - if (this.al == null) {
17.1182 - this.al = al;
17.1183 -
17.1184 - ArrayList<Pair> ep = getEarlyPairs();
17.1185 - if (ep != null) {
17.1186 - notifyIn = null;
17.1187 - setPairs(ep);
17.1188 - }
17.1189 - } else {
17.1190 - throw new IllegalStateException(
17.1191 - "Trying to use content for " + al + " but it is already used for " + this.al
17.1192 - ); // NOI18N
17.1193 - }
17.1194 - }
17.1195 -
17.1196 - /** The method to add instance to the lookup with.
17.1197 - * @param pair class/instance pair
17.1198 - */
17.1199 - public final void addPair(Pair<?> pair) {
17.1200 - AbstractLookup a = al;
17.1201 - Executor e = getExecutor();
17.1202 -
17.1203 - if (a != null || e != null) {
17.1204 - a.addPair(pair, e);
17.1205 - } else {
17.1206 - if (notifyIn == null) {
17.1207 - notifyIn = new ArrayList<Pair>(3);
17.1208 - }
17.1209 -
17.1210 - getEarlyPairs().add(pair);
17.1211 - }
17.1212 - }
17.1213 -
17.1214 - /** Remove instance.
17.1215 - * @param pair class/instance pair
17.1216 - */
17.1217 - public final void removePair(Pair<?> pair) {
17.1218 - AbstractLookup a = al;
17.1219 - Executor e = getExecutor();
17.1220 -
17.1221 - if (a != null || e != null) {
17.1222 - a.removePair(pair, e);
17.1223 - } else {
17.1224 - if (notifyIn == null) {
17.1225 - notifyIn = new ArrayList<Pair>(3);
17.1226 - }
17.1227 -
17.1228 - getEarlyPairs().remove(pair);
17.1229 - }
17.1230 - }
17.1231 -
17.1232 - /** Changes all pairs in the lookup to new values.
17.1233 - * @param c the collection of (Pair) objects
17.1234 - */
17.1235 - public final void setPairs(Collection<? extends Pair> c) {
17.1236 - AbstractLookup a = al;
17.1237 - Executor e = getExecutor();
17.1238 -
17.1239 - if (a != null || e != null) {
17.1240 - a.setPairs(c, e);
17.1241 - } else {
17.1242 - notifyIn = new ArrayList<Pair>(c);
17.1243 - }
17.1244 - }
17.1245 -
17.1246 - @SuppressWarnings("unchecked")
17.1247 - private ArrayList<Pair> getEarlyPairs() {
17.1248 - Object o = notifyIn;
17.1249 - return o instanceof ArrayList ? (ArrayList<Pair>)o : null;
17.1250 - }
17.1251 -
17.1252 - private Executor getExecutor() {
17.1253 - Object o = notifyIn;
17.1254 - return o instanceof Executor ? (Executor)o : null;
17.1255 - }
17.1256 - }
17.1257 - // end of Content
17.1258 -
17.1259 - /** Just a holder for index & modified values.
17.1260 - */
17.1261 - final static class Info extends Object {
17.1262 - public int index;
17.1263 - public Object transaction;
17.1264 -
17.1265 - public Info(int i, Object t) {
17.1266 - index = i;
17.1267 - transaction = t;
17.1268 - }
17.1269 - }
17.1270 -
17.1271 - /** Reference to a result R
17.1272 - */
17.1273 - static final class ReferenceToResult<T> extends WeakReference<R<T>> implements Runnable {
17.1274 - /** next refernece in chain, modified only from AbstractLookup or this */
17.1275 - private ReferenceToResult<?> next;
17.1276 -
17.1277 - /** the template for the result */
17.1278 - public final Template<T> template;
17.1279 -
17.1280 - /** the lookup we are attached to */
17.1281 - public final AbstractLookup lookup;
17.1282 -
17.1283 - /** caches for results */
17.1284 - public Object caches;
17.1285 -
17.1286 - /** Creates a weak refernece to a new result R in context of lookup
17.1287 - * for given template
17.1288 - */
17.1289 - private ReferenceToResult(R<T> result, AbstractLookup lookup, Template<T> template) {
17.1290 - super(result, activeQueue());
17.1291 - this.template = template;
17.1292 - this.lookup = lookup;
17.1293 - getResult().reference = this;
17.1294 - }
17.1295 -
17.1296 - /** Returns the result or null
17.1297 - */
17.1298 - R<T> getResult() {
17.1299 - return get();
17.1300 - }
17.1301 -
17.1302 - /** Cleans the reference. Implements Runnable interface, do not call
17.1303 - * directly.
17.1304 - */
17.1305 - public void run() {
17.1306 - lookup.cleanUpResult(this.template);
17.1307 - }
17.1308 -
17.1309 - /** Clones the reference list to given Storage.
17.1310 - * @param storage storage to clone to
17.1311 - */
17.1312 - public void cloneList(AbstractLookup.Storage<?> storage) {
17.1313 - ReferenceIterator it = new ReferenceIterator(this);
17.1314 -
17.1315 - while (it.next()) {
17.1316 - ReferenceToResult<?> current = it.current();
17.1317 - ReferenceToResult<?> newRef = current.cloneRef();
17.1318 - newRef.next = storage.registerReferenceToResult(newRef);
17.1319 - newRef.caches = current.caches;
17.1320 -
17.1321 - if (current.caches == current) {
17.1322 - current.getResult().initItems(storage);
17.1323 - }
17.1324 - }
17.1325 - }
17.1326 -
17.1327 - private ReferenceToResult<T> cloneRef() {
17.1328 - return new ReferenceToResult<T>(getResult(), lookup, template);
17.1329 - }
17.1330 - }
17.1331 - // end of ReferenceToResult
17.1332 -
17.1333 - /** Supporting class to iterate over linked list of ReferenceToResult
17.1334 - * Use:
17.1335 - * <PRE>
17.1336 - * ReferenceIterator it = new ReferenceIterator (this.ref);
17.1337 - * while (it.next ()) {
17.1338 - * it.current (): // do some work
17.1339 - * }
17.1340 - * this.ref = it.first (); // remember the first one
17.1341 - */
17.1342 - static final class ReferenceIterator extends Object {
17.1343 - private ReferenceToResult<?> first;
17.1344 - private ReferenceToResult<?> current;
17.1345 -
17.1346 - /** hard reference to current result, so it is not GCed meanwhile */
17.1347 - private R<?> currentResult;
17.1348 -
17.1349 - /** Initializes the iterator with first reference.
17.1350 - */
17.1351 - public ReferenceIterator(ReferenceToResult<?> first) {
17.1352 - this.first = first;
17.1353 - }
17.1354 -
17.1355 - /** Moves the current to next possition */
17.1356 - public boolean next() {
17.1357 - ReferenceToResult<?> prev;
17.1358 - ReferenceToResult<?> ref;
17.1359 -
17.1360 - if (current == null) {
17.1361 - ref = first;
17.1362 - prev = null;
17.1363 - } else {
17.1364 - prev = current;
17.1365 - ref = current.next;
17.1366 - }
17.1367 -
17.1368 - while (ref != null) {
17.1369 - R<?> result = ref.get();
17.1370 -
17.1371 - if (result == null) {
17.1372 - if (prev == null) {
17.1373 - // move the head
17.1374 - first = ref.next;
17.1375 - } else {
17.1376 - // skip over this reference
17.1377 - prev.next = ref.next;
17.1378 - }
17.1379 -
17.1380 - prev = ref;
17.1381 - ref = ref.next;
17.1382 - } else {
17.1383 - // we have found next item
17.1384 - currentResult = result;
17.1385 - current = ref;
17.1386 -
17.1387 - return true;
17.1388 - }
17.1389 - }
17.1390 -
17.1391 - currentResult = null;
17.1392 - current = null;
17.1393 -
17.1394 - return false;
17.1395 - }
17.1396 -
17.1397 - /** Access to current reference.
17.1398 - */
17.1399 - public ReferenceToResult<?> current() {
17.1400 - return current;
17.1401 - }
17.1402 -
17.1403 - /** Access to reference that is supposed to be the first one.
17.1404 - */
17.1405 - public ReferenceToResult<?> first() {
17.1406 - return first;
17.1407 - }
17.1408 - }
17.1409 -
17.1410 - /** Signals that a lookup is being modified from a lookup query.
17.1411 - *
17.1412 - * @author Jaroslav Tulach
17.1413 - */
17.1414 - static final class ISE extends IllegalStateException {
17.1415 - static final long serialVersionUID = 100L;
17.1416 -
17.1417 - /** list of jobs to execute. */
17.1418 - private java.util.List<Job> jobs;
17.1419 -
17.1420 - /** @param msg message
17.1421 - */
17.1422 - public ISE(String msg) {
17.1423 - super(msg);
17.1424 - }
17.1425 -
17.1426 - /** Registers a job to be executed partially out and partially in
17.1427 - * the lock over storage.
17.1428 - */
17.1429 - public void registerJob(Job job) {
17.1430 - if (jobs == null) {
17.1431 - jobs = new java.util.ArrayList<Job>();
17.1432 - }
17.1433 -
17.1434 - jobs.add(job);
17.1435 - }
17.1436 -
17.1437 - /** Executes the jobs outside, and then inside a locked session.
17.1438 - */
17.1439 - public void recover(AbstractLookup lookup) {
17.1440 - if (jobs == null) {
17.1441 - // no recovery plan, throw itself
17.1442 - throw this;
17.1443 - }
17.1444 -
17.1445 - for (Job j : jobs) {
17.1446 - j.before();
17.1447 - }
17.1448 -
17.1449 - AbstractLookup.Storage s = lookup.enterStorage();
17.1450 -
17.1451 - try {
17.1452 - for (Job j : jobs) {
17.1453 - j.inside();
17.1454 - }
17.1455 - } finally {
17.1456 - lookup.exitStorage();
17.1457 - }
17.1458 - }
17.1459 -
17.1460 - /** A job to be executed partially outside and partially inside
17.1461 - * the storage lock.
17.1462 - */
17.1463 - static interface Job {
17.1464 - public void before();
17.1465 -
17.1466 - public void inside();
17.1467 - }
17.1468 - }
17.1469 - // end of ISE
17.1470 -}
18.1 --- a/lookup/src/main/java/org/openide/util/lookup/ArrayStorage.java Wed Jan 27 17:46:23 2010 -0500
18.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
18.3 @@ -1,477 +0,0 @@
18.4 -/*
18.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
18.6 - *
18.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
18.8 - *
18.9 - * The contents of this file are subject to the terms of either the GNU
18.10 - * General Public License Version 2 only ("GPL") or the Common
18.11 - * Development and Distribution License("CDDL") (collectively, the
18.12 - * "License"). You may not use this file except in compliance with the
18.13 - * License. You can obtain a copy of the License at
18.14 - * http://www.netbeans.org/cddl-gplv2.html
18.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
18.16 - * specific language governing permissions and limitations under the
18.17 - * License. When distributing the software, include this License Header
18.18 - * Notice in each file and include the License file at
18.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
18.20 - * particular file as subject to the "Classpath" exception as provided
18.21 - * by Sun in the GPL Version 2 section of the License file that
18.22 - * accompanied this code. If applicable, add the following below the
18.23 - * License Header, with the fields enclosed by brackets [] replaced by
18.24 - * your own identifying information:
18.25 - * "Portions Copyrighted [year] [name of copyright owner]"
18.26 - *
18.27 - * Contributor(s):
18.28 - *
18.29 - * The Original Software is NetBeans. The Initial Developer of the Original
18.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
18.31 - * Microsystems, Inc. All Rights Reserved.
18.32 - *
18.33 - * If you wish your version of this file to be governed by only the CDDL
18.34 - * or only the GPL Version 2, indicate your decision by adding
18.35 - * "[Contributor] elects to include this software in this distribution
18.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
18.37 - * single choice of license, a recipient has the option to distribute
18.38 - * your version of this file under either the CDDL, the GPL Version 2 or
18.39 - * to extend the choice of license to its licensees as provided above.
18.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
18.41 - * Version 2 license, then the option applies only if the new code is
18.42 - * made subject to such option by the copyright holder.
18.43 - */
18.44 -package org.openide.util.lookup;
18.45 -
18.46 -import org.openide.util.Lookup;
18.47 -
18.48 -
18.49 -
18.50 -import java.util.*;
18.51 -import org.openide.util.lookup.AbstractLookup.Pair;
18.52 -
18.53 -
18.54 -/** ArrayStorage of Pairs from AbstractLookup.
18.55 - * @author Jaroslav Tulach
18.56 - */
18.57 -final class ArrayStorage extends Object
18.58 -implements AbstractLookup.Storage<ArrayStorage.Transaction> {
18.59 - /** default trashold */
18.60 - static final Integer DEFAULT_TRASH = new Integer(11);
18.61 -
18.62 - /** list of items */
18.63 - private Object content;
18.64 -
18.65 - /** linked list of refernces to results */
18.66 - private transient AbstractLookup.ReferenceToResult<?> results;
18.67 -
18.68 - /** Constructor
18.69 - */
18.70 - public ArrayStorage() {
18.71 - this(DEFAULT_TRASH);
18.72 - }
18.73 -
18.74 - /** Constructs new ArrayStorage */
18.75 - public ArrayStorage(Integer treshhold) {
18.76 - this.content = treshhold;
18.77 - }
18.78 -
18.79 - /** Adds an item into the tree.
18.80 - * @param item to add
18.81 - * @return true if the Item has been added for the first time or false if some other
18.82 - * item equal to this one already existed in the lookup
18.83 - */
18.84 - public boolean add(AbstractLookup.Pair<?> item, Transaction changed) {
18.85 - Object[] arr = changed.current;
18.86 -
18.87 - if (changed.arr == null) {
18.88 - // just simple add of one item
18.89 - for (int i = 0; i < arr.length; i++) {
18.90 - if (arr[i] == null) {
18.91 - arr[i] = item;
18.92 - changed.add(item);
18.93 -
18.94 - return true;
18.95 - }
18.96 -
18.97 - if (arr[i].equals(item)) {
18.98 - // reassign the item number
18.99 - item.setIndex(null, ((AbstractLookup.Pair) arr[i]).getIndex());
18.100 -
18.101 - // already there, but update it
18.102 - arr[i] = item;
18.103 -
18.104 - return false;
18.105 - }
18.106 - }
18.107 -
18.108 - // cannot happen as the beginTransaction ensured we can finish
18.109 - // correctly
18.110 - throw new IllegalStateException();
18.111 - } else {
18.112 - // doing remainAll after that, let Transaction hold the new array
18.113 - int newIndex = changed.addPair(item);
18.114 -
18.115 - for (int i = 0; i < arr.length; i++) {
18.116 - if (arr[i] == null) {
18.117 - changed.add(item);
18.118 -
18.119 - return true;
18.120 - }
18.121 -
18.122 - if (arr[i].equals(item)) {
18.123 - // already there
18.124 - if (i != newIndex) {
18.125 - // change in index
18.126 - changed.add(item);
18.127 -
18.128 - return false;
18.129 - } else {
18.130 - // no change
18.131 - return false;
18.132 - }
18.133 - }
18.134 - }
18.135 -
18.136 - // if not found in the original array
18.137 - changed.add(item);
18.138 -
18.139 - return true;
18.140 - }
18.141 - }
18.142 -
18.143 - /** Removes an item.
18.144 - */
18.145 - public void remove(AbstractLookup.Pair item, Transaction changed) {
18.146 - Object[] arr = changed.current;
18.147 - if (arr == null) {
18.148 - return;
18.149 - }
18.150 -
18.151 - int found = -1;
18.152 -
18.153 - for (int i = 0; i < arr.length;) {
18.154 - if (arr[i] == null) {
18.155 - // end of task
18.156 - return;
18.157 - }
18.158 -
18.159 - if ((found == -1) && arr[i].equals(item)) {
18.160 - // already there
18.161 - Pair<?> p = (Pair<?>)arr[i];
18.162 - p.setIndex(null, -1);
18.163 - changed.add(p);
18.164 - found = i;
18.165 - }
18.166 -
18.167 - i++;
18.168 -
18.169 - if (found != -1) {
18.170 - if (i < arr.length && !(arr[i] instanceof Integer)) {
18.171 - // moving the array
18.172 - arr[i - 1] = arr[i];
18.173 - } else {
18.174 - arr[i - 1] = null;
18.175 - }
18.176 - }
18.177 - }
18.178 - }
18.179 -
18.180 - /** Removes all items that are not present in the provided collection.
18.181 - * @param retain Pair -> AbstractLookup.Info map
18.182 - * @param notify set of Classes that has possibly changed
18.183 - */
18.184 - public void retainAll(Map retain, Transaction changed) {
18.185 - Object[] arr = changed.current;
18.186 -
18.187 - for (int from = 0; from < arr.length; from++) {
18.188 - if (!(arr[from] instanceof AbstractLookup.Pair)) {
18.189 - // end of content
18.190 - break;
18.191 - }
18.192 -
18.193 - AbstractLookup.Pair p = (AbstractLookup.Pair) arr[from];
18.194 -
18.195 - AbstractLookup.Info info = (AbstractLookup.Info) retain.get(p);
18.196 -
18.197 - if (info == null) {
18.198 - // was removed
18.199 -
18.200 - /*
18.201 - if (info != null) {
18.202 - if (info.index < arr.length) {
18.203 - newArr[info.index] = p;
18.204 - }
18.205 -
18.206 - if (p.getIndex() != info.index) {
18.207 - p.setIndex (null, info.index);
18.208 - changed.add (p);
18.209 - }
18.210 - } else {
18.211 - // removed
18.212 - */
18.213 - changed.add(p);
18.214 - }
18.215 - }
18.216 - }
18.217 -
18.218 - /** Queries for instances of given class.
18.219 - * @param clazz the class to check
18.220 - * @return enumeration of Item
18.221 - * @see #unsorted
18.222 - */
18.223 - public <T> Enumeration<Pair<T>> lookup(final Class<T> clazz) {
18.224 - if (content instanceof Object[]) {
18.225 - final Enumeration<Object> all = InheritanceTree.arrayEn((Object[]) content);
18.226 - class JustPairs implements Enumeration<Pair<T>> {
18.227 - private Pair<T> next;
18.228 -
18.229 - @SuppressWarnings("unchecked")
18.230 - private Pair<T> findNext() {
18.231 - for (;;) {
18.232 - if (next != null) {
18.233 - return next;
18.234 - }
18.235 - if (!all.hasMoreElements()) {
18.236 - return null;
18.237 - }
18.238 - Object o = all.nextElement();
18.239 - boolean ok;
18.240 - if (o instanceof AbstractLookup.Pair) {
18.241 - ok = (clazz == null) || ((AbstractLookup.Pair<?>) o).instanceOf(clazz);
18.242 - } else {
18.243 - ok = false;
18.244 - }
18.245 -
18.246 - next = ok ? (Pair<T>) o : null;
18.247 - }
18.248 - }
18.249 -
18.250 - public boolean hasMoreElements() {
18.251 - return findNext() != null;
18.252 - }
18.253 -
18.254 - public Pair<T> nextElement() {
18.255 - Pair<T> r = findNext();
18.256 - if (r == null) {
18.257 - throw new NoSuchElementException();
18.258 - }
18.259 - next = null;
18.260 - return r;
18.261 - }
18.262 - } // end of JustPairs
18.263 - return new JustPairs();
18.264 - } else {
18.265 - return InheritanceTree.emptyEn();
18.266 - }
18.267 - }
18.268 -
18.269 - /** Associates another result with this storage.
18.270 - */
18.271 - public AbstractLookup.ReferenceToResult registerReferenceToResult(AbstractLookup.ReferenceToResult<?> newRef) {
18.272 - AbstractLookup.ReferenceToResult prev = this.results;
18.273 - this.results = newRef;
18.274 -
18.275 - return prev;
18.276 - }
18.277 -
18.278 - /** Cleanup the references
18.279 - */
18.280 - public AbstractLookup.ReferenceToResult cleanUpResult(Lookup.Template<?> templ) {
18.281 - AbstractLookup.ReferenceIterator it = new AbstractLookup.ReferenceIterator(this.results);
18.282 -
18.283 - while (it.next()) {
18.284 - // empty
18.285 - }
18.286 -
18.287 - return this.results = it.first();
18.288 - }
18.289 -
18.290 - /** We use a hash set of all modified Pair to handle the transaction */
18.291 - public Transaction beginTransaction(int ensure) {
18.292 - return new Transaction(ensure, content);
18.293 - }
18.294 -
18.295 - /** Extract all results.
18.296 - */
18.297 - public void endTransaction(Transaction changed, Set<AbstractLookup.R> modified) {
18.298 - AbstractLookup.ReferenceIterator it = new AbstractLookup.ReferenceIterator(this.results);
18.299 -
18.300 - if (changed.arr == null) {
18.301 - // either add or remove, only check the content of check HashSet
18.302 - while (it.next()) {
18.303 - AbstractLookup.ReferenceToResult ref = it.current();
18.304 - Iterator<Pair<?>> pairs = changed.iterator();
18.305 -
18.306 - while (pairs.hasNext()) {
18.307 - AbstractLookup.Pair p = (AbstractLookup.Pair) pairs.next();
18.308 -
18.309 - if (AbstractLookup.matches(ref.template, p, true)) {
18.310 - modified.add(ref.getResult());
18.311 - }
18.312 - }
18.313 - }
18.314 - } else {
18.315 - // do full check of changes
18.316 - while (it.next()) {
18.317 - AbstractLookup.ReferenceToResult ref = it.current();
18.318 -
18.319 - int oldIndex = -1;
18.320 - int newIndex = -1;
18.321 -
18.322 - for (;;) {
18.323 - oldIndex = findMatching(ref.template, changed.current, oldIndex);
18.324 - newIndex = findMatching(ref.template, changed.arr, newIndex);
18.325 -
18.326 - if ((oldIndex == -1) && (newIndex == -1)) {
18.327 - break;
18.328 - }
18.329 -
18.330 - if (
18.331 - (oldIndex == -1) || (newIndex == -1) ||
18.332 - !changed.current[oldIndex].equals(changed.arr[newIndex])
18.333 - ) {
18.334 - modified.add(ref.getResult());
18.335 -
18.336 - break;
18.337 - }
18.338 - }
18.339 - }
18.340 - }
18.341 -
18.342 - this.results = it.first();
18.343 - this.content = changed.newContent(this.content);
18.344 - }
18.345 -
18.346 - private static int findMatching(Lookup.Template t, Object[] arr, int from) {
18.347 - while (++from < arr.length) {
18.348 - if (arr[from] instanceof AbstractLookup.Pair) {
18.349 - if (AbstractLookup.matches(t, (AbstractLookup.Pair) arr[from], true)) {
18.350 - return from;
18.351 - }
18.352 - }
18.353 - }
18.354 -
18.355 - return -1;
18.356 - }
18.357 -
18.358 - /** HashSet with additional field for new array which is callocated
18.359 - * in case we are doing replace to hold all new items.
18.360 - */
18.361 - static final class Transaction extends HashSet<Pair<?>> {
18.362 - /** array with current objects */
18.363 - public final Object[] current;
18.364 -
18.365 - /** array with new objects */
18.366 - public final Object[] arr;
18.367 -
18.368 - /** number of objects in the array */
18.369 - private int cnt;
18.370 -
18.371 - public Transaction(int ensure, Object currentContent) {
18.372 - Integer trashold;
18.373 - Object[] _arr;
18.374 -
18.375 - if (currentContent instanceof Integer) {
18.376 - trashold = (Integer) currentContent;
18.377 - _arr = null;
18.378 - } else {
18.379 - _arr = (Object[]) currentContent;
18.380 -
18.381 - if (_arr[_arr.length - 1] instanceof Integer) {
18.382 - trashold = (Integer) _arr[_arr.length - 1];
18.383 - } else {
18.384 - // nowhere to grow we have reached the limit
18.385 - trashold = null;
18.386 - }
18.387 - }
18.388 -
18.389 - int maxSize = (trashold == null) ? _arr.length : trashold.intValue();
18.390 -
18.391 - if (ensure > maxSize) {
18.392 - throw new UnsupportedOperationException();
18.393 - }
18.394 -
18.395 - if (ensure == -1) {
18.396 - // remove => it is ok
18.397 - this.current = currentContent instanceof Integer ? null : (Object[]) currentContent;
18.398 - this.arr = null;
18.399 -
18.400 - return;
18.401 - }
18.402 -
18.403 - if (ensure == -2) {
18.404 - // adding one
18.405 - if (_arr == null) {
18.406 - // first time add, let's allocate the array
18.407 - _arr = new Object[2];
18.408 - _arr[1] = trashold;
18.409 - } else {
18.410 - if (_arr[_arr.length - 1] instanceof AbstractLookup.Pair) {
18.411 - // we are full
18.412 - throw new UnsupportedOperationException();
18.413 - } else {
18.414 - // ensure we have allocated enough space
18.415 - if (_arr.length < 2 || _arr[_arr.length - 2] != null) {
18.416 - // double the array
18.417 - int newSize = (_arr.length - 1) * 2;
18.418 -
18.419 - if (newSize <= 1) {
18.420 - newSize = 2;
18.421 - }
18.422 -
18.423 - if (newSize > maxSize) {
18.424 - newSize = maxSize;
18.425 -
18.426 - if (newSize <= _arr.length) {
18.427 - // no space to get in
18.428 - throw new UnsupportedOperationException();
18.429 - }
18.430 -
18.431 - _arr = new Object[newSize];
18.432 - } else {
18.433 - // still a lot of space
18.434 - _arr = new Object[newSize + 1];
18.435 - _arr[newSize] = trashold;
18.436 - }
18.437 -
18.438 - // copy content of original array without the last Integer into
18.439 - // the new one
18.440 - System.arraycopy(currentContent, 0, _arr, 0, ((Object[]) currentContent).length - 1);
18.441 - }
18.442 - }
18.443 - }
18.444 -
18.445 - this.current = _arr;
18.446 - this.arr = null;
18.447 - } else {
18.448 - // allocate array for complete replacement
18.449 - if (ensure == maxSize) {
18.450 - this.arr = new Object[ensure];
18.451 - } else {
18.452 - this.arr = new Object[ensure + 1];
18.453 - this.arr[ensure] = trashold;
18.454 - }
18.455 -
18.456 - this.current = (currentContent instanceof Object[]) ? (Object[]) currentContent : new Object[0];
18.457 - }
18.458 - }
18.459 -
18.460 - public int addPair(AbstractLookup.Pair<?> p) {
18.461 - p.setIndex(null, cnt);
18.462 - arr[cnt++] = p;
18.463 -
18.464 - return p.getIndex();
18.465 - }
18.466 -
18.467 - public Object newContent(Object prev) {
18.468 - if (arr == null) {
18.469 - if (current == null) {
18.470 - return prev;
18.471 - } else {
18.472 - return current;
18.473 - }
18.474 - } else {
18.475 - return arr;
18.476 - }
18.477 - }
18.478 - }
18.479 - // end of Transaction
18.480 -}
19.1 --- a/lookup/src/main/java/org/openide/util/lookup/Bundle.properties Wed Jan 27 17:46:23 2010 -0500
19.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
19.3 @@ -1,1 +0,0 @@
19.4 -OpenIDE-Module-Name=Lookup
20.1 --- a/lookup/src/main/java/org/openide/util/lookup/DelegatingStorage.java Wed Jan 27 17:46:23 2010 -0500
20.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
20.3 @@ -1,180 +0,0 @@
20.4 -/*
20.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
20.6 - *
20.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
20.8 - *
20.9 - * The contents of this file are subject to the terms of either the GNU
20.10 - * General Public License Version 2 only ("GPL") or the Common
20.11 - * Development and Distribution License("CDDL") (collectively, the
20.12 - * "License"). You may not use this file except in compliance with the
20.13 - * License. You can obtain a copy of the License at
20.14 - * http://www.netbeans.org/cddl-gplv2.html
20.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
20.16 - * specific language governing permissions and limitations under the
20.17 - * License. When distributing the software, include this License Header
20.18 - * Notice in each file and include the License file at
20.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
20.20 - * particular file as subject to the "Classpath" exception as provided
20.21 - * by Sun in the GPL Version 2 section of the License file that
20.22 - * accompanied this code. If applicable, add the following below the
20.23 - * License Header, with the fields enclosed by brackets [] replaced by
20.24 - * your own identifying information:
20.25 - * "Portions Copyrighted [year] [name of copyright owner]"
20.26 - *
20.27 - * Contributor(s):
20.28 - *
20.29 - * The Original Software is NetBeans. The Initial Developer of the Original
20.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
20.31 - * Microsystems, Inc. All Rights Reserved.
20.32 - *
20.33 - * If you wish your version of this file to be governed by only the CDDL
20.34 - * or only the GPL Version 2, indicate your decision by adding
20.35 - * "[Contributor] elects to include this software in this distribution
20.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
20.37 - * single choice of license, a recipient has the option to distribute
20.38 - * your version of this file under either the CDDL, the GPL Version 2 or
20.39 - * to extend the choice of license to its licensees as provided above.
20.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
20.41 - * Version 2 license, then the option applies only if the new code is
20.42 - * made subject to such option by the copyright holder.
20.43 - */
20.44 -package org.openide.util.lookup;
20.45 -
20.46 -import org.openide.util.Lookup;
20.47 -
20.48 -import java.io.*;
20.49 -
20.50 -import java.lang.ref.WeakReference;
20.51 -
20.52 -import java.util.*;
20.53 -import org.openide.util.lookup.AbstractLookup.Pair;
20.54 -
20.55 -
20.56 -/** Storages that can switch between another storages.
20.57 - * @author Jaroslav Tulach
20.58 - */
20.59 -final class DelegatingStorage<Transaction> extends Object
20.60 -implements Serializable, AbstractLookup.Storage<Transaction> {
20.61 - /** object to delegate to */
20.62 - private AbstractLookup.Storage<Transaction> delegate;
20.63 -
20.64 - /** thread just accessing the storage */
20.65 - private Thread owner;
20.66 -
20.67 - public DelegatingStorage(AbstractLookup.Storage<Transaction> d) {
20.68 - this.delegate = d;
20.69 - this.owner = Thread.currentThread();
20.70 - }
20.71 -
20.72 - /** Never serialize yourself, always put there the delegate */
20.73 - public Object writeReplace() {
20.74 - return this.delegate;
20.75 - }
20.76 -
20.77 - /** Method to check whether there is not multiple access from the same thread.
20.78 - */
20.79 - public void checkForTreeModification() {
20.80 - if (Thread.currentThread() == owner) {
20.81 - throw new AbstractLookup.ISE("You are trying to modify lookup from lookup query!"); // NOI18N
20.82 - }
20.83 - }
20.84 -
20.85 - /** Checks whether we have simple behaviour or complex.
20.86 - */
20.87 - public static boolean isSimple(AbstractLookup.Storage s) {
20.88 - if (s instanceof DelegatingStorage) {
20.89 - return ((DelegatingStorage) s).delegate instanceof ArrayStorage;
20.90 - } else {
20.91 - return s instanceof ArrayStorage;
20.92 - }
20.93 - }
20.94 -
20.95 - /** Exits from the owners ship of the storage.
20.96 - */
20.97 - public AbstractLookup.Storage<Transaction> exitDelegate() {
20.98 - if (Thread.currentThread() != owner) {
20.99 - throw new IllegalStateException("Onwer: " + owner + " caller: " + Thread.currentThread()); // NOI18N
20.100 - }
20.101 -
20.102 - AbstractLookup.Storage<Transaction> d = delegate;
20.103 - delegate = null;
20.104 -
20.105 - return d;
20.106 - }
20.107 -
20.108 - public boolean add(AbstractLookup.Pair<?> item, Transaction transaction) {
20.109 - return delegate.add(item, transaction);
20.110 - }
20.111 -
20.112 - public void remove(org.openide.util.lookup.AbstractLookup.Pair item, Transaction transaction) {
20.113 - delegate.remove(item, transaction);
20.114 - }
20.115 -
20.116 - public void retainAll(Map retain, Transaction transaction) {
20.117 - delegate.retainAll(retain, transaction);
20.118 - }
20.119 -
20.120 - /** A special method to change the backing storage.
20.121 - * In fact it is not much typesafe as it changes the
20.122 - * type of Transaction but we know that nobody is currently
20.123 - * holding a transaction object, so there cannot be inconsitencies.
20.124 - */
20.125 - @SuppressWarnings("unchecked")
20.126 - private void changeDelegate(InheritanceTree st) {
20.127 - delegate = (AbstractLookup.Storage<Transaction>)st;
20.128 - }
20.129 -
20.130 - public Transaction beginTransaction(int ensure) {
20.131 - try {
20.132 - return delegate.beginTransaction(ensure);
20.133 - } catch (UnsupportedOperationException ex) {
20.134 - // let's convert to InheritanceTree
20.135 - ArrayStorage arr = (ArrayStorage) delegate;
20.136 - InheritanceTree inh = new InheritanceTree();
20.137 - changeDelegate(inh);
20.138 -
20.139 - //
20.140 - // Copy content
20.141 - //
20.142 - Enumeration<Pair<Object>> en = arr.lookup(Object.class);
20.143 -
20.144 - while (en.hasMoreElements()) {
20.145 - if (!inh.add(en.nextElement(), new ArrayList<Class>())) {
20.146 - throw new IllegalStateException("All objects have to be accepted"); // NOI18N
20.147 - }
20.148 - }
20.149 -
20.150 - //
20.151 - // Copy listeners
20.152 - //
20.153 - AbstractLookup.ReferenceToResult<?> ref = arr.cleanUpResult(null);
20.154 -
20.155 - if (ref != null) {
20.156 - ref.cloneList(inh);
20.157 - }
20.158 -
20.159 - // we have added the current content and now we can start transaction
20.160 - return delegate.beginTransaction(ensure);
20.161 - }
20.162 - }
20.163 -
20.164 - public org.openide.util.lookup.AbstractLookup.ReferenceToResult cleanUpResult(
20.165 - org.openide.util.Lookup.Template templ
20.166 - ) {
20.167 - return delegate.cleanUpResult(templ);
20.168 - }
20.169 -
20.170 - public void endTransaction(Transaction transaction, Set<AbstractLookup.R> modified) {
20.171 - delegate.endTransaction(transaction, modified);
20.172 - }
20.173 -
20.174 - public <T> Enumeration<Pair<T>> lookup(Class<T> clazz) {
20.175 - return delegate.lookup(clazz);
20.176 - }
20.177 -
20.178 - public org.openide.util.lookup.AbstractLookup.ReferenceToResult registerReferenceToResult(
20.179 - org.openide.util.lookup.AbstractLookup.ReferenceToResult newRef
20.180 - ) {
20.181 - return delegate.registerReferenceToResult(newRef);
20.182 - }
20.183 -}
21.1 --- a/lookup/src/main/java/org/openide/util/lookup/ExcludingLookup.java Wed Jan 27 17:46:23 2010 -0500
21.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
21.3 @@ -1,428 +0,0 @@
21.4 -/*
21.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
21.6 - *
21.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
21.8 - *
21.9 - * The contents of this file are subject to the terms of either the GNU
21.10 - * General Public License Version 2 only ("GPL") or the Common
21.11 - * Development and Distribution License("CDDL") (collectively, the
21.12 - * "License"). You may not use this file except in compliance with the
21.13 - * License. You can obtain a copy of the License at
21.14 - * http://www.netbeans.org/cddl-gplv2.html
21.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
21.16 - * specific language governing permissions and limitations under the
21.17 - * License. When distributing the software, include this License Header
21.18 - * Notice in each file and include the License file at
21.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
21.20 - * particular file as subject to the "Classpath" exception as provided
21.21 - * by Sun in the GPL Version 2 section of the License file that
21.22 - * accompanied this code. If applicable, add the following below the
21.23 - * License Header, with the fields enclosed by brackets [] replaced by
21.24 - * your own identifying information:
21.25 - * "Portions Copyrighted [year] [name of copyright owner]"
21.26 - *
21.27 - * Contributor(s):
21.28 - *
21.29 - * The Original Software is NetBeans. The Initial Developer of the Original
21.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
21.31 - * Microsystems, Inc. All Rights Reserved.
21.32 - *
21.33 - * If you wish your version of this file to be governed by only the CDDL
21.34 - * or only the GPL Version 2, indicate your decision by adding
21.35 - * "[Contributor] elects to include this software in this distribution
21.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
21.37 - * single choice of license, a recipient has the option to distribute
21.38 - * your version of this file under either the CDDL, the GPL Version 2 or
21.39 - * to extend the choice of license to its licensees as provided above.
21.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
21.41 - * Version 2 license, then the option applies only if the new code is
21.42 - * made subject to such option by the copyright holder.
21.43 - */
21.44 -package org.openide.util.lookup;
21.45 -
21.46 -import java.lang.ref.Reference;
21.47 -import java.lang.ref.WeakReference;
21.48 -import org.openide.util.Lookup;
21.49 -import org.openide.util.LookupListener;
21.50 -
21.51 -import java.util.*;
21.52 -import org.openide.util.LookupEvent;
21.53 -
21.54 -
21.55 -/** Allows exclusion of certain instances from lookup.
21.56 - *
21.57 - * @author Jaroslav Tulach
21.58 - */
21.59 -final class ExcludingLookup extends org.openide.util.Lookup {
21.60 - /** the other lookup that we delegate to */
21.61 - private Lookup delegate;
21.62 -
21.63 - /** classes to exclude (Class[]) or just one class (Class) */
21.64 - private Object classes;
21.65 -
21.66 - /**
21.67 - * Creates new Result object with supplied instances parameter.
21.68 - * @param instances to be used to return from the lookup
21.69 - */
21.70 - ExcludingLookup(Lookup delegate, Class[] classes) {
21.71 - this.delegate = delegate;
21.72 -
21.73 - for (Class c : classes) {
21.74 - if (c == null) {
21.75 - throw new NullPointerException();
21.76 - }
21.77 - }
21.78 - if (classes.length == 1) {
21.79 - this.classes = classes[0];
21.80 - } else {
21.81 - this.classes = classes;
21.82 - }
21.83 - }
21.84 -
21.85 - @Override
21.86 - public String toString() {
21.87 - return "ExcludingLookup: " + delegate + " excludes: " + Arrays.asList(classes()); // NOI18N
21.88 - }
21.89 -
21.90 - public <T> Result<T> lookup(Template<T> template) {
21.91 - if (template == null) {
21.92 - throw new NullPointerException();
21.93 - }
21.94 -
21.95 - if (areSubclassesOfThisClassAlwaysExcluded(template.getType())) {
21.96 - // empty result
21.97 - return Lookup.EMPTY.lookup(template);
21.98 - }
21.99 -
21.100 - return new R<T>(template.getType(), delegate.lookup(template));
21.101 - }
21.102 -
21.103 - public <T> T lookup(Class<T> clazz) {
21.104 - if (areSubclassesOfThisClassAlwaysExcluded(clazz)) {
21.105 - return null;
21.106 - }
21.107 -
21.108 - T res = delegate.lookup(clazz);
21.109 -
21.110 - if (isObjectAccessible(clazz, res, 0)) {
21.111 - return res;
21.112 - } else {
21.113 - return null;
21.114 - }
21.115 - }
21.116 -
21.117 - @Override
21.118 - public <T> Lookup.Item<T> lookupItem(Lookup.Template<T> template) {
21.119 - if (areSubclassesOfThisClassAlwaysExcluded(template.getType())) {
21.120 - return null;
21.121 - }
21.122 -
21.123 - Lookup.Item<T> retValue = delegate.lookupItem(template);
21.124 -
21.125 - if (isObjectAccessible(template.getType(), retValue, 2)) {
21.126 - return retValue;
21.127 - } else {
21.128 - return null;
21.129 - }
21.130 - }
21.131 -
21.132 - /** @return true if the instance of class c shall never be returned from this lookup
21.133 - */
21.134 - private boolean areSubclassesOfThisClassAlwaysExcluded(Class<?> c) {
21.135 - Class<?>[] arr = classes();
21.136 -
21.137 - for (int i = 0; i < arr.length; i++) {
21.138 - if (arr[i].isAssignableFrom(c)) {
21.139 - return true;
21.140 - }
21.141 - }
21.142 -
21.143 - return false;
21.144 - }
21.145 -
21.146 - /** Returns the array of classes this lookup filters.
21.147 - */
21.148 - final Class<?>[] classes() {
21.149 - if (classes instanceof Class[]) {
21.150 - return (Class[]) classes;
21.151 - } else {
21.152 - return new Class[] { (Class) classes };
21.153 - }
21.154 - }
21.155 -
21.156 - /** Does a check whether two classes are accessible (in the super/sub class)
21.157 - * releation ship without walking thru any of the classes mentioned in the
21.158 - * barrier.
21.159 - */
21.160 - private static boolean isAccessible(Class<?>[] barriers, Class<?> from, Class<?> to) {
21.161 - if ((to == null) || !from.isAssignableFrom(to)) {
21.162 - // no way to reach each other by walking up
21.163 - return false;
21.164 - }
21.165 -
21.166 - for (int i = 0; i < barriers.length; i++) {
21.167 - if (to == barriers[i]) {
21.168 - return false;
21.169 - }
21.170 - }
21.171 -
21.172 - if (from == to) {
21.173 - return true;
21.174 - }
21.175 -
21.176 - //
21.177 - // depth first search
21.178 - //
21.179 - if (isAccessible(barriers, from, to.getSuperclass())) {
21.180 - return true;
21.181 - }
21.182 -
21.183 - Class[] interfaces = to.getInterfaces();
21.184 -
21.185 - for (int i = 0; i < interfaces.length; i++) {
21.186 - if (isAccessible(barriers, from, interfaces[i])) {
21.187 - return true;
21.188 - }
21.189 - }
21.190 -
21.191 - return false;
21.192 - }
21.193 -
21.194 - /** based on type decides whether the class accepts or not anObject
21.195 - * @param from the base type of the query
21.196 - * @param to depending on value of type either Object, Class or Item
21.197 - * @param type 0,1,2 for Object, Class or Item
21.198 - * @return true if we can access the to from from by walking around the bariers
21.199 - */
21.200 - private final boolean isObjectAccessible(Class from, Object to, int type) {
21.201 - if (to == null) {
21.202 - return false;
21.203 - }
21.204 -
21.205 - return isObjectAccessible(classes(), from, to, type);
21.206 - }
21.207 -
21.208 - /** based on type decides whether the class accepts or not anObject
21.209 - * @param barriers classes to avoid when testing reachability
21.210 - * @param from the base type of the query
21.211 - * @param to depending on value of type either Object, Class or Item
21.212 - * @param type 0,1,2 for Object, Class or Item
21.213 - * @return true if we can access the to from from by walking around the bariers
21.214 - */
21.215 - static final boolean isObjectAccessible(Class[] barriers, Class from, Object to, int type) {
21.216 - if (to == null) {
21.217 - return false;
21.218 - }
21.219 -
21.220 - switch (type) {
21.221 - case 0:
21.222 - return isAccessible(barriers, from, to.getClass());
21.223 -
21.224 - case 1:
21.225 - return isAccessible(barriers, from, (Class) to);
21.226 -
21.227 - case 2: {
21.228 - Item item = (Item) to;
21.229 -
21.230 - return isAccessible(barriers, from, item.getType());
21.231 - }
21.232 -
21.233 - default:
21.234 - throw new IllegalStateException("Type: " + type);
21.235 - }
21.236 - }
21.237 -
21.238 - /** Filters collection accroding to set of given filters.
21.239 - */
21.240 - final <E, T extends Collection<E>> T filter(
21.241 - Class<?>[] arr, Class<?> from, T c, int type, T prototype
21.242 - ) {
21.243 - T ret = null;
21.244 -
21.245 -
21.246 -// optimistic strategy expecting we will not need to filter
21.247 -TWICE:
21.248 - for (;;) {
21.249 - Iterator<E> it = c.iterator();
21.250 -BIG:
21.251 - while (it.hasNext()) {
21.252 - E res = it.next();
21.253 -
21.254 - if (!isObjectAccessible(arr, from, res, type)) {
21.255 - if (ret == null) {
21.256 - // we need to restart the scanning again
21.257 - // as there is an active filter
21.258 - ret = prototype;
21.259 - continue TWICE;
21.260 - }
21.261 -
21.262 - continue BIG;
21.263 - }
21.264 -
21.265 - if (ret != null) {
21.266 - // if we are running the second round from TWICE
21.267 - ret.add(res);
21.268 - }
21.269 - }
21.270 -
21.271 - // ok, processed
21.272 - break TWICE;
21.273 - }
21.274 -
21.275 - return (ret != null) ? ret : c;
21.276 - }
21.277 -
21.278 - /** Delegating result that filters unwanted items and instances.
21.279 - */
21.280 - private final class R<T> extends WaitableResult<T> implements LookupListener {
21.281 - private Result<T> result;
21.282 - private WeakResult<T> weak;
21.283 - private Object listeners;
21.284 - private Class<?> from;
21.285 -
21.286 - R(Class<?> from, Result<T> delegate) {
21.287 - this.from = from;
21.288 - this.result = delegate;
21.289 - this.weak = new WeakResult<T>(this, delegate);
21.290 - }
21.291 -
21.292 - protected void beforeLookup(Template t) {
21.293 - if (result instanceof WaitableResult) {
21.294 - ((WaitableResult) result).beforeLookup(t);
21.295 - }
21.296 - }
21.297 -
21.298 - public void addLookupListener(LookupListener l) {
21.299 - boolean add;
21.300 -
21.301 - synchronized (this) {
21.302 - listeners = AbstractLookup.modifyListenerList(true, l, listeners);
21.303 - add = listeners != null;
21.304 - }
21.305 -
21.306 - if (add) {
21.307 - result.addLookupListener(weak);
21.308 - }
21.309 - }
21.310 -
21.311 - public void removeLookupListener(LookupListener l) {
21.312 - boolean remove;
21.313 -
21.314 - synchronized (this) {
21.315 - listeners = AbstractLookup.modifyListenerList(false, l, listeners);
21.316 - remove = listeners == null;
21.317 - }
21.318 -
21.319 - if (remove) {
21.320 - result.removeLookupListener(weak);
21.321 - }
21.322 - }
21.323 -
21.324 - public Collection<? extends T> allInstances() {
21.325 - return openCol(result.allInstances(), 0);
21.326 - }
21.327 -
21.328 - private <S> Collection<S> openCol(Collection<S> c, int type) {
21.329 - return filter(classes(), from, c, type, new ArrayList<S>(c.size()));
21.330 - }
21.331 -
21.332 - @Override
21.333 - public Set<Class<? extends T>> allClasses() {
21.334 - return filter(classes(), from, result.allClasses(), 1, new HashSet<Class<? extends T>>());
21.335 - }
21.336 -
21.337 - @Override
21.338 - public Collection<? extends Item<T>> allItems() {
21.339 - return openCol(result.allItems(), 2);
21.340 - }
21.341 -
21.342 - public void resultChanged(org.openide.util.LookupEvent ev) {
21.343 - if (ev.getSource() == result) {
21.344 - collectFires(null);
21.345 - }
21.346 - }
21.347 -
21.348 - protected void collectFires(Collection<Object> evAndListeners) {
21.349 - LookupListener[] arr;
21.350 -
21.351 - synchronized (this) {
21.352 - if (listeners == null) {
21.353 - return;
21.354 - }
21.355 -
21.356 - if (listeners instanceof LookupListener) {
21.357 - arr = new LookupListener[] { (LookupListener) listeners };
21.358 - } else {
21.359 - ArrayList<?> l = (ArrayList<?>) listeners;
21.360 - arr = l.toArray(new LookupListener[l.size()]);
21.361 - }
21.362 - }
21.363 -
21.364 - final LookupListener[] ll = arr;
21.365 - final org.openide.util.LookupEvent newev = new org.openide.util.LookupEvent(this);
21.366 - AbstractLookup.notifyListeners(ll, newev, evAndListeners);
21.367 - }
21.368 - } // end of R
21.369 -
21.370 - private final class WeakResult<T> extends WaitableResult<T> implements LookupListener {
21.371 - private Lookup.Result source;
21.372 - private Reference<R<T>> result;
21.373 -
21.374 - public WeakResult(R<T> r, Lookup.Result<T> s) {
21.375 - this.result = new WeakReference<R<T>>(r);
21.376 - this.source = s;
21.377 - }
21.378 -
21.379 - protected void beforeLookup(Lookup.Template t) {
21.380 - R r = (R)result.get();
21.381 - if (r != null) {
21.382 - r.beforeLookup(t);
21.383 - } else {
21.384 - source.removeLookupListener(this);
21.385 - }
21.386 - }
21.387 -
21.388 - protected void collectFires(Collection<Object> evAndListeners) {
21.389 - R<T> r = result.get();
21.390 - if (r != null) {
21.391 - r.collectFires(evAndListeners);
21.392 - } else {
21.393 - source.removeLookupListener(this);
21.394 - }
21.395 - }
21.396 -
21.397 - public void addLookupListener(LookupListener l) {
21.398 - assert false;
21.399 - }
21.400 -
21.401 - public void removeLookupListener(LookupListener l) {
21.402 - assert false;
21.403 - }
21.404 -
21.405 - public Collection<T> allInstances() {
21.406 - assert false;
21.407 - return null;
21.408 - }
21.409 -
21.410 - public void resultChanged(LookupEvent ev) {
21.411 - R r = (R)result.get();
21.412 - if (r != null) {
21.413 - r.resultChanged(ev);
21.414 - } else {
21.415 - source.removeLookupListener(this);
21.416 - }
21.417 - }
21.418 -
21.419 - @Override
21.420 - public Collection<? extends Item<T>> allItems() {
21.421 - assert false;
21.422 - return null;
21.423 - }
21.424 -
21.425 - @Override
21.426 - public Set<Class<? extends T>> allClasses() {
21.427 - assert false;
21.428 - return null;
21.429 - }
21.430 - } // end of WeakResult
21.431 -}
22.1 --- a/lookup/src/main/java/org/openide/util/lookup/InheritanceTree.java Wed Jan 27 17:46:23 2010 -0500
22.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
22.3 @@ -1,1276 +0,0 @@
22.4 -/*
22.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
22.6 - *
22.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
22.8 - *
22.9 - * The contents of this file are subject to the terms of either the GNU
22.10 - * General Public License Version 2 only ("GPL") or the Common
22.11 - * Development and Distribution License("CDDL") (collectively, the
22.12 - * "License"). You may not use this file except in compliance with the
22.13 - * License. You can obtain a copy of the License at
22.14 - * http://www.netbeans.org/cddl-gplv2.html
22.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
22.16 - * specific language governing permissions and limitations under the
22.17 - * License. When distributing the software, include this License Header
22.18 - * Notice in each file and include the License file at
22.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
22.20 - * particular file as subject to the "Classpath" exception as provided
22.21 - * by Sun in the GPL Version 2 section of the License file that
22.22 - * accompanied this code. If applicable, add the following below the
22.23 - * License Header, with the fields enclosed by brackets [] replaced by
22.24 - * your own identifying information:
22.25 - * "Portions Copyrighted [year] [name of copyright owner]"
22.26 - *
22.27 - * Contributor(s):
22.28 - *
22.29 - * The Original Software is NetBeans. The Initial Developer of the Original
22.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
22.31 - * Microsystems, Inc. All Rights Reserved.
22.32 - *
22.33 - * If you wish your version of this file to be governed by only the CDDL
22.34 - * or only the GPL Version 2, indicate your decision by adding
22.35 - * "[Contributor] elects to include this software in this distribution
22.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
22.37 - * single choice of license, a recipient has the option to distribute
22.38 - * your version of this file under either the CDDL, the GPL Version 2 or
22.39 - * to extend the choice of license to its licensees as provided above.
22.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
22.41 - * Version 2 license, then the option applies only if the new code is
22.42 - * made subject to such option by the copyright holder.
22.43 - */
22.44 -package org.openide.util.lookup;
22.45 -
22.46 -import org.openide.util.Lookup;
22.47 -import org.openide.util.lookup.AbstractLookup.Pair;
22.48 -import org.openide.util.lookup.AbstractLookup.ReferenceIterator;
22.49 -import org.openide.util.lookup.AbstractLookup.ReferenceToResult;
22.50 -
22.51 -import java.io.*;
22.52 -
22.53 -import java.lang.ref.WeakReference;
22.54 -
22.55 -import java.util.*;
22.56 -
22.57 -
22.58 -/** A tree to represent classes with inheritance. Description of the
22.59 - * data structure by Petr Nejedly:
22.60 - * <P>
22.61 - * So pretend I'm Lookup implementation. I've got a bunch of Items (e.g.
22.62 - * setPairs() method),
22.63 - * didn't do anything on them yet (no startup penalty) so I know nothing
22.64 - * about them.
22.65 - * Then I'll be asked for all instances implementing given interface or a
22.66 - * class. I surely need
22.67 - * to check all the Items now, as I don't know anything abou them. I surely
22.68 - * don't want to call
22.69 - * Item.getClass() as it will dismiss the whole effort. So all I have is
22.70 - * Item.instanceOf()
22.71 - * and I'll call it on every Item. I'll cache results, so the next time
22.72 - * you'll ask me for
22.73 - * the same interface/class, I'll answer immediatelly. But what if you ask
22.74 - * me for another
22.75 - * interface/class? I'll have to scan all Items for it again, unless I can
22.76 - * be sure some
22.77 - * of them can't implement it. The only source of this knowledge are the
22.78 - * previous questions
22.79 - * and my rulings on them. Here the algorithm have to be split into two
22.80 - * paths. If you
22.81 - * previously asked me for interfaces only, I'll have no hint for
22.82 - * subsequent queries,
22.83 - * but if you asked me for a class in history, and then for another class
22.84 - * and these classes
22.85 - * are not in inheritance relation (I can check hierarchy of lookup
22.86 - * arguments, because
22.87 - * they are already resolved/loaded) I can tell that those returned in
22.88 - * previous query can't
22.89 - * implement the newly asked class (they are in different hierarchy branch)
22.90 - * and I need to
22.91 - * ask less Items.
22.92 - * <P>
22.93 - * So if we use mostly classes for asking for services (and it is a trend
22.94 - * to use
22.95 - * abstract classes for this purpose in IDE anyway), this could be usable.
22.96 - * <P>
22.97 - * The data structure for separating the Items based on previous queries is
22.98 - * simple
22.99 - * tree, with every node tagged with one class. The tree's root is,
22.100 - * naturally,
22.101 - * java.lang.Object, is marked invited and initially contains all the
22.102 - * Items.
22.103 - * For every class query, the missing part of class hierarchy tree is
22.104 - * created,
22.105 - * the node of the class looked up is marked as invited and all Items from
22.106 - * nearest
22.107 - * invited parent (sperclass) are dragged to this node. The result are then
22.108 - * all
22.109 - * Items from this node and all the nodes deeper in hierarchy. Because it
22.110 - * may
22.111 - * be too complicated to walk through the children nodes, the results could
22.112 - * be
22.113 - * cached in the map.
22.114 - * For interface lookup, there is a little hint in reality (interfaces
22.115 - * and superinterfaces), but it would be harder to exploit it, so we could
22.116 - * fall-back
22.117 - * to walking through all the Items and cache results.
22.118 - *
22.119 - *
22.120 - * @author Jaroslav Tulach
22.121 - */
22.122 -final class InheritanceTree extends Object
22.123 -implements Serializable, AbstractLookup.Storage<ArrayList<Class>> {
22.124 - private static final long serialVersionUID = 1L;
22.125 -
22.126 - /** the root item (represents Object) */
22.127 - private transient Node object;
22.128 -
22.129 - /** Map of queried interfaces.
22.130 - * <p>Type: <code>Map<Class, (Collection<AbstractLookup.Pair> | AbstractLookup.Pair)></code>
22.131 - */
22.132 - private transient Map<Class,Object> interfaces;
22.133 -
22.134 - /** Map (Class, ReferenceToResult) of all listeners that are waiting in
22.135 - * changes in class Class
22.136 - */
22.137 - private transient Map<Class,ReferenceToResult> reg;
22.138 -
22.139 - /** Constructor
22.140 - */
22.141 - public InheritanceTree() {
22.142 - object = new Node(java.lang.Object.class);
22.143 - }
22.144 -
22.145 - private void writeObject(ObjectOutputStream oos) throws IOException {
22.146 - oos.writeObject(object);
22.147 -
22.148 - if (interfaces != null) {
22.149 - Iterator it = interfaces.entrySet().iterator();
22.150 -
22.151 - while (it.hasNext()) {
22.152 - Map.Entry e = (Map.Entry) it.next();
22.153 - Class c = (Class) e.getKey();
22.154 - oos.writeObject(c.getName());
22.155 -
22.156 - Object o = e.getValue();
22.157 -
22.158 - if (!(o instanceof Collection) && !(o instanceof AbstractLookup.Pair)) {
22.159 - throw new ClassCastException(String.valueOf(o));
22.160 - }
22.161 -
22.162 - oos.writeObject(o);
22.163 - }
22.164 - }
22.165 -
22.166 - oos.writeObject(null);
22.167 - }
22.168 -
22.169 - private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
22.170 - object = (Node) ois.readObject();
22.171 - interfaces = new WeakHashMap<Class,Object>();
22.172 -
22.173 - String clazz;
22.174 - ClassLoader l = Lookup.getDefault().lookup(ClassLoader.class);
22.175 -
22.176 - while ((clazz = (String) ois.readObject()) != null) {
22.177 - Object o = ois.readObject();
22.178 -
22.179 - if (!(o instanceof Collection) && !(o instanceof AbstractLookup.Pair)) {
22.180 - throw new ClassCastException(String.valueOf(o));
22.181 - }
22.182 -
22.183 - Class c = Class.forName(clazz, false, l);
22.184 - interfaces.put(c, o);
22.185 - }
22.186 - }
22.187 -
22.188 - /** Adds an item into the tree.
22.189 - * @param item to add
22.190 - * @return true if the Item has been added for the first time or false if some other
22.191 - * item equal to this one already existed in the lookup
22.192 - */
22.193 - public boolean add(AbstractLookup.Pair<?> item, ArrayList<Class> affected) {
22.194 - Node node = registerClass(object, item);
22.195 -
22.196 - affected.add(node.getType());
22.197 -
22.198 - if (node.assignItem(this, item)) {
22.199 - // this is the first item added to n.items
22.200 - // ok, we have to test interfaces too
22.201 - } else {
22.202 - // equal item is already there => stop processing
22.203 - return false;
22.204 - }
22.205 -
22.206 - boolean registeredAsInterface = registerInterface(item, affected);
22.207 -
22.208 - return registeredAsInterface;
22.209 - }
22.210 -
22.211 - /** Removes an item.
22.212 - */
22.213 - public void remove(AbstractLookup.Pair item, ArrayList<Class> affected) {
22.214 - Node n = removeClass(object, item);
22.215 -
22.216 - if (n != null) {
22.217 - affected.add(n.getType());
22.218 - }
22.219 -
22.220 - removeInterface(item, affected);
22.221 - }
22.222 -
22.223 - /** Removes all items that are not present in the provided collection.
22.224 - * @param retain collection of Pairs to keep them in
22.225 - * @param notify set of Classes that has possibly changed
22.226 - */
22.227 - public void retainAll(Map retain, ArrayList<Class> notify) {
22.228 - retainAllInterface(retain, notify);
22.229 - retainAllClasses(object, retain, notify);
22.230 - }
22.231 -
22.232 - /** Queries for instances of given class.
22.233 - * @param clazz the class to check
22.234 - * @return enumeration of Item
22.235 - * @see #unsorted
22.236 - */
22.237 - @SuppressWarnings("unchecked")
22.238 - public <T> Enumeration<Pair<T>> lookup(Class<T> clazz) {
22.239 - if ((clazz != null) && clazz.isInterface()) {
22.240 - return (Enumeration)searchInterface(clazz);
22.241 - } else {
22.242 - return (Enumeration)searchClass(object, clazz);
22.243 - }
22.244 - }
22.245 -
22.246 - /** A method to check whether the enumeration returned from
22.247 - * lookup method is sorted or is not
22.248 - * @param en enumeration to check
22.249 - * @return true if it is unsorted and needs to be sorted to find
22.250 - * pair with smallest index
22.251 - */
22.252 - public static boolean unsorted(Enumeration en) {
22.253 - return en instanceof NeedsSortEnum;
22.254 - }
22.255 -
22.256 - /** Prints debug messages.
22.257 - * @param out stream to output to
22.258 - * @param instances print also instances of the
22.259 - */
22.260 - public void print(java.io.PrintStream out, boolean instances) {
22.261 - printNode(object, "", out, instances); // NOI18N
22.262 - }
22.263 -
22.264 - //
22.265 - // methods to work on classes which are not interfaces
22.266 - //
22.267 -
22.268 - /** Searches the subtree and register the item where necessary.
22.269 - * @return the node that should contain the item
22.270 - */
22.271 - private static Node registerClass(Node n, AbstractLookup.Pair item) {
22.272 - if (!n.accepts(item)) {
22.273 - return null;
22.274 - }
22.275 -
22.276 - if (n.children != null) {
22.277 - Iterator it = n.children.iterator();
22.278 -
22.279 - for (;;) {
22.280 - Node ch = extractNode(it);
22.281 -
22.282 - if (ch == null) {
22.283 - break;
22.284 - }
22.285 -
22.286 - Node result = registerClass(ch, item);
22.287 -
22.288 - if (result != null) {
22.289 - // it is in subclass, in case of classes, it cannot
22.290 - // be any other class
22.291 - return result;
22.292 - }
22.293 - }
22.294 - }
22.295 -
22.296 - // ok, nobody of our subclasses wants the class, I'll take it
22.297 - return n;
22.298 - }
22.299 -
22.300 - /** Removes the item from the tree of objects.
22.301 - * @return most narrow class that this item was removed from
22.302 - */
22.303 - private static Node removeClass(Node n, AbstractLookup.Pair item) {
22.304 - if (!n.accepts(item)) {
22.305 - return null;
22.306 - }
22.307 -
22.308 - if ((n.items != null) && n.items.remove(item)) {
22.309 - // this node really contains the item
22.310 - return n;
22.311 - }
22.312 -
22.313 - if (n.children != null) {
22.314 - Iterator it = n.children.iterator();
22.315 -
22.316 - for (;;) {
22.317 - Node ch = extractNode(it);
22.318 -
22.319 - if (ch == null) {
22.320 - break;
22.321 - }
22.322 -
22.323 - Node result = removeClass(ch, item);
22.324 -
22.325 - // If the children node was emptied, remove it if possible.
22.326 - if (((ch.items == null) || ch.items.isEmpty()) && ((ch.children == null) || ch.children.isEmpty())) {
22.327 - it.remove();
22.328 - }
22.329 -
22.330 - if (result != null) {
22.331 - // it is in subclass, in case of classes, it cannot
22.332 - // be any other class
22.333 - return result;
22.334 - }
22.335 - }
22.336 - }
22.337 -
22.338 - // nobody found
22.339 - return null;
22.340 - }
22.341 -
22.342 - /** Finds a node that represents a class.
22.343 - * @param n node to search from
22.344 - * @param clazz the clazz to find
22.345 - * @return node that represents clazz in the tree or null if the clazz is not
22.346 - * represented under the node n
22.347 - */
22.348 - private Node classToNode(final Node n, final Class<?> clazz) {
22.349 - if (!n.accepts(clazz)) {
22.350 - // nothing from us
22.351 - return null;
22.352 - }
22.353 -
22.354 - if (n.getType() == clazz) {
22.355 - // we have found what we need
22.356 - return n;
22.357 - }
22.358 -
22.359 - if (n.children != null) {
22.360 - // have to proceed to children
22.361 - Iterator it = n.children.iterator();
22.362 -
22.363 - for (;;) {
22.364 - final Node ch = extractNode(it);
22.365 -
22.366 - if (ch == null) {
22.367 - break;
22.368 - }
22.369 -
22.370 - Node found = classToNode(ch, clazz);
22.371 -
22.372 - if ((found != null) && ch.deserialized()) {
22.373 - class VerifyJob implements AbstractLookup.ISE.Job {
22.374 - private AbstractLookup.Pair<?>[] pairs;
22.375 - private boolean[] answers;
22.376 -
22.377 - public VerifyJob(Collection<Pair> items) {
22.378 - if (items != null) {
22.379 - pairs = items.toArray(new AbstractLookup.Pair[0]);
22.380 - }
22.381 - }
22.382 -
22.383 - public void before() {
22.384 - // make sure the node is converted into deserialized state
22.385 - ch.deserialized();
22.386 -
22.387 - if (pairs != null) {
22.388 - answers = new boolean[pairs.length];
22.389 -
22.390 - for (int i = 0; i < pairs.length; i++) {
22.391 - answers[i] = pairs[i].instanceOf(clazz);
22.392 - }
22.393 - }
22.394 - }
22.395 -
22.396 - public void inside() {
22.397 - if (pairs != null) {
22.398 - for (int i = 0; i < pairs.length; i++) {
22.399 - if (answers[i]) {
22.400 - ch.assignItem(InheritanceTree.this, pairs[i]);
22.401 - n.items.remove(pairs[i]);
22.402 - }
22.403 - }
22.404 - }
22.405 -
22.406 - if (n.children != null) {
22.407 - // consolidate all nodes that represent the same class
22.408 - HashMap<Class,Node> nodes = new HashMap<Class,Node>(n.children.size() * 3);
22.409 -
22.410 - Iterator child = n.children.iterator();
22.411 -
22.412 - while (child.hasNext()) {
22.413 - Node node = extractNode(child);
22.414 - if (node == null) {
22.415 - continue;
22.416 - }
22.417 - Node prev = nodes.put(node.getType(), node);
22.418 -
22.419 - if (prev != null) {
22.420 - child.remove();
22.421 - nodes.put(node.getType(), prev);
22.422 -
22.423 - // mark as being deserialized
22.424 - prev.markDeserialized();
22.425 -
22.426 - if (prev.children == null) {
22.427 - prev.children = node.children;
22.428 - } else {
22.429 - if (node.children != null) {
22.430 - prev.children.addAll(node.children);
22.431 - }
22.432 - }
22.433 -
22.434 - if (node.items != null) {
22.435 - Iterator items = node.items.iterator();
22.436 -
22.437 - while (items.hasNext()) {
22.438 - AbstractLookup.Pair item = (AbstractLookup.Pair) items.next();
22.439 - prev.assignItem(InheritanceTree.this, item);
22.440 - }
22.441 - }
22.442 - }
22.443 - }
22.444 - }
22.445 - }
22.446 - }
22.447 -
22.448 - VerifyJob verify = new VerifyJob(n.items);
22.449 -
22.450 - try {
22.451 - verify.before();
22.452 - } catch (AbstractLookup.ISE ex) {
22.453 - // mark deserialized again
22.454 - ch.markDeserialized();
22.455 - ex.registerJob(verify);
22.456 - throw ex;
22.457 - }
22.458 -
22.459 - verify.inside();
22.460 -
22.461 - found = classToNode(ch, clazz);
22.462 - }
22.463 -
22.464 - if (found != null) {
22.465 - // class found in one of subnodes
22.466 - return found;
22.467 - }
22.468 - }
22.469 - }
22.470 -
22.471 - class TwoJobs implements AbstractLookup.ISE.Job {
22.472 - private AbstractLookup.Pair[] pairs;
22.473 - private boolean[] answers;
22.474 - private Node newNode;
22.475 -
22.476 - public void before() {
22.477 - // have to create new subnode and possibly reparent one of my own
22.478 - // but all changes can be done only if we will not be interrupted from
22.479 - // outside - e.g. instanceOf methods will not throw exception
22.480 - // first of all let's compute the answers to method instanceOf
22.481 - AbstractLookup.Pair[] arr = null;
22.482 - boolean[] boolArr = null;
22.483 -
22.484 - if (n.items != null) {
22.485 - arr = new AbstractLookup.Pair[n.items.size()];
22.486 - boolArr = new boolean[n.items.size()];
22.487 -
22.488 - int i = 0;
22.489 - Iterator<Pair> it = n.items.iterator();
22.490 -
22.491 - while (it.hasNext()) {
22.492 - AbstractLookup.Pair<?> item = it.next();
22.493 - arr[i] = item;
22.494 - boolArr[i] = item.instanceOf(clazz);
22.495 - i++;
22.496 - }
22.497 - }
22.498 -
22.499 - pairs = arr;
22.500 - answers = boolArr;
22.501 - }
22.502 -
22.503 - public void inside() {
22.504 - // test if the query has not chagned since
22.505 - if (pairs != null) {
22.506 - if (!Arrays.equals(n.items.toArray(), pairs)) {
22.507 - // ok, let try once more
22.508 - return;
22.509 - }
22.510 - }
22.511 -
22.512 - internal();
22.513 - }
22.514 -
22.515 - public void internal() {
22.516 - ArrayList<Node> reparent = null;
22.517 -
22.518 - if (n.children == null) {
22.519 - n.children = new ArrayList<Node>();
22.520 - } else {
22.521 - // scan thru all my nodes if some of them are not a subclass
22.522 - // of clazz => then they would need to become child of newNode
22.523 - Iterator it = n.children.iterator();
22.524 -
22.525 - for (;;) {
22.526 - Node r = extractNode(it);
22.527 -
22.528 - if (r == null) {
22.529 - break;
22.530 - }
22.531 -
22.532 - if (clazz.isAssignableFrom(r.getType())) {
22.533 - if (reparent == null) {
22.534 - reparent = new ArrayList<Node>();
22.535 - }
22.536 -
22.537 - reparent.add(r);
22.538 - it.remove();
22.539 - }
22.540 - }
22.541 - }
22.542 -
22.543 - newNode = new Node(clazz);
22.544 - n.children.add(newNode);
22.545 -
22.546 - if (reparent != null) {
22.547 - // reassing reparent node as a child of newNode
22.548 - newNode.children = reparent;
22.549 - }
22.550 -
22.551 - // now take all my items that are instances of that class and
22.552 - // reasign them
22.553 - if (n.items != null) {
22.554 - Iterator it = n.items.iterator();
22.555 - int i = 0;
22.556 -
22.557 - while (it.hasNext()) {
22.558 - AbstractLookup.Pair item = (AbstractLookup.Pair) it.next();
22.559 -
22.560 - if (answers[i]) { // answers[i] is precomputed value of item.instanceOf (clazz))
22.561 - it.remove();
22.562 - newNode.assignItem(InheritanceTree.this, pairs[i]);
22.563 - }
22.564 -
22.565 - i++;
22.566 - }
22.567 - }
22.568 - }
22.569 - }
22.570 -
22.571 - TwoJobs j = new TwoJobs();
22.572 -
22.573 - try {
22.574 - j.before();
22.575 - } catch (AbstractLookup.ISE ex) {
22.576 - // ok, it is not possible to call instanceOf now, let's
22.577 - // schedule it for later
22.578 - // so register recovery job
22.579 - ex.registerJob(j);
22.580 - throw ex;
22.581 - }
22.582 -
22.583 - j.internal();
22.584 -
22.585 - // newNode represents my clazz
22.586 - return j.newNode;
22.587 - }
22.588 -
22.589 - /** Search for a requested class.
22.590 - * @return enumeration of Pair
22.591 - */
22.592 - private Enumeration<Pair> searchClass(Node n, Class<?> clazz) {
22.593 - if (clazz != null) {
22.594 - n = classToNode(n, clazz);
22.595 - }
22.596 -
22.597 - if (n == null) {
22.598 - // not for us
22.599 - return emptyEn();
22.600 - } else {
22.601 - return nodeToEnum(n);
22.602 - }
22.603 - }
22.604 -
22.605 - /** Retains all classes. Removes nodes which items and children are emptied, works
22.606 - * recursivelly from specified root node.
22.607 - * @param node root node from which to start to process the tree
22.608 - * @param retain a map from (Item, AbstractLookup.Info) that describes which items to retain
22.609 - * and witch integer to assign them
22.610 - * @param notify collection of classes will be changed
22.611 - * @return <code>true<code> if some items were changed and node items and children are emptied,
22.612 - * those nodes, excluding root, will be removed from tree */
22.613 - private boolean retainAllClasses(Node node, Map retain, Collection<Class> notify) {
22.614 - boolean retained = false;
22.615 -
22.616 - if ((node.items != null) && (retain != null)) {
22.617 - Iterator<Pair> it = node.items.iterator();
22.618 -
22.619 - while (it.hasNext()) {
22.620 - AbstractLookup.Pair<?> item = it.next();
22.621 - AbstractLookup.Info n = (AbstractLookup.Info) retain.remove(item);
22.622 -
22.623 - if (n == null) {
22.624 - // remove this item, it should not be there
22.625 - it.remove();
22.626 - retained = true;
22.627 - } else {
22.628 - // change the index
22.629 - if (item.getIndex() != n.index) {
22.630 - item.setIndex(null, n.index);
22.631 -
22.632 - // notify.addAll ((ArrayList)n.transaction);
22.633 - }
22.634 - }
22.635 - }
22.636 -
22.637 - if (retained && (notify != null)) {
22.638 - // type of this node has been changed
22.639 - notify.add(node.getType());
22.640 - }
22.641 - }
22.642 -
22.643 - if (node.children != null) {
22.644 - for (Iterator it = node.children.iterator();;) {
22.645 - Node ch = extractNode(it);
22.646 -
22.647 - if (ch == null) {
22.648 - break;
22.649 - }
22.650 -
22.651 - boolean result = retainAllClasses(ch, retain, notify);
22.652 -
22.653 - if (result) {
22.654 - // The children node was emptied and has no children -> remove it.
22.655 - it.remove();
22.656 - }
22.657 - }
22.658 - }
22.659 -
22.660 - return retained && node.items.isEmpty() && ((node.children == null) || node.children.isEmpty());
22.661 - }
22.662 -
22.663 - /** A method that creates enumeration of all items under given node.
22.664 - *
22.665 - * @param n node to create enumeration for
22.666 - * @return enumeration of Pairs
22.667 - */
22.668 - private static Enumeration<Pair> nodeToEnum(Node n) {
22.669 - if (n.children == null) {
22.670 - // create a simple enumeration because we do not have children
22.671 - Enumeration<Pair> e;
22.672 - if (n.items == null) {
22.673 - e = emptyEn();
22.674 - } else {
22.675 - e = Collections.enumeration(n.items);
22.676 - }
22.677 - return e;
22.678 - }
22.679 -
22.680 - // create enumeration of Items
22.681 - return new NeedsSortEnum(n);
22.682 - }
22.683 -
22.684 - //
22.685 - // Methods to work on interfaces
22.686 - //
22.687 -
22.688 - /** Registers an item with interfaces.
22.689 - * @param item item to register
22.690 - * @param affected list of classes that were affected
22.691 - * @return false if similar item has already been registered
22.692 - */
22.693 - @SuppressWarnings("unchecked")
22.694 - private boolean registerInterface(AbstractLookup.Pair<?> item, Collection<Class> affected) {
22.695 - if (interfaces == null) {
22.696 - return true;
22.697 - }
22.698 -
22.699 - Iterator<Map.Entry<Class,Object>> it = interfaces.entrySet().iterator();
22.700 -
22.701 - while (it.hasNext()) {
22.702 - Map.Entry<Class,Object> entry = it.next();
22.703 - Class<?> iface = entry.getKey();
22.704 -
22.705 - if (item.instanceOf(iface)) {
22.706 - Object value = entry.getValue();
22.707 -
22.708 - if (value instanceof Collection) {
22.709 - Collection<Object> set = (Collection<Object>) value;
22.710 -
22.711 - if (!set.add(item)) {
22.712 - // item is already there, probably (if everything is correct) is registered in
22.713 - // all other ifaces too, so stop additional testing
22.714 - return false;
22.715 - }
22.716 - } else {
22.717 - // there is just one pair right now
22.718 - if (value.equals(item)) {
22.719 - // item is there => stop processing (same as above)
22.720 - return false;
22.721 - }
22.722 -
22.723 - // otherwise replace the single item with ArrayList
22.724 - ArrayList<Object> ll = new ArrayList<Object>(3);
22.725 - ll.add(value);
22.726 - ll.add(item);
22.727 - entry.setValue(ll);
22.728 - }
22.729 -
22.730 - affected.add(iface);
22.731 - }
22.732 - }
22.733 -
22.734 - return true;
22.735 - }
22.736 -
22.737 - /** Removes interface.
22.738 - * @param item item to register
22.739 - * @param affected list of classes that were affected
22.740 - */
22.741 - @SuppressWarnings("unchecked")
22.742 - private void removeInterface(AbstractLookup.Pair item, Collection affected) {
22.743 - if (interfaces == null) {
22.744 - return;
22.745 - }
22.746 -
22.747 - Iterator it = interfaces.entrySet().iterator();
22.748 -
22.749 - while (it.hasNext()) {
22.750 - Map.Entry entry = (Map.Entry) it.next();
22.751 - Object value = entry.getValue();
22.752 -
22.753 - if (value instanceof Collection) {
22.754 - Collection set = (Collection) value;
22.755 -
22.756 - if (set.remove(item)) {
22.757 - if (set.size() == 1) {
22.758 - // if there is just one item remaining change to single item mode
22.759 - entry.setValue(set.iterator().next());
22.760 - }
22.761 -
22.762 - // adds the Class the item was register to into affected
22.763 - affected.add(entry.getKey());
22.764 - }
22.765 - } else {
22.766 - // single item value
22.767 - if (value.equals(item)) {
22.768 - // Emptied -> remove.
22.769 - it.remove();
22.770 -
22.771 - affected.add(entry.getKey());
22.772 - }
22.773 - }
22.774 - }
22.775 - }
22.776 -
22.777 - /** Retains some items.
22.778 - * @param retainItems items to retain and their mapping to index numbers
22.779 - * (AbstractLookup.Pair -> AbstractLookup.Info)
22.780 - * @param affected list of classes that were affected
22.781 - */
22.782 - @SuppressWarnings("unchecked")
22.783 - private void retainAllInterface(Map retainItems, Collection affected) {
22.784 - if (interfaces == null) {
22.785 - return;
22.786 - }
22.787 -
22.788 - Iterator it = interfaces.entrySet().iterator();
22.789 -
22.790 - while (it.hasNext()) {
22.791 - Map.Entry entry = (Map.Entry) it.next();
22.792 - Object value = entry.getValue();
22.793 -
22.794 - HashMap<?,?> retain = new HashMap(retainItems);
22.795 -
22.796 - Iterator elems;
22.797 - boolean multi = value instanceof Collection;
22.798 -
22.799 - if (multi) {
22.800 - // collection mode
22.801 - elems = ((Collection) value).iterator();
22.802 - } else {
22.803 - // single item mode
22.804 - elems = Collections.singleton(value).iterator();
22.805 - }
22.806 -
22.807 - boolean changed = false;
22.808 - boolean reordered = false;
22.809 -
22.810 - while (elems.hasNext()) {
22.811 - AbstractLookup.Pair p = (AbstractLookup.Pair) elems.next();
22.812 -
22.813 - AbstractLookup.Info n = (AbstractLookup.Info) retain.remove(p);
22.814 -
22.815 - if (n == null) {
22.816 - if (multi) {
22.817 - // remove it
22.818 - elems.remove();
22.819 - }
22.820 -
22.821 - changed = true;
22.822 - } else {
22.823 - if (p.getIndex() != n.index) {
22.824 - // improve the index
22.825 - p.setIndex(null, n.index);
22.826 -
22.827 - // affected.addAll ((ArrayList)n.transaction);
22.828 - reordered = true;
22.829 - }
22.830 - }
22.831 - }
22.832 -
22.833 - if (reordered && value instanceof List) {
22.834 - // if reordered, than update the order in the collection
22.835 - List l = (List) value;
22.836 - Collections.sort(l, ALPairComparator.DEFAULT);
22.837 - }
22.838 -
22.839 - if (changed) {
22.840 - if (multi) {
22.841 - Collection c = (Collection) value;
22.842 -
22.843 - if (c.size() == 1) {
22.844 - // back to single item mode
22.845 - entry.setValue(c.iterator().next());
22.846 - }
22.847 - } else {
22.848 - // remove in single mode => remove completely
22.849 - it.remove();
22.850 - }
22.851 -
22.852 - // adds the Class the item was register to into affected
22.853 - affected.add(entry.getKey());
22.854 - }
22.855 - }
22.856 - }
22.857 -
22.858 - /** Searches for a clazz between interfaces.
22.859 - * @param clazz class to search for
22.860 - * @return enumeration of Items
22.861 - */
22.862 - @SuppressWarnings("unchecked")
22.863 - private Enumeration<Pair> searchInterface(final Class<?> clazz) {
22.864 - if (interfaces == null) {
22.865 - // first call for interface, only initialize
22.866 - interfaces = new WeakHashMap();
22.867 - }
22.868 -
22.869 - Object obj = interfaces.get(clazz);
22.870 -
22.871 - if (obj == null) {
22.872 - // set of items
22.873 - AbstractLookup.Pair one = null;
22.874 - ArrayList items = null;
22.875 -
22.876 - Enumeration en = lookup(Object.class);
22.877 -
22.878 - while (en.hasMoreElements()) {
22.879 - AbstractLookup.Pair it = (AbstractLookup.Pair) en.nextElement();
22.880 -
22.881 - if (it.instanceOf(clazz)) {
22.882 - // ok, this item implements given clazz
22.883 - if (one == null) {
22.884 - one = it;
22.885 - } else {
22.886 - if (items == null) {
22.887 - items = new ArrayList(3);
22.888 - items.add(one);
22.889 - }
22.890 -
22.891 - items.add(it);
22.892 - }
22.893 - }
22.894 - }
22.895 -
22.896 - if ((items == null) && (one != null)) {
22.897 - // single item mode
22.898 - interfaces.put(clazz, one);
22.899 -
22.900 - return singletonEn(one);
22.901 - } else {
22.902 - if (items == null) {
22.903 - items = new ArrayList(2);
22.904 - }
22.905 -
22.906 - interfaces.put(clazz, items);
22.907 -
22.908 - return Collections.enumeration(items);
22.909 - }
22.910 - } else {
22.911 - if (obj instanceof Collection) {
22.912 - return Collections.enumeration((Collection) obj);
22.913 - } else {
22.914 - // single item mode
22.915 - return singletonEn((Pair)obj);
22.916 - }
22.917 - }
22.918 - }
22.919 -
22.920 - /** Extracts a node from an iterator, returning null if no next element found
22.921 - */
22.922 - private static Node extractNode(Iterator it) {
22.923 - while (it.hasNext()) {
22.924 - Node n = (Node) it.next();
22.925 -
22.926 - if (n.get() == null) {
22.927 - it.remove();
22.928 - } else {
22.929 - return n;
22.930 - }
22.931 - }
22.932 -
22.933 - return null;
22.934 - }
22.935 -
22.936 - /** Prints debug info about the node.
22.937 - * @param n node to print
22.938 - * @param sp spaces to add
22.939 - * @param out where
22.940 - * @param instances print also instances
22.941 - */
22.942 - private static void printNode(Node n, String sp, java.io.PrintStream out, boolean instances) {
22.943 - int i;
22.944 - Iterator it;
22.945 -
22.946 - Class type = n.getType();
22.947 -
22.948 - out.print(sp);
22.949 - out.println("Node for: " + type + "\t" + ((type == null) ? null : type.getClassLoader())); // NOI18N
22.950 -
22.951 - if (n.items != null) {
22.952 - i = 0;
22.953 - it = new ArrayList<Pair>(n.items).iterator();
22.954 -
22.955 - while (it.hasNext()) {
22.956 - AbstractLookup.Pair p = (AbstractLookup.Pair) it.next();
22.957 - out.print(sp);
22.958 - out.print(" item (" + i++ + "): ");
22.959 - out.print(p); // NOI18N
22.960 - out.print(" id: " + Integer.toHexString(System.identityHashCode(p))); // NOI18N
22.961 - out.print(" index: "); // NOI18N
22.962 - out.print(p.getIndex());
22.963 -
22.964 - if (instances) {
22.965 - out.print(" I: " + p.getInstance());
22.966 - }
22.967 -
22.968 - out.println();
22.969 - }
22.970 - }
22.971 -
22.972 - if (n.children != null) {
22.973 - i = 0;
22.974 - it = n.children.iterator();
22.975 -
22.976 - while (it.hasNext()) {
22.977 - Node ch = (Node) it.next();
22.978 - printNode(ch, sp + " ", out, instances); // NOI18N
22.979 - }
22.980 - }
22.981 - }
22.982 -
22.983 - public ReferenceToResult registerReferenceToResult(ReferenceToResult<?> newRef) {
22.984 - if (reg == null) {
22.985 - reg = new HashMap<Class,ReferenceToResult>();
22.986 - }
22.987 -
22.988 - Class<? extends Object> clazz = newRef.template.getType();
22.989 -
22.990 - // initialize the data structures if not yet
22.991 - lookup(clazz);
22.992 -
22.993 - // newRef will be the new head of the list
22.994 - return reg.put(clazz, newRef);
22.995 - }
22.996 -
22.997 - public ReferenceToResult cleanUpResult(Lookup.Template templ) {
22.998 - collectListeners(null, templ.getType());
22.999 -
22.1000 - return (reg == null) ? null : reg.get(templ.getType());
22.1001 - }
22.1002 -
22.1003 - public ArrayList<Class> beginTransaction(int ensure) {
22.1004 - return new ArrayList<Class>();
22.1005 - }
22.1006 -
22.1007 - public void endTransaction(ArrayList<Class> list, Set<AbstractLookup.R> allAffectedResults) {
22.1008 - if (list.size() == 1) {
22.1009 - // probably the most common case
22.1010 - collectListeners(allAffectedResults, list.get(0));
22.1011 - } else {
22.1012 - Iterator it = list.iterator();
22.1013 -
22.1014 - while (it.hasNext()) {
22.1015 - collectListeners(allAffectedResults, (Class) it.next());
22.1016 - }
22.1017 - }
22.1018 - }
22.1019 -
22.1020 - /** Notifies all listeners that are interested in changes in this class.
22.1021 - * Should be called from synchronized places.
22.1022 - * @param allAffectedResults adds Results into this set
22.1023 - * @param c the class that has changed
22.1024 - */
22.1025 - private void collectListeners(Set<AbstractLookup.R> allAffectedResults, Class c) {
22.1026 - if (reg == null) {
22.1027 - return;
22.1028 - }
22.1029 -
22.1030 - while (c != null) {
22.1031 - ReferenceToResult first = reg.get(c);
22.1032 - ReferenceIterator it = new ReferenceIterator(first);
22.1033 -
22.1034 - while (it.next()) {
22.1035 - AbstractLookup.R result = it.current().getResult();
22.1036 -
22.1037 - if (allAffectedResults != null) {
22.1038 - // add result
22.1039 - allAffectedResults.add(result);
22.1040 - }
22.1041 - }
22.1042 -
22.1043 - if (first != it.first()) {
22.1044 - if (it.first() == null) {
22.1045 - // we do not need have more results on this object
22.1046 - reg.remove(c);
22.1047 - } else {
22.1048 - // move the head of the list
22.1049 - reg.put(c, it.first());
22.1050 - }
22.1051 - }
22.1052 -
22.1053 - c = c.getSuperclass();
22.1054 - }
22.1055 -
22.1056 - if (reg.isEmpty()) {
22.1057 - // clean up the list of all results if we do not need them anymore
22.1058 - reg = null;
22.1059 - }
22.1060 - }
22.1061 -
22.1062 - /** Node in the tree.
22.1063 - */
22.1064 - static final class Node extends WeakReference<Class> implements Serializable {
22.1065 - static final long serialVersionUID = 3L;
22.1066 -
22.1067 - /** children nodes */
22.1068 - public ArrayList<Node> children;
22.1069 -
22.1070 - /** list of items assigned to this node (suspect to be subclasses) */
22.1071 - public Collection<Pair> items;
22.1072 -
22.1073 - /** Constructor.
22.1074 - */
22.1075 - public Node(Class clazz) {
22.1076 - super(clazz);
22.1077 - }
22.1078 -
22.1079 - /** Returns true if the object was deserialized also clears the serialized flag.
22.1080 - * @return true if so.
22.1081 - */
22.1082 - public boolean deserialized() {
22.1083 - if ((items == null) || items instanceof LinkedHashSet) {
22.1084 - return false;
22.1085 - }
22.1086 -
22.1087 - if (items.isEmpty()) {
22.1088 - items = null;
22.1089 - } else {
22.1090 - items = new LinkedHashSet<Pair>(items);
22.1091 - }
22.1092 -
22.1093 - return true;
22.1094 - }
22.1095 -
22.1096 - /** Marks this item as being deserialized.
22.1097 - */
22.1098 - public void markDeserialized() {
22.1099 - if (items == null || items == Collections.EMPTY_LIST) {
22.1100 - items = Collections.emptyList();
22.1101 - } else {
22.1102 - items = Collections.synchronizedCollection(items);
22.1103 - }
22.1104 - }
22.1105 -
22.1106 - /** Getter for the type associated with this node.
22.1107 - */
22.1108 - public Class<?> getType() {
22.1109 - Class<?> c = get();
22.1110 -
22.1111 - // if garbage collected, then return a garbage
22.1112 - return (c == null) ? Void.TYPE : c;
22.1113 - }
22.1114 -
22.1115 - /** Checks whether a node can represent an class.
22.1116 - */
22.1117 - public boolean accepts(Class<?> clazz) {
22.1118 - if (getType() == Object.class) {
22.1119 - return true;
22.1120 - }
22.1121 -
22.1122 - return getType().isAssignableFrom(clazz);
22.1123 - }
22.1124 -
22.1125 - /** Checks whether item is instance of this node.
22.1126 - */
22.1127 - public boolean accepts(AbstractLookup.Pair<?> item) {
22.1128 - if (getType() == Object.class) {
22.1129 - // Object.class
22.1130 - return true;
22.1131 - }
22.1132 -
22.1133 - return item.instanceOf(getType());
22.1134 - }
22.1135 -
22.1136 - /** Assings an item to this node.
22.1137 - * @param item the item
22.1138 - * @return true if item has been added as new
22.1139 - */
22.1140 - public boolean assignItem(InheritanceTree tree, AbstractLookup.Pair<?> item) {
22.1141 - if ((items == null) || (items == Collections.EMPTY_LIST)) {
22.1142 - items = new LinkedHashSet<Pair>();
22.1143 - items.add(item);
22.1144 -
22.1145 - return true;
22.1146 - }
22.1147 -
22.1148 - if (items.contains(item)) {
22.1149 - Iterator<Pair> it = items.iterator();
22.1150 - Pair old;
22.1151 - for (;;) {
22.1152 - old = it.next();
22.1153 - if (item.equals(old)) {
22.1154 - break;
22.1155 - }
22.1156 - }
22.1157 -
22.1158 - if (old != item) {
22.1159 - // replace the items there
22.1160 - item.setIndex(tree, old.getIndex());
22.1161 - }
22.1162 -
22.1163 - it.remove();
22.1164 - items.add(item);
22.1165 -
22.1166 - return false;
22.1167 - }
22.1168 -
22.1169 - items.add(item);
22.1170 -
22.1171 - return true;
22.1172 - }
22.1173 -
22.1174 - private Object writeReplace() {
22.1175 - return new R(this);
22.1176 - }
22.1177 -
22.1178 - @Override
22.1179 - public String toString() {
22.1180 - return "Node for " + get();
22.1181 - }
22.1182 - }
22.1183 - // End of class Node.
22.1184 -
22.1185 - private static final class R implements Serializable {
22.1186 - static final long serialVersionUID = 1L;
22.1187 - private static ClassLoader l;
22.1188 - private String clazzName;
22.1189 - private transient Class<?> clazz;
22.1190 - private ArrayList<Node> children;
22.1191 - private Collection<Pair> items;
22.1192 -
22.1193 - public R(Node n) {
22.1194 - this.clazzName = n.getType().getName();
22.1195 - this.children = n.children;
22.1196 -
22.1197 - if (n.items instanceof LinkedHashSet || (n.items == null)) {
22.1198 - this.items = n.items;
22.1199 - } else {
22.1200 - this.items = new LinkedHashSet<Pair>(n.items);
22.1201 - }
22.1202 - }
22.1203 -
22.1204 - private void readObject(ObjectInputStream ois)
22.1205 - throws IOException, ClassNotFoundException {
22.1206 - ois.defaultReadObject();
22.1207 -
22.1208 - if (l == null) {
22.1209 - l = Lookup.getDefault().lookup(ClassLoader.class);
22.1210 - }
22.1211 -
22.1212 - clazz = Class.forName(clazzName, false, l);
22.1213 - }
22.1214 -
22.1215 - private Object readResolve() throws ObjectStreamException {
22.1216 - Node n = new Node(clazz);
22.1217 - n.children = children;
22.1218 - n.items = items;
22.1219 - n.markDeserialized();
22.1220 -
22.1221 - return n;
22.1222 - }
22.1223 - }
22.1224 - // end of R
22.1225 -
22.1226 - static Enumeration<Object> arrayEn(Object[] object) {
22.1227 - return Collections.enumeration(Arrays.asList(object));
22.1228 - }
22.1229 - static <T> Enumeration<T> singletonEn(T object) {
22.1230 - return Collections.enumeration(Collections.singleton(object));
22.1231 - }
22.1232 - static <T> Enumeration<T> emptyEn() {
22.1233 - return Collections.enumeration(Collections.<T>emptyList());
22.1234 - }
22.1235 -
22.1236 - /** Just a marker class to be able to do instanceof and find out
22.1237 - * that this enumeration is not sorted
22.1238 - */
22.1239 - private static final class NeedsSortEnum extends LinkedList<Node>
22.1240 - implements Enumeration<Pair> {
22.1241 - private Enumeration<Pair> en;
22.1242 -
22.1243 - public NeedsSortEnum(Node n) {
22.1244 - add(n);
22.1245 - }
22.1246 -
22.1247 - private boolean ensureNext() {
22.1248 - for (;;) {
22.1249 - if (en != null && en.hasMoreElements()) {
22.1250 - return true;
22.1251 - }
22.1252 - if (isEmpty()) {
22.1253 - return false;
22.1254 - }
22.1255 -
22.1256 - Node n2 = poll();
22.1257 - if (n2.children != null) {
22.1258 - addAll(n2.children);
22.1259 - }
22.1260 -
22.1261 - if (n2.items != null && !n2.items.isEmpty()) {
22.1262 - en = Collections.enumeration(n2.items);
22.1263 - }
22.1264 - }
22.1265 - }
22.1266 -
22.1267 - public boolean hasMoreElements() {
22.1268 - return ensureNext();
22.1269 - }
22.1270 -
22.1271 - public Pair nextElement() {
22.1272 - if (!ensureNext()) {
22.1273 - throw new NoSuchElementException();
22.1274 - }
22.1275 - return en.nextElement();
22.1276 - }
22.1277 - }
22.1278 - // end of NeedsSortEnum
22.1279 -}
23.1 --- a/lookup/src/main/java/org/openide/util/lookup/InstanceContent.java Wed Jan 27 17:46:23 2010 -0500
23.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
23.3 @@ -1,378 +0,0 @@
23.4 -/*
23.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
23.6 - *
23.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
23.8 - *
23.9 - * The contents of this file are subject to the terms of either the GNU
23.10 - * General Public License Version 2 only ("GPL") or the Common
23.11 - * Development and Distribution License("CDDL") (collectively, the
23.12 - * "License"). You may not use this file except in compliance with the
23.13 - * License. You can obtain a copy of the License at
23.14 - * http://www.netbeans.org/cddl-gplv2.html
23.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
23.16 - * specific language governing permissions and limitations under the
23.17 - * License. When distributing the software, include this License Header
23.18 - * Notice in each file and include the License file at
23.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
23.20 - * particular file as subject to the "Classpath" exception as provided
23.21 - * by Sun in the GPL Version 2 section of the License file that
23.22 - * accompanied this code. If applicable, add the following below the
23.23 - * License Header, with the fields enclosed by brackets [] replaced by
23.24 - * your own identifying information:
23.25 - * "Portions Copyrighted [year] [name of copyright owner]"
23.26 - *
23.27 - * Contributor(s):
23.28 - *
23.29 - * The Original Software is NetBeans. The Initial Developer of the Original
23.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
23.31 - * Microsystems, Inc. All Rights Reserved.
23.32 - *
23.33 - * If you wish your version of this file to be governed by only the CDDL
23.34 - * or only the GPL Version 2, indicate your decision by adding
23.35 - * "[Contributor] elects to include this software in this distribution
23.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
23.37 - * single choice of license, a recipient has the option to distribute
23.38 - * your version of this file under either the CDDL, the GPL Version 2 or
23.39 - * to extend the choice of license to its licensees as provided above.
23.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
23.41 - * Version 2 license, then the option applies only if the new code is
23.42 - * made subject to such option by the copyright holder.
23.43 - */
23.44 -package org.openide.util.lookup;
23.45 -
23.46 -import org.openide.util.lookup.AbstractLookup.Pair;
23.47 -
23.48 -import java.lang.ref.WeakReference;
23.49 -
23.50 -import java.util.*;
23.51 -import java.util.concurrent.Executor;
23.52 -import org.openide.util.Lookup.Item;
23.53 -
23.54 -
23.55 -/** A special content implementation that can be passed to AbstractLookup
23.56 - * and provides methods for registration of instances and lazy instances.
23.57 - * <PRE>
23.58 - * InstanceContent ic = new InstanceContent ();
23.59 - * AbstractLookup al = new AbstractLookup (ic);
23.60 - *
23.61 - * ic.add (new Object ());
23.62 - * ic.add (new Dimension (...));
23.63 - *
23.64 - * Dimension theDim = (Dimension)al.lookup (Dimension.class);
23.65 - * </PRE>
23.66 - *
23.67 - * @author Jaroslav Tulach
23.68 - *
23.69 - * @since 1.25
23.70 - */
23.71 -public final class InstanceContent extends AbstractLookup.Content {
23.72 - /**
23.73 - * Create a new, empty content.
23.74 - */
23.75 - public InstanceContent() {
23.76 - }
23.77 -
23.78 - /** Creates a content associated with an executor to handle dispatch
23.79 - * of changes.
23.80 - * @param notifyIn the executor to notify changes in
23.81 - * @since 7.16
23.82 - */
23.83 - public InstanceContent(Executor notifyIn) {
23.84 - super(notifyIn);
23.85 - }
23.86 - /** The method to add instance to the lookup with.
23.87 - * @param inst instance
23.88 - */
23.89 - public final void add(Object inst) {
23.90 - addPair(new SimpleItem<Object>(inst));
23.91 - }
23.92 -
23.93 - /** Adds a convertible instance into the lookup. The <code>inst</code>
23.94 - * argument is just a key, not the actual value to appear in the lookup.
23.95 - * The value will be created on demand, later when it is really needed
23.96 - * by calling <code>convertor</code> methods.
23.97 - * <p>
23.98 - * This method is useful to delay creation of heavy weight objects.
23.99 - * Instead just register lightweight key and a convertor.
23.100 - * <p>
23.101 - * To remove registered object from lookup use {@link #remove(java.lang.Object, org.openide.util.lookup.InstanceContent.Convertor)}
23.102 - * with the same arguments.
23.103 - *
23.104 - * @param inst instance
23.105 - * @param conv convertor which postponing an instantiation,
23.106 - * if <code>conv==null</code> then the instance is registered directly.
23.107 - */
23.108 - public final <T,R> void add(T inst, Convertor<T,R> conv) {
23.109 - addPair(new ConvertingItem<T,R>(inst, conv));
23.110 - }
23.111 -
23.112 - /** Remove instance.
23.113 - * @param inst instance
23.114 - */
23.115 - public final void remove(Object inst) {
23.116 - removePair(new SimpleItem<Object>(inst));
23.117 - }
23.118 -
23.119 - /** Remove instance added with a convertor.
23.120 - * @param inst instance
23.121 - * @param conv convertor, if <code>conv==null</code> it is same like
23.122 - * remove(Object)
23.123 - */
23.124 - public final <T,R> void remove(T inst, Convertor<T,R> conv) {
23.125 - removePair(new ConvertingItem<T,R>(inst, conv));
23.126 - }
23.127 -
23.128 - /** Changes all pairs in the lookup to new values. Converts collection of
23.129 - * instances to collection of pairs.
23.130 - * @param col the collection of (Item) objects
23.131 - * @param conv the convertor to use or null
23.132 - */
23.133 - public final <T,R> void set(Collection<T> col, Convertor<T,R> conv) {
23.134 - ArrayList<Pair<?>> l = new ArrayList<Pair<?>>(col.size());
23.135 - Iterator<T> it = col.iterator();
23.136 -
23.137 - if (conv == null) {
23.138 - while (it.hasNext()) {
23.139 - l.add(new SimpleItem<T>(it.next()));
23.140 - }
23.141 - } else {
23.142 - while (it.hasNext()) {
23.143 - l.add(new ConvertingItem<T,R>(it.next(), conv));
23.144 - }
23.145 - }
23.146 -
23.147 - setPairs(l);
23.148 - }
23.149 -
23.150 - /** Convertor postpones an instantiation of an object.
23.151 - * @since 1.25
23.152 - */
23.153 - public static interface Convertor<T,R> {
23.154 - /** Convert obj to other object. There is no need to implement
23.155 - * cache mechanism. It is provided by
23.156 - * {@link Item#getInstance()} method itself. However the
23.157 - * method can be called more than once because instance is held
23.158 - * just by weak reference.
23.159 - *
23.160 - * @param obj the registered object
23.161 - * @return the object converted from this object
23.162 - */
23.163 - public R convert(T obj);
23.164 -
23.165 - /** Return type of converted object. Accessible via
23.166 - * {@link Item#getType()}
23.167 - * @param obj the registered object
23.168 - * @return the class that will be produced from this object (class or
23.169 - * superclass of convert (obj))
23.170 - */
23.171 - public Class<? extends R> type(T obj);
23.172 -
23.173 - /** Computes the ID of the resulted object. Accessible via
23.174 - * {@link Item#getId()}.
23.175 - * @param obj the registered object
23.176 - * @return the ID for the object
23.177 - */
23.178 - public String id(T obj);
23.179 -
23.180 - /** The human presentable name for the object. Accessible via
23.181 - * {@link Item#getDisplayName()}.
23.182 - * @param obj the registered object
23.183 - * @return the name representing the object for the user
23.184 - */
23.185 - public String displayName(T obj);
23.186 - }
23.187 -
23.188 - /** Instance of one item representing an object.
23.189 - */
23.190 - final static class SimpleItem<T> extends Pair<T> {
23.191 - private T obj;
23.192 -
23.193 - /** Create an item.
23.194 - * @obj object to register
23.195 - */
23.196 - public SimpleItem(T obj) {
23.197 - if (obj == null) {
23.198 - throw new NullPointerException();
23.199 - }
23.200 - this.obj = obj;
23.201 - }
23.202 -
23.203 - /** Tests whether this item can produce object
23.204 - * of class c.
23.205 - */
23.206 - public boolean instanceOf(Class<?> c) {
23.207 - return c.isInstance(obj);
23.208 - }
23.209 -
23.210 - /** Get instance of registered object. If convertor is specified then
23.211 - * method InstanceLookup.Convertor.convertor is used and weak reference
23.212 - * to converted object is saved.
23.213 - * @return the instance of the object.
23.214 - */
23.215 - public T getInstance() {
23.216 - return obj;
23.217 - }
23.218 -
23.219 - @Override
23.220 - public boolean equals(Object o) {
23.221 - if (o instanceof SimpleItem) {
23.222 - return obj.equals(((SimpleItem) o).obj);
23.223 - } else {
23.224 - return false;
23.225 - }
23.226 - }
23.227 -
23.228 - @Override
23.229 - public int hashCode() {
23.230 - return obj.hashCode();
23.231 - }
23.232 -
23.233 - /** An identity of the item.
23.234 - * @return string representing the item, that can be used for
23.235 - * persistance purposes to locate the same item next time
23.236 - */
23.237 - public String getId() {
23.238 - return "IL[" + obj.toString(); // NOI18N
23.239 - }
23.240 -
23.241 - /** Getter for display name of the item.
23.242 - */
23.243 - public String getDisplayName() {
23.244 - return obj.toString();
23.245 - }
23.246 -
23.247 - /** Method that can test whether an instance of a class has been created
23.248 - * by this item.
23.249 - *
23.250 - * @param obj the instance
23.251 - * @return if the item has already create an instance and it is the same
23.252 - * as obj.
23.253 - */
23.254 - protected boolean creatorOf(Object obj) {
23.255 - return obj == this.obj;
23.256 - }
23.257 -
23.258 - /** The class of this item.
23.259 - * @return the correct class
23.260 - */
23.261 - @SuppressWarnings("unchecked")
23.262 - public Class<? extends T> getType() {
23.263 - return (Class<? extends T>)obj.getClass();
23.264 - }
23.265 - }
23.266 - // end of SimpleItem
23.267 -
23.268 - /** Instance of one item registered in the map.
23.269 - */
23.270 - final static class ConvertingItem<T,R> extends Pair<R> {
23.271 - /** registered object */
23.272 - private T obj;
23.273 -
23.274 - /** Reference to converted object. */
23.275 - private WeakReference<R> ref;
23.276 -
23.277 - /** convertor to use */
23.278 - private Convertor<? super T,R> conv;
23.279 -
23.280 - /** Create an item.
23.281 - * @obj object to register
23.282 - * @conv a convertor, can be <code>null</code>.
23.283 - */
23.284 - public ConvertingItem(T obj, Convertor<? super T,R> conv) {
23.285 - this.obj = obj;
23.286 - this.conv = conv;
23.287 - }
23.288 -
23.289 - /** Tests whether this item can produce object
23.290 - * of class c.
23.291 - */
23.292 - public boolean instanceOf(Class<?> c) {
23.293 - return c.isAssignableFrom(getType());
23.294 - }
23.295 -
23.296 - /** Returns converted object or null if obj has not been converted yet
23.297 - * or reference was cleared by garbage collector.
23.298 - */
23.299 - private R getConverted() {
23.300 - if (ref == null) {
23.301 - return null;
23.302 - }
23.303 -
23.304 - return ref.get();
23.305 - }
23.306 -
23.307 - /** Get instance of registered object. If convertor is specified then
23.308 - * method InstanceLookup.Convertor.convertor is used and weak reference
23.309 - * to converted object is saved.
23.310 - * @return the instance of the object.
23.311 - */
23.312 - public synchronized R getInstance() {
23.313 - R converted = getConverted();
23.314 -
23.315 - if (converted == null) {
23.316 - converted = conv.convert(obj);
23.317 - ref = new WeakReference<R>(converted);
23.318 - }
23.319 -
23.320 - return converted;
23.321 - }
23.322 -
23.323 - @Override
23.324 - public boolean equals(Object o) {
23.325 - if (o instanceof ConvertingItem) {
23.326 - return obj.equals(((ConvertingItem) o).obj);
23.327 - } else {
23.328 - return false;
23.329 - }
23.330 - }
23.331 -
23.332 - @Override
23.333 - public int hashCode() {
23.334 - return obj.hashCode();
23.335 - }
23.336 -
23.337 - /** An identity of the item.
23.338 - * @return string representing the item, that can be used for
23.339 - * persistance purposes to locate the same item next time
23.340 - */
23.341 - public String getId() {
23.342 - return conv.id(obj);
23.343 - }
23.344 -
23.345 - /** Getter for display name of the item.
23.346 - */
23.347 - public String getDisplayName() {
23.348 - return conv.displayName(obj);
23.349 - }
23.350 -
23.351 - /** Method that can test whether an instance of a class has been created
23.352 - * by this item.
23.353 - *
23.354 - * @param obj the instance
23.355 - * @return if the item has already create an instance and it is the same
23.356 - * as obj.
23.357 - */
23.358 - protected boolean creatorOf(Object obj) {
23.359 - if (conv == null) {
23.360 - return obj == this.obj;
23.361 - } else {
23.362 - return obj == getConverted();
23.363 - }
23.364 - }
23.365 -
23.366 - /** The class of this item.
23.367 - * @return the correct class
23.368 - */
23.369 - @SuppressWarnings("unchecked")
23.370 - public Class<? extends R> getType() {
23.371 - R converted = getConverted();
23.372 -
23.373 - if (converted == null) {
23.374 - return conv.type(obj);
23.375 - }
23.376 -
23.377 - return (Class<? extends R>)converted.getClass();
23.378 - }
23.379 - }
23.380 - // end of ConvertingItem
23.381 -}
24.1 --- a/lookup/src/main/java/org/openide/util/lookup/Lookups.java Wed Jan 27 17:46:23 2010 -0500
24.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
24.3 @@ -1,317 +0,0 @@
24.4 -/*
24.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
24.6 - *
24.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
24.8 - *
24.9 - * The contents of this file are subject to the terms of either the GNU
24.10 - * General Public License Version 2 only ("GPL") or the Common
24.11 - * Development and Distribution License("CDDL") (collectively, the
24.12 - * "License"). You may not use this file except in compliance with the
24.13 - * License. You can obtain a copy of the License at
24.14 - * http://www.netbeans.org/cddl-gplv2.html
24.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
24.16 - * specific language governing permissions and limitations under the
24.17 - * License. When distributing the software, include this License Header
24.18 - * Notice in each file and include the License file at
24.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
24.20 - * particular file as subject to the "Classpath" exception as provided
24.21 - * by Sun in the GPL Version 2 section of the License file that
24.22 - * accompanied this code. If applicable, add the following below the
24.23 - * License Header, with the fields enclosed by brackets [] replaced by
24.24 - * your own identifying information:
24.25 - * "Portions Copyrighted [year] [name of copyright owner]"
24.26 - *
24.27 - * Contributor(s):
24.28 - *
24.29 - * The Original Software is NetBeans. The Initial Developer of the Original
24.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2009 Sun
24.31 - * Microsystems, Inc. All Rights Reserved.
24.32 - *
24.33 - * If you wish your version of this file to be governed by only the CDDL
24.34 - * or only the GPL Version 2, indicate your decision by adding
24.35 - * "[Contributor] elects to include this software in this distribution
24.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
24.37 - * single choice of license, a recipient has the option to distribute
24.38 - * your version of this file under either the CDDL, the GPL Version 2 or
24.39 - * to extend the choice of license to its licensees as provided above.
24.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
24.41 - * Version 2 license, then the option applies only if the new code is
24.42 - * made subject to such option by the copyright holder.
24.43 - */
24.44 -
24.45 -package org.openide.util.lookup;
24.46 -
24.47 -import java.util.Arrays;
24.48 -import org.netbeans.modules.openide.util.NamedServicesProvider;
24.49 -import org.openide.util.Lookup;
24.50 -
24.51 -/**
24.52 - * Static factory methods for creating common lookup implementations.
24.53 - *
24.54 - * @author David Strupl
24.55 - * @since 2.21
24.56 - */
24.57 -public class Lookups {
24.58 -
24.59 - /** static methods only */
24.60 - private Lookups() {}
24.61 -
24.62 - /**
24.63 - * Creates a singleton lookup. It means lookup that contains only
24.64 - * one object specified via the supplied parameter. The lookup will
24.65 - * either return the object or null if the supplied template does
24.66 - * not match the class. If the specified argument is null the method
24.67 - * will end with NullPointerException.
24.68 - * @return Fully initialized lookup object ready to use
24.69 - * @throws NullPointerException if the supplied argument is null
24.70 - * @since 2.21
24.71 - */
24.72 - public static Lookup singleton(Object objectToLookup) {
24.73 - if (objectToLookup == null) {
24.74 - throw new NullPointerException();
24.75 - }
24.76 -
24.77 - return new SingletonLookup(objectToLookup);
24.78 - }
24.79 -
24.80 - /**
24.81 - * Creates a lookup that contains an array of objects specified via the
24.82 - * parameter. The resulting lookup is fixed in the following sense: it
24.83 - * contains only fixed set of objects passed in by the array parameter.
24.84 - * Its contents never changes so registering listeners on such lookup
24.85 - * does not have any observable effect (the listeners are never called).
24.86 - *
24.87 - * @param objectsToLookup list of objects to include
24.88 - * @return Fully initialized lookup object ready to use
24.89 - * @throws NullPointerException if the supplied argument is null
24.90 - * @since 2.21
24.91 - *
24.92 - */
24.93 - public static Lookup fixed(Object... objectsToLookup) {
24.94 - if (objectsToLookup == null) {
24.95 - throw new NullPointerException();
24.96 - }
24.97 -
24.98 - if (objectsToLookup.length == 0) {
24.99 - return Lookup.EMPTY;
24.100 - }
24.101 -
24.102 - if (objectsToLookup.length == 1) {
24.103 - return singleton(objectsToLookup[0]);
24.104 - }
24.105 -
24.106 - return new SimpleLookup(Arrays.asList(objectsToLookup));
24.107 - }
24.108 -
24.109 - /**
24.110 - * Creates a lookup that contains an array of objects specified via the
24.111 - * parameter. The resulting lookup is fixed in the following sense: it
24.112 - * contains only fixed set of objects passed in by the array parameter.
24.113 - * The objects returned from this lookup are converted to real objects
24.114 - * before they are returned by the lookup.
24.115 - * Its contents never changes so registering listeners on such lookup
24.116 - * does not have any observable effect (the listeners are never called).
24.117 - *
24.118 - * @return Fully initialized lookup object ready to use
24.119 - * @throws NullPointerException if the any of the arguments is null
24.120 - * @since 2.21
24.121 - *
24.122 - */
24.123 - public static <T,R> Lookup fixed(T[] keys, InstanceContent.Convertor<? super T,R> convertor) {
24.124 - if (keys == null) {
24.125 - throw new NullPointerException();
24.126 - }
24.127 -
24.128 - if (convertor == null) {
24.129 - throw new NullPointerException();
24.130 - }
24.131 -
24.132 - return new SimpleLookup(Arrays.asList(keys), convertor);
24.133 - }
24.134 -
24.135 - /** Creates a lookup that delegates to another one but that one can change
24.136 - * from time to time. The returned lookup checks every time somebody calls
24.137 - * <code>lookup</code> or <code>lookupItem</code> method whether the
24.138 - * provider still returns the same lookup. If not, it updates state of
24.139 - * all {@link org.openide.util.Lookup.Result}s
24.140 - * that it created (and that still exists).
24.141 - * <P>
24.142 - * The user of this method has to implement its provider's <code>getLookup</code>
24.143 - * method (must be thread safe and fast, will be called often and from any thread)
24.144 - * pass it to this method and use the returned lookup. Whenever the user
24.145 - * changes the return value from the <code>getLookup</code> method and wants
24.146 - * to notify listeners on the lookup about that it should trigger the event
24.147 - * firing, for example by calling <code>lookup.lookup (Object.class)</code>
24.148 - * directly on the lookup returned by this method
24.149 - * that forces a check of the return value of {@link org.openide.util.Lookup.Provider#getLookup}</code>.
24.150 - *
24.151 - * @param provider the provider that returns a lookup to delegate to
24.152 - * @return lookup delegating to the lookup returned by the provider
24.153 - * @since 3.9
24.154 - */
24.155 - public static Lookup proxy(Lookup.Provider provider) {
24.156 - return new SimpleProxyLookup(provider);
24.157 - }
24.158 -
24.159 - /** Returns a lookup that implements the JDK1.3 JAR services mechanism and delegates
24.160 - * to META-INF/services/name.of.class files.
24.161 - * <p>Some extensions to the JAR services specification are implemented:
24.162 - * <ol>
24.163 - * <li>An entry may be followed by a line of the form <code>#position=<i>integer</i></code>
24.164 - * to specify ordering. (Smaller numbers first, entries with unspecified position last.)
24.165 - * <li>A line of the form <code>#-<i>classname</i></code> suppresses an entry registered
24.166 - * in another file, so can be used to supersede one implementation with another.
24.167 - * </ol>
24.168 - * <p>Note: It is not dynamic - so if you need to change the classloader or JARs,
24.169 - * wrap it in a {@link ProxyLookup} and change the delegate when necessary.
24.170 - * Existing instances will be kept if the implementation classes are unchanged,
24.171 - * so there is "stability" in doing this provided some parent loaders are the same
24.172 - * as the previous ones.
24.173 - * @since 3.35
24.174 - * @see ServiceProvider
24.175 - */
24.176 - public static Lookup metaInfServices(ClassLoader classLoader) {
24.177 - return new MetaInfServicesLookup(classLoader, "META-INF/services/"); // NOI18N
24.178 - }
24.179 -
24.180 - /** Returns a lookup that behaves exactly like {@link #metaInfServices(ClassLoader)}
24.181 - * except that it does not read data from <code>META-INF/services/</code>, but instead
24.182 - * from the specified prefix.
24.183 - * @param classLoader class loader to use for loading
24.184 - * @param prefix prefix to prepend to the class name when searching
24.185 - * @since 7.9
24.186 - */
24.187 - public static Lookup metaInfServices(ClassLoader classLoader, String prefix) {
24.188 - return new MetaInfServicesLookup(classLoader, prefix);
24.189 - }
24.190 -
24.191 - /** Creates a <q>named</q> lookup.
24.192 - * It is a lookup identified by a given path.
24.193 - * Two lookups with the same path should have the same content.
24.194 - * <p>It is expected that each <q>named</q> lookup
24.195 - * will contain a superset of what would be created by:
24.196 - * <code>{@linkplain #metaInfServices(ClassLoader,String) metaInfServices}(theRightLoader, "META-INF/namedservices/" + path + "/")</code>
24.197 - *
24.198 - * <p class="nonnormative">Various environments can add their own
24.199 - * extensions to its content. As such
24.200 - * {@link Lookups#forPath(java.lang.String)} can combine lookups
24.201 - * from several sources. In current NetBeans Runtime Container, two lookups are used:
24.202 - * </p>
24.203 - * <ul class="nonnormative">
24.204 - * <li><code>Lookups.metaInfServices("META-INF/namedservices/" + path)</code></li>
24.205 - * <li><code>org.openide.loaders.FolderLookup(path)</code></li>
24.206 - * </ul>
24.207 - * <p class="nonnormative">
24.208 - * Please note that these lookups differ in the way they inspect sub-folders.
24.209 - * The first lookup just returns instances from the given path, ignoring
24.210 - * sub-folders, the second one retrieves instances from the whole sub-tree.
24.211 - * </p>
24.212 - * <p>
24.213 - * Read more about the <a href="@org-openide-util@/org/openide/util/doc-files/api.html#folderlookup">usage of this method</a>.
24.214 - *
24.215 - * @param path the path identifying the lookup, e.g. <code>Projects/Actions</code>
24.216 - * @return lookup associated with this path
24.217 - * @since 7.9
24.218 - */
24.219 - public static Lookup forPath(String path) {
24.220 - return NamedServicesProvider.find(path);
24.221 - }
24.222 -
24.223 - /** Creates a lookup that wraps another one and filters out instances
24.224 - * of specified classes. If you have a lookup and
24.225 - * you want to remove all instances of ActionMap you can use:
24.226 - * <pre>
24.227 - * l = Lookups.exclude(lookup, ActionMap.class);
24.228 - * </pre>
24.229 - * Then anybody who asks for <code>l.lookup(ActionMap.class)</code> or
24.230 - * subclass will get <code>null</code>. Even if the original lookup contains the
24.231 - * value.
24.232 - * To create empty lookup (well, just an example, otherwise use {@link Lookup#EMPTY}) one could use:
24.233 - * <pre>
24.234 - * Lookup.exclude(anyLookup, Object.class);
24.235 - * </pre>
24.236 - * as any instance in any lookup is of type Object and thus would be excluded.
24.237 - * <p>
24.238 - * The complete behavior can be described as <code>classes</code> being
24.239 - * a barrier. For an object not to be excluded, there has to be an inheritance
24.240 - * path between the queried class and the actual class of the instance,
24.241 - * that is not blocked by any of the excluded classes:
24.242 - * <pre>
24.243 - * interface A {}
24.244 - * interface B {}
24.245 - * class C implements A, B {}
24.246 - * Object c = new C();
24.247 - * Lookup l1 = Lookups.singleton(c);
24.248 - * Lookup l2 = Lookups.exclude(l1, A.class);
24.249 - * assertNull("A is directly excluded", l2.lookup(A.class));
24.250 - * assertEquals("Returns C as A.class is not between B and C", c, l2.lookup(B.class));
24.251 - * </pre>
24.252 - * For more info check the
24.253 - * <a href="http://hg.netbeans.org/main-golden/annotate/4883eaeda744/openide.util/test/unit/src/org/openide/util/lookup/ExcludingLookupTest.java">
24.254 - * excluding lookup tests</a> and the discussion in issue
24.255 - * <a href="http://openide.netbeans.org/issues/show_bug.cgi?id=53058">53058</a>.
24.256 - *
24.257 - * @param lookup the original lookup that should be filtered
24.258 - * @param classes array of classes those instances should be excluded
24.259 - * @since 5.4
24.260 - */
24.261 - public static Lookup exclude(Lookup lookup, Class... classes) {
24.262 - return new ExcludingLookup(lookup, classes);
24.263 - }
24.264 -
24.265 - /** Creates <code>Lookup.Item</code> representing the instance passed in.
24.266 - *
24.267 - * @param instance the object for which Lookup.Item should be creted
24.268 - * @param id unique identification of the object, for details see {@link org.openide.util.Lookup.Item#getId},
24.269 - * can be <code>null</code>
24.270 - * @return lookup item representing instance
24.271 - * @since 4.8
24.272 - */
24.273 - public static <T> Lookup.Item<T> lookupItem(T instance, String id) {
24.274 - return new LookupItem<T>(instance, id);
24.275 - }
24.276 -
24.277 - private static class LookupItem<T> extends Lookup.Item<T> {
24.278 - private String id;
24.279 - private T instance;
24.280 -
24.281 - public LookupItem(T instance) {
24.282 - this(instance, null);
24.283 - }
24.284 -
24.285 - public LookupItem(T instance, String id) {
24.286 - this.id = id;
24.287 - this.instance = instance;
24.288 - }
24.289 -
24.290 - public String getDisplayName() {
24.291 - return getId();
24.292 - }
24.293 -
24.294 - public String getId() {
24.295 - return (id == null) ? instance.toString() : id;
24.296 - }
24.297 -
24.298 - public T getInstance() {
24.299 - return instance;
24.300 - }
24.301 -
24.302 - @SuppressWarnings("unchecked")
24.303 - public Class<? extends T> getType() {
24.304 - return (Class<? extends T>)instance.getClass();
24.305 - }
24.306 -
24.307 - public @Override boolean equals(Object object) {
24.308 - if (object instanceof LookupItem) {
24.309 - return instance == ((LookupItem) object).getInstance();
24.310 - }
24.311 -
24.312 - return false;
24.313 - }
24.314 -
24.315 - public @Override int hashCode() {
24.316 - return instance.hashCode();
24.317 - }
24.318 - }
24.319 - // End of LookupItem class
24.320 -}
25.1 --- a/lookup/src/main/java/org/openide/util/lookup/MetaInfServicesLookup.java Wed Jan 27 17:46:23 2010 -0500
25.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
25.3 @@ -1,573 +0,0 @@
25.4 -/*
25.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
25.6 - *
25.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
25.8 - *
25.9 - * The contents of this file are subject to the terms of either the GNU
25.10 - * General Public License Version 2 only ("GPL") or the Common
25.11 - * Development and Distribution License("CDDL") (collectively, the
25.12 - * "License"). You may not use this file except in compliance with the
25.13 - * License. You can obtain a copy of the License at
25.14 - * http://www.netbeans.org/cddl-gplv2.html
25.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
25.16 - * specific language governing permissions and limitations under the
25.17 - * License. When distributing the software, include this License Header
25.18 - * Notice in each file and include the License file at
25.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
25.20 - * particular file as subject to the "Classpath" exception as provided
25.21 - * by Sun in the GPL Version 2 section of the License file that
25.22 - * accompanied this code. If applicable, add the following below the
25.23 - * License Header, with the fields enclosed by brackets [] replaced by
25.24 - * your own identifying information:
25.25 - * "Portions Copyrighted [year] [name of copyright owner]"
25.26 - *
25.27 - * Contributor(s):
25.28 - *
25.29 - * The Original Software is NetBeans. The Initial Developer of the Original
25.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
25.31 - * Microsystems, Inc. All Rights Reserved.
25.32 - *
25.33 - * If you wish your version of this file to be governed by only the CDDL
25.34 - * or only the GPL Version 2, indicate your decision by adding
25.35 - * "[Contributor] elects to include this software in this distribution
25.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
25.37 - * single choice of license, a recipient has the option to distribute
25.38 - * your version of this file under either the CDDL, the GPL Version 2 or
25.39 - * to extend the choice of license to its licensees as provided above.
25.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
25.41 - * Version 2 license, then the option applies only if the new code is
25.42 - * made subject to such option by the copyright holder.
25.43 - */
25.44 -
25.45 -package org.openide.util.lookup;
25.46 -
25.47 -import java.io.BufferedReader;
25.48 -import java.io.IOException;
25.49 -import java.io.InputStream;
25.50 -import java.io.InputStreamReader;
25.51 -import java.lang.ref.Reference;
25.52 -import java.lang.ref.WeakReference;
25.53 -import java.lang.reflect.Method;
25.54 -import java.net.URL;
25.55 -import java.util.ArrayList;
25.56 -import java.util.Collection;
25.57 -import java.util.Enumeration;
25.58 -import java.util.HashSet;
25.59 -import java.util.LinkedHashSet;
25.60 -import java.util.List;
25.61 -import java.util.Map;
25.62 -import java.util.WeakHashMap;
25.63 -import java.util.concurrent.Executor;
25.64 -import java.util.concurrent.Executors;
25.65 -import java.util.logging.Level;
25.66 -import java.util.logging.Logger;
25.67 -import org.openide.util.Lookup;
25.68 -
25.69 -/**
25.70 - * @author Jaroslav Tulach, Jesse Glick
25.71 - * @see Lookups#metaInfServices(ClassLoader,String)
25.72 - * @see "#14722"
25.73 - */
25.74 -final class MetaInfServicesLookup extends AbstractLookup {
25.75 -
25.76 - private static final Logger LOGGER = Logger.getLogger(MetaInfServicesLookup.class.getName());
25.77 - static final Executor RP;
25.78 - static {
25.79 - Executor res = null;
25.80 - try {
25.81 - Class<?> seek = Class.forName("org.openide.util.RequestProcessor");
25.82 - res = (Executor)seek.newInstance();
25.83 - } catch (Throwable t) {
25.84 - res = Executors.newSingleThreadExecutor();
25.85 - }
25.86 - RP = res;
25.87 - }
25.88 - /*TBD: Inject RequestProcessor somehow
25.89 - new RequestProcessor(MetaInfServicesLookup.class.getName(), 1);
25.90 - */
25.91 - private static int knownInstancesCount;
25.92 - private static final List<Reference<Object>> knownInstances;
25.93 - static {
25.94 - knownInstances = new ArrayList<Reference<Object>>();
25.95 - for (int i = 0; i < 512; i++) {
25.96 - knownInstances.add(null);
25.97 - }
25.98 - }
25.99 -
25.100 - /** A set of all requested classes.
25.101 - * Note that classes that we actually succeeded on can never be removed
25.102 - * from here because we hold a strong reference to the loader.
25.103 - * However we also hold classes which are definitely not loadable by
25.104 - * our loader.
25.105 - */
25.106 - private final Map<Class,Object> classes = new WeakHashMap<Class,Object>();
25.107 -
25.108 - /** class loader to use */
25.109 - private final ClassLoader loader;
25.110 - /** prefix to prepend */
25.111 - private final String prefix;
25.112 -
25.113 - /** Create a lookup reading from a specified classloader.
25.114 - */
25.115 - public MetaInfServicesLookup(ClassLoader loader, String prefix) {
25.116 - this.loader = loader;
25.117 - this.prefix = prefix;
25.118 -
25.119 - LOGGER.log(Level.FINE, "Created: {0}", this);
25.120 - }
25.121 -
25.122 - @Override
25.123 - public String toString() {
25.124 - return "MetaInfServicesLookup[" + loader + "]"; // NOI18N
25.125 - }
25.126 -
25.127 - /* Tries to load appropriate resources from manifest files.
25.128 - */
25.129 - @Override
25.130 - protected final void beforeLookup(Lookup.Template t) {
25.131 - Class c = t.getType();
25.132 -
25.133 - Collection<AbstractLookup.Pair<?>> toAdd = null;
25.134 - synchronized (this) {
25.135 - if (classes.get(c) == null) { // NOI18N
25.136 - toAdd = new ArrayList<Pair<?>>();
25.137 - } else {
25.138 - // ok, nothing needs to be done
25.139 - return;
25.140 - }
25.141 - }
25.142 - if (toAdd != null) {
25.143 - search(c, toAdd);
25.144 - }
25.145 - synchronized (this) {
25.146 - if (classes.put(c, "") == null) { // NOI18N
25.147 - // Added new class, search for it.
25.148 - LinkedHashSet<AbstractLookup.Pair<?>> arr = getPairsAsLHS();
25.149 - arr.addAll(toAdd);
25.150 - setPairs(arr, RP);
25.151 - }
25.152 - }
25.153 - }
25.154 -
25.155 - /** Finds all pairs and adds them to the collection.
25.156 - *
25.157 - * @param clazz class to find
25.158 - * @param result collection to add Pair to
25.159 - */
25.160 - private void search(Class<?> clazz, Collection<AbstractLookup.Pair<?>> result) {
25.161 - if (LOGGER.isLoggable(Level.FINER)) {
25.162 - LOGGER.log(Level.FINER, "Searching for " + clazz.getName() + " in " + clazz.getClassLoader() + " from " + this);
25.163 - }
25.164 -
25.165 - String res = prefix + clazz.getName(); // NOI18N
25.166 - Enumeration<URL> en;
25.167 -
25.168 - try {
25.169 - en = loader.getResources(res);
25.170 - } catch (IOException ioe) {
25.171 - // do not use ErrorManager because we are in the startup code
25.172 - // and ErrorManager might not be ready
25.173 - ioe.printStackTrace();
25.174 -
25.175 - return;
25.176 - }
25.177 -
25.178 - // Do not create multiple instances in case more than one JAR
25.179 - // has the same entry in it (and they load to the same class).
25.180 - // Probably would not happen, assuming JARs only list classes
25.181 - // they own, but just in case...
25.182 - List<Item> foundClasses = new ArrayList<Item>();
25.183 - Collection<Class> removeClasses = new ArrayList<Class>();
25.184 -
25.185 - boolean foundOne = false;
25.186 -
25.187 - while (en.hasMoreElements()) {
25.188 - if (!foundOne) {
25.189 - foundOne = true;
25.190 -
25.191 - // Double-check that in fact we can load the *interface* class.
25.192 - // For example, say class I is defined in two JARs, J1 and J2.
25.193 - // There is also an implementation M1 defined in J1, and another
25.194 - // implementation M2 defined in J2.
25.195 - // Classloaders C1 and C2 are made from J1 and J2.
25.196 - // A MetaInfServicesLookup is made from C1. Then the user asks to
25.197 - // lookup I as loaded from C2. J1 has the services line and lists
25.198 - // M1, and we can in fact make it. However it is not of the desired
25.199 - // type to be looked up. Don't do this check, which could be expensive,
25.200 - // unless we expect to be getting some results, however.
25.201 - Class realMcCoy = null;
25.202 -
25.203 - try {
25.204 - realMcCoy = loader.loadClass(clazz.getName());
25.205 - } catch (ClassNotFoundException cnfe) {
25.206 - // our loader does not know about it, OK
25.207 - }
25.208 -
25.209 - if (realMcCoy != clazz) {
25.210 - // Either the interface class is not available at all in our loader,
25.211 - // or it is not the same version as we expected. Don't provide results.
25.212 - if (LOGGER.isLoggable(Level.WARNING)) {
25.213 - if (realMcCoy != null) {
25.214 - LOGGER.log(Level.WARNING,
25.215 - clazz.getName() + " is not the real McCoy! Actually found it in " +
25.216 - realMcCoy.getClassLoader()
25.217 - ); // NOI18N
25.218 - } else {
25.219 - LOGGER.log(Level.WARNING, clazz.getName() + " could not be found in " + loader); // NOI18N
25.220 - }
25.221 - }
25.222 -
25.223 - return;
25.224 - }
25.225 - }
25.226 -
25.227 - URL url = en.nextElement();
25.228 - Item currentItem = null;
25.229 -
25.230 - try {
25.231 - InputStream is = url.openStream();
25.232 -
25.233 - try {
25.234 - BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); // NOI18N
25.235 -
25.236 - while (true) {
25.237 - String line = reader.readLine();
25.238 -
25.239 - if (line == null) {
25.240 - break;
25.241 - }
25.242 -
25.243 - line = line.trim();
25.244 -
25.245 - // is it position attribute?
25.246 - if (line.startsWith("#position=")) {
25.247 - if (currentItem == null) {
25.248 - LOGGER.log(Level.WARNING, "Found line '{0}' in {1} but there is no item to associate it with", new Object[] {line, url});
25.249 - continue;
25.250 - }
25.251 -
25.252 - try {
25.253 - currentItem.position = Integer.parseInt(line.substring(10));
25.254 - } catch (NumberFormatException e) {
25.255 - // do not use ErrorManager because we are in the startup code
25.256 - // and ErrorManager might not be ready
25.257 - e.printStackTrace();
25.258 - }
25.259 - }
25.260 -
25.261 - if (currentItem != null) {
25.262 - insertItem(currentItem, foundClasses);
25.263 - currentItem = null;
25.264 - }
25.265 -
25.266 - // Ignore blank lines and comments.
25.267 - if (line.length() == 0) {
25.268 - continue;
25.269 - }
25.270 -
25.271 - boolean remove = false;
25.272 -
25.273 - if (line.charAt(0) == '#') {
25.274 - if ((line.length() == 1) || (line.charAt(1) != '-')) {
25.275 - continue;
25.276 - }
25.277 -
25.278 - // line starting with #- is a sign to remove that class from lookup
25.279 - remove = true;
25.280 - line = line.substring(2);
25.281 - }
25.282 -
25.283 - Class inst = null;
25.284 -
25.285 - try {
25.286 - // Most lines are fully-qualified class names.
25.287 - inst = Class.forName(line, false, loader);
25.288 - } catch (ClassNotFoundException cnfe) {
25.289 - if (remove) {
25.290 - // if we are removing somthing and the something
25.291 - // cannot be found it is ok to do nothing
25.292 - continue;
25.293 - } else {
25.294 - // but if we are not removing just rethrow
25.295 - throw cnfe;
25.296 - }
25.297 - }
25.298 -
25.299 - if (!clazz.isAssignableFrom(inst)) {
25.300 - throw new ClassNotFoundException(clazzToString(inst) + " not a subclass of " + clazzToString(clazz)); // NOI18N
25.301 - }
25.302 -
25.303 - if (remove) {
25.304 - removeClasses.add(inst);
25.305 - } else {
25.306 - // create new item here, but do not put it into
25.307 - // foundClasses array yet because following line
25.308 - // might specify its position
25.309 - currentItem = new Item();
25.310 - currentItem.clazz = inst;
25.311 - }
25.312 - }
25.313 -
25.314 - if (currentItem != null) {
25.315 - insertItem(currentItem, foundClasses);
25.316 - currentItem = null;
25.317 - }
25.318 - } finally {
25.319 - is.close();
25.320 - }
25.321 - } catch (ClassNotFoundException ex) {
25.322 - LOGGER.log(Level.WARNING, null, ex);
25.323 - } catch (IOException ex) {
25.324 - LOGGER.log(Level.WARNING, null, ex);
25.325 - }
25.326 - }
25.327 -
25.328 - LOGGER.log(Level.FINER, "Found impls of {0}: {1} and removed: {2} from: {3}", new Object[] {clazz.getName(), foundClasses, removeClasses, this});
25.329 -
25.330 - foundClasses.removeAll(removeClasses);
25.331 -
25.332 - for (Item item : foundClasses) {
25.333 - if (removeClasses.contains(item.clazz)) {
25.334 - continue;
25.335 - }
25.336 -
25.337 - result.add(new P(item.clazz));
25.338 - }
25.339 - }
25.340 - private static String clazzToString(Class clazz) {
25.341 - return clazz.getName() + "@" + clazz.getClassLoader() + ":" + clazz.getProtectionDomain().getCodeSource().getLocation(); // NOI18N
25.342 - }
25.343 -
25.344 - /**
25.345 - * Insert item to the list according to item.position value.
25.346 - */
25.347 - private void insertItem(Item item, List<Item> list) {
25.348 - // no position? -> add it to the end
25.349 - if (item.position == -1) {
25.350 - list.add(item);
25.351 -
25.352 - return;
25.353 - }
25.354 -
25.355 - int index = -1;
25.356 - for (Item i : list) {
25.357 - index++;
25.358 -
25.359 - if (i.position == -1) {
25.360 - list.add(index, item);
25.361 -
25.362 - return;
25.363 - } else {
25.364 - if (i.position > item.position) {
25.365 - list.add(index, item);
25.366 -
25.367 - return;
25.368 - }
25.369 - }
25.370 - }
25.371 -
25.372 - list.add(item);
25.373 - }
25.374 -
25.375 - private static class Item {
25.376 - private Class clazz;
25.377 - private int position = -1;
25.378 - @Override
25.379 - public String toString() {
25.380 - return "MetaInfServicesLookup.Item[" + clazz.getName() + "]"; // NOI18N
25.381 - }
25.382 - }
25.383 -
25.384 - /** Pair that holds name of a class and maybe the instance.
25.385 - */
25.386 - private static final class P extends AbstractLookup.Pair<Object> {
25.387 - /** May be one of three things:
25.388 - * 1. The implementation class which was named in the services file.
25.389 - * 2. An instance of it.
25.390 - * 3. Null, if creation of the instance resulted in an error.
25.391 - */
25.392 - private Object object;
25.393 -
25.394 - public P(Class<?> clazz) {
25.395 - this.object = clazz;
25.396 - }
25.397 -
25.398 - /** Finds the class.
25.399 - */
25.400 - private Class<? extends Object> clazz() {
25.401 - Object o = object;
25.402 -
25.403 - if (o instanceof Class) {
25.404 - return (Class<? extends Object>) o;
25.405 - } else if (o != null) {
25.406 - return o.getClass();
25.407 - } else {
25.408 - // Broken.
25.409 - return Object.class;
25.410 - }
25.411 - }
25.412 -
25.413 - @Override
25.414 - public boolean equals(Object o) {
25.415 - if (o instanceof P) {
25.416 - return ((P) o).clazz().equals(clazz());
25.417 - }
25.418 -
25.419 - return false;
25.420 - }
25.421 -
25.422 - @Override
25.423 - public int hashCode() {
25.424 - return clazz().hashCode();
25.425 - }
25.426 -
25.427 - protected boolean instanceOf(Class<?> c) {
25.428 - return c.isAssignableFrom(clazz());
25.429 - }
25.430 -
25.431 - public Class<?> getType() {
25.432 - return clazz();
25.433 - }
25.434 -
25.435 - public Object getInstance() {
25.436 - Object o = object; // keeping local copy to avoid another
25.437 -
25.438 - // thread to modify it under my hands
25.439 - if (o instanceof Class) {
25.440 - synchronized (o) { // o is Class and we will not create
25.441 - // 2 instances of the same class
25.442 -
25.443 - try {
25.444 - Class<?> c = ((Class) o);
25.445 - o = null;
25.446 -
25.447 - synchronized (knownInstances) { // guards only the static cache
25.448 - int size = knownInstances.size();
25.449 - int index = c.hashCode() % size;
25.450 - for (int i = 0; i < size; i++) {
25.451 - Reference<Object> ref = knownInstances.get(index);
25.452 - Object obj = ref == null ? null : ref.get();
25.453 - if (obj == null) {
25.454 - break;
25.455 - }
25.456 - if (c == obj.getClass()) {
25.457 - o = obj;
25.458 - break;
25.459 - }
25.460 - if (++index == size) {
25.461 - index = 0;
25.462 - }
25.463 - }
25.464 - }
25.465 -
25.466 - if (o == null) {
25.467 - o = createInstance(c);
25.468 -
25.469 - synchronized (knownInstances) { // guards only the static cache
25.470 - hashPut(o);
25.471 -
25.472 - int size = knownInstances.size();
25.473 - if (knownInstancesCount > size * 2 / 3) {
25.474 - LOGGER.log(Level.CONFIG, "Cache of size {0} is 2/3 full. Rehashing.", size);
25.475 - HashSet<Reference<Object>> all = new HashSet<Reference<Object>>();
25.476 - all.addAll(knownInstances);
25.477 - for (int i = 0; i < size; i++) {
25.478 - knownInstances.set(i, null);
25.479 - }
25.480 - for (int i = 0; i < size; i++) {
25.481 - knownInstances.add(null);
25.482 - }
25.483 - knownInstancesCount = 0;
25.484 - for (Reference<Object> r : all) {
25.485 - if (r == null) {
25.486 - continue;
25.487 - }
25.488 - Object instance = r.get();
25.489 - if (instance == null) {
25.490 - continue;
25.491 - }
25.492 - hashPut(instance);
25.493 - }
25.494 - }
25.495 -
25.496 - }
25.497 - }
25.498 -
25.499 - // Do not assign to instance var unless there is a complete synch
25.500 - // block between the newInstance and this line. Otherwise we could
25.501 - // be assigning a half-constructed instance that another thread
25.502 - // could see and return immediately.
25.503 - object = o;
25.504 - } catch (Exception ex) {
25.505 - LOGGER.log(Level.WARNING, "Cannot create " + object, ex);
25.506 - object = null;
25.507 - } catch (ExceptionInInitializerError x) { // #174055
25.508 - LOGGER.log(Level.WARNING, "Cannot create " + object, x);
25.509 - object = null;
25.510 - }
25.511 - }
25.512 - }
25.513 -
25.514 - return object;
25.515 - }
25.516 -
25.517 - public String getDisplayName() {
25.518 - return clazz().getName();
25.519 - }
25.520 -
25.521 - public String getId() {
25.522 - return clazz().getName();
25.523 - }
25.524 -
25.525 - protected boolean creatorOf(Object obj) {
25.526 - return obj == object;
25.527 - }
25.528 -
25.529 - private static void hashPut(Object o) {
25.530 - Class<?> c = o.getClass();
25.531 - int size = knownInstances.size();
25.532 - int index = c.hashCode() % size;
25.533 - for (int i = 0; i < size; i++) {
25.534 - Reference<Object> ref = knownInstances.get(index);
25.535 - Object obj = ref == null ? null : ref.get();
25.536 - if (obj == null) {
25.537 - knownInstances.set(index, new WeakReference<Object>(o));
25.538 - knownInstancesCount++;
25.539 - break;
25.540 - }
25.541 - if (++index == size) {
25.542 - index = 0;
25.543 - }
25.544 - }
25.545 - }
25.546 -
25.547 - private static boolean findSharedClassObjectSkip;
25.548 - private static Method findSharedClassObject;
25.549 - /** Basically does c.newInstance(), however the method is complicated
25.550 - * with a special behaviour for old and almost obsoleted NetBeans
25.551 - * class: SharedClassObject.
25.552 - */
25.553 - private static Object createInstance(Class<?> c) throws InstantiationException, IllegalAccessException {
25.554 - if (!findSharedClassObjectSkip) {
25.555 - try {
25.556 - if (findSharedClassObject == null) {
25.557 - Class<?> sco;
25.558 - try {
25.559 - sco = Class.forName("org.openide.util.SharedClassObject"); // NOI18N
25.560 - } catch (ClassNotFoundException ex) {
25.561 - findSharedClassObjectSkip = true;
25.562 - return c.newInstance();
25.563 - }
25.564 - findSharedClassObject = sco.getMethod("findObject", Class.class, boolean.class);
25.565 - }
25.566 - if (findSharedClassObject.getReturnType().isAssignableFrom(c)) {
25.567 - return findSharedClassObject.invoke(null, c, true);
25.568 - }
25.569 - } catch (Exception problem) {
25.570 - throw (InstantiationException)new InstantiationException(problem.getMessage()).initCause(problem);
25.571 - }
25.572 - }
25.573 - return c.newInstance();
25.574 - }
25.575 - }
25.576 -}
26.1 --- a/lookup/src/main/java/org/openide/util/lookup/ProxyLookup.java Wed Jan 27 17:46:23 2010 -0500
26.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
26.3 @@ -1,980 +0,0 @@
26.4 -/*
26.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
26.6 - *
26.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
26.8 - *
26.9 - * The contents of this file are subject to the terms of either the GNU
26.10 - * General Public License Version 2 only ("GPL") or the Common
26.11 - * Development and Distribution License("CDDL") (collectively, the
26.12 - * "License"). You may not use this file except in compliance with the
26.13 - * License. You can obtain a copy of the License at
26.14 - * http://www.netbeans.org/cddl-gplv2.html
26.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
26.16 - * specific language governing permissions and limitations under the
26.17 - * License. When distributing the software, include this License Header
26.18 - * Notice in each file and include the License file at
26.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
26.20 - * particular file as subject to the "Classpath" exception as provided
26.21 - * by Sun in the GPL Version 2 section of the License file that
26.22 - * accompanied this code. If applicable, add the following below the
26.23 - * License Header, with the fields enclosed by brackets [] replaced by
26.24 - * your own identifying information:
26.25 - * "Portions Copyrighted [year] [name of copyright owner]"
26.26 - *
26.27 - * Contributor(s):
26.28 - *
26.29 - * The Original Software is NetBeans. The Initial Developer of the Original
26.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
26.31 - * Microsystems, Inc. All Rights Reserved.
26.32 - *
26.33 - * If you wish your version of this file to be governed by only the CDDL
26.34 - * or only the GPL Version 2, indicate your decision by adding
26.35 - * "[Contributor] elects to include this software in this distribution
26.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
26.37 - * single choice of license, a recipient has the option to distribute
26.38 - * your version of this file under either the CDDL, the GPL Version 2 or
26.39 - * to extend the choice of license to its licensees as provided above.
26.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
26.41 - * Version 2 license, then the option applies only if the new code is
26.42 - * made subject to such option by the copyright holder.
26.43 - */
26.44 -
26.45 -package org.openide.util.lookup;
26.46 -
26.47 -import java.lang.ref.Reference;
26.48 -import java.lang.ref.WeakReference;
26.49 -import java.util.ArrayList;
26.50 -import java.util.Arrays;
26.51 -import java.util.Collection;
26.52 -import java.util.Collections;
26.53 -import java.util.HashMap;
26.54 -import java.util.HashSet;
26.55 -import java.util.IdentityHashMap;
26.56 -import java.util.Iterator;
26.57 -import java.util.List;
26.58 -import java.util.Map;
26.59 -import java.util.Map.Entry;
26.60 -import java.util.Set;
26.61 -import java.util.concurrent.Executor;
26.62 -import javax.swing.event.EventListenerList;
26.63 -import org.openide.util.Lookup;
26.64 -import org.openide.util.LookupEvent;
26.65 -import org.openide.util.LookupListener;
26.66 -
26.67 -/** Implementation of lookup that can delegate to others.
26.68 - *
26.69 - * @author Jaroslav Tulach
26.70 - * @since 1.9
26.71 - */
26.72 -public class ProxyLookup extends Lookup {
26.73 - /** data representing the state of the lookup */
26.74 - private ImmutableInternalData data;
26.75 -
26.76 - /** Create a proxy to some other lookups.
26.77 - * @param lookups the initial delegates
26.78 - */
26.79 - public ProxyLookup(Lookup... lookups) {
26.80 - data = ImmutableInternalData.EMPTY.setLookupsNoFire(lookups, true);
26.81 - }
26.82 -
26.83 - /**
26.84 - * Create a lookup initially proxying to no others.
26.85 - * Permits serializable subclasses.
26.86 - * @since 3.27
26.87 - */
26.88 - protected ProxyLookup() {
26.89 - data = ImmutableInternalData.EMPTY;
26.90 - }
26.91 -
26.92 - @Override
26.93 - public synchronized String toString() {
26.94 - return "ProxyLookup(class=" + getClass() + ")->" + Arrays.asList(getData().getLookups(false)); // NOI18N
26.95 - }
26.96 -
26.97 - /** Getter for the delegates.
26.98 - * @return the array of lookups we delegate to
26.99 - * @since 1.19
26.100 - */
26.101 - protected final Lookup[] getLookups() {
26.102 - synchronized (ProxyLookup.this) {
26.103 - return getData().getLookups(true);
26.104 - }
26.105 - }
26.106 -
26.107 - private Set<Lookup> identityHashSet(Collection<Lookup> current) {
26.108 - Map<Lookup,Void> map = new IdentityHashMap<Lookup, Void>();
26.109 - for (Lookup lookup : current) {
26.110 - map.put(lookup, null);
26.111 - }
26.112 - return map.keySet();
26.113 - }
26.114 -
26.115 - /**
26.116 - * Changes the delegates.
26.117 - *
26.118 - * @param lookups the new lookups to delegate to
26.119 - * @since 1.19 protected
26.120 - */
26.121 - protected final void setLookups(Lookup... lookups) {
26.122 - setLookups(null, lookups);
26.123 - }
26.124 -
26.125 - /**
26.126 - * Changes the delegates immediatelly, notifies the listeners in provided
26.127 - * executor, potentially later.
26.128 - *
26.129 - * @param lookups the new lookups to delegate to
26.130 - * @param notifyIn executor to deliver the notification to listeners or null
26.131 - * @since 7.16
26.132 - */
26.133 - protected final void setLookups(Executor notifyIn, Lookup... lookups) {
26.134 - Collection<Reference<R>> arr;
26.135 - Set<Lookup> newL;
26.136 - Set<Lookup> current;
26.137 - Lookup[] old;
26.138 -
26.139 - Map<Result,LookupListener> toRemove = new IdentityHashMap<Lookup.Result, LookupListener>();
26.140 - Map<Result,LookupListener> toAdd = new IdentityHashMap<Lookup.Result, LookupListener>();
26.141 -
26.142 - ImmutableInternalData orig;
26.143 - synchronized (ProxyLookup.this) {
26.144 - orig = getData();
26.145 - ImmutableInternalData newData = getData().setLookupsNoFire(lookups, false);
26.146 - if (newData == getData()) {
26.147 - return;
26.148 - }
26.149 - arr = setData(newData, lookups, toAdd, toRemove);
26.150 - }
26.151 -
26.152 - // better to do this later than in synchronized block
26.153 - for (Map.Entry<Result, LookupListener> e : toRemove.entrySet()) {
26.154 - e.getKey().removeLookupListener(e.getValue());
26.155 - }
26.156 - for (Map.Entry<Result, LookupListener> e : toAdd.entrySet()) {
26.157 - e.getKey().addLookupListener(e.getValue());
26.158 - }
26.159 -
26.160 -
26.161 - // this cannot be done from the synchronized block
26.162 - final ArrayList<Object> evAndListeners = new ArrayList<Object>();
26.163 - for (Reference<R> ref : arr) {
26.164 - R<?> r = ref.get();
26.165 - if (r != null) {
26.166 - r.collectFires(evAndListeners);
26.167 - }
26.168 - }
26.169 -
26.170 - class Notify implements Runnable {
26.171 - public void run() {
26.172 - Iterator it = evAndListeners.iterator();
26.173 - while (it.hasNext()) {
26.174 - LookupEvent ev = (LookupEvent)it.next();
26.175 - LookupListener l = (LookupListener)it.next();
26.176 - l.resultChanged(ev);
26.177 - }
26.178 - }
26.179 - }
26.180 - Notify n = new Notify();
26.181 - if (notifyIn == null) {
26.182 - n.run();
26.183 - } else {
26.184 - notifyIn.execute(n);
26.185 - }
26.186 - }
26.187 -
26.188 - /** Notifies subclasses that a query is about to be processed.
26.189 - * Subclasses can update its state before the actual processing
26.190 - * begins. It is allowed to call <code>setLookups</code> method
26.191 - * to change/update the set of objects the proxy delegates to.
26.192 - *
26.193 - * @param template the template of the query
26.194 - * @since 1.31
26.195 - */
26.196 - protected void beforeLookup(Template<?> template) {
26.197 - }
26.198 -
26.199 - public final <T> T lookup(Class<T> clazz) {
26.200 - beforeLookup(new Template<T>(clazz));
26.201 -
26.202 - Lookup[] tmpLkps;
26.203 - synchronized (ProxyLookup.this) {
26.204 - tmpLkps = getData().getLookups(false);
26.205 - }
26.206 -
26.207 - for (int i = 0; i < tmpLkps.length; i++) {
26.208 - T o = tmpLkps[i].lookup(clazz);
26.209 -
26.210 - if (o != null) {
26.211 - return o;
26.212 - }
26.213 - }
26.214 -
26.215 - return null;
26.216 - }
26.217 -
26.218 - @Override
26.219 - public final <T> Item<T> lookupItem(Template<T> template) {
26.220 - beforeLookup(template);
26.221 -
26.222 - Lookup[] tmpLkps;
26.223 - synchronized (ProxyLookup.this) {
26.224 - tmpLkps = getData().getLookups(false);
26.225 - }
26.226 -
26.227 - for (int i = 0; i < tmpLkps.length; i++) {
26.228 - Item<T> o = tmpLkps[i].lookupItem(template);
26.229 -
26.230 - if (o != null) {
26.231 - return o;
26.232 - }
26.233 - }
26.234 -
26.235 - return null;
26.236 - }
26.237 -
26.238 - @SuppressWarnings("unchecked")
26.239 - private static <T> R<T> convertResult(R r) {
26.240 - return (R<T>)r;
26.241 - }
26.242 -
26.243 - public final <T> Result<T> lookup(Lookup.Template<T> template) {
26.244 - synchronized (ProxyLookup.this) {
26.245 - ImmutableInternalData[] res = { null };
26.246 - R<T> newR = getData().findResult(this, res, template);
26.247 - setData(res[0], getData().getLookups(false), null, null);
26.248 - return newR;
26.249 - }
26.250 - }
26.251 -
26.252 - /** Unregisters a template from the has map.
26.253 - */
26.254 - private final void unregisterTemplate(Template<?> template) {
26.255 - synchronized (ProxyLookup.this) {
26.256 - ImmutableInternalData id = getData();
26.257 - if (id == null) {
26.258 - return;
26.259 - }
26.260 - setData(id.removeTemplate(this, template), getData().getLookups(false), null, null);
26.261 - }
26.262 - }
26.263 -
26.264 - private ImmutableInternalData getData() {
26.265 - assert Thread.holdsLock(this);
26.266 - return data;
26.267 - }
26.268 -
26.269 - private Collection<Reference<R>> setData(
26.270 - ImmutableInternalData newData, Lookup[] current,
26.271 - Map<Result,LookupListener> toAdd, Map<Result,LookupListener> toRemove
26.272 - ) {
26.273 - assert Thread.holdsLock(ProxyLookup.this);
26.274 - assert newData != null;
26.275 -
26.276 - ImmutableInternalData previous = this.getData();
26.277 -
26.278 - if (previous == newData) {
26.279 - return Collections.emptyList();
26.280 - }
26.281 -
26.282 - if (newData.isEmpty()) {
26.283 - this.setData(newData);
26.284 - // no affected results => exit
26.285 - return Collections.emptyList();
26.286 - }
26.287 -
26.288 - Collection<Reference<R>> arr = newData.references();
26.289 -
26.290 - Set<Lookup> removed = identityHashSet(previous.getLookupsList());
26.291 - Set<Lookup> currentSet = identityHashSet(Arrays.asList(current));
26.292 - Set<Lookup> newL = identityHashSet(currentSet);
26.293 - removed.removeAll(currentSet); // current contains just those lookups that have disappeared
26.294 - newL.removeAll(previous.getLookupsList()); // really new lookups
26.295 -
26.296 - for (Reference<R> ref : arr) {
26.297 - R<?> r = ref.get();
26.298 - if (r != null) {
26.299 - r.lookupChange(newData, current, previous, newL, removed, toAdd, toRemove);
26.300 - if (this.getData() != previous) {
26.301 - // the data were changed by an re-entrant call
26.302 - // skip any other change processing, as it is not needed
26.303 - // anymore
26.304 - }
26.305 - }
26.306 - }
26.307 - for (Reference<R> ref : arr) {
26.308 - R<?> r = ref.get();
26.309 - if (r != null) {
26.310 - r.data = newData;
26.311 - }
26.312 - }
26.313 - this.setData(newData);
26.314 - return arr;
26.315 - }
26.316 -
26.317 - private void setData(ImmutableInternalData data) {
26.318 - this.data = data;
26.319 - }
26.320 -
26.321 - /** Result of a lookup request. Allows access to single object
26.322 - * that was found (not too useful) and also to all objects found
26.323 - * (more useful).
26.324 - */
26.325 - private static final class R<T> extends WaitableResult<T> {
26.326 - /** weak listener & result */
26.327 - private final WeakResult<T> weakL;
26.328 -
26.329 - /** list of listeners added */
26.330 - private javax.swing.event.EventListenerList listeners;
26.331 -
26.332 - /** collection of Objects */
26.333 - private Collection[] cache;
26.334 -
26.335 -
26.336 - /** associated lookup */
26.337 - private ImmutableInternalData data;
26.338 -
26.339 - /** Constructor.
26.340 - */
26.341 - public R(ProxyLookup proxy, Lookup.Template<T> t) {
26.342 - this.weakL = new WeakResult<T>(proxy, this, t);
26.343 - }
26.344 -
26.345 - private ProxyLookup proxy() {
26.346 - return weakL.result.proxy;
26.347 - }
26.348 -
26.349 - @SuppressWarnings("unchecked")
26.350 - private Result<T>[] newResults(int len) {
26.351 - return new Result[len];
26.352 - }
26.353 -
26.354 - @Override
26.355 - protected void finalize() {
26.356 - weakL.result.run();
26.357 - }
26.358 -
26.359 - /** initializes the results
26.360 - */
26.361 - private Result<T>[] initResults() {
26.362 - BIG_LOOP: for (;;) {
26.363 - Lookup[] myLkps;
26.364 - ImmutableInternalData current;
26.365 - synchronized (proxy()) {
26.366 - if (weakL.getResults() != null) {
26.367 - return weakL.getResults();
26.368 - }
26.369 - myLkps = data.getLookups(false);
26.370 - current = data;
26.371 - }
26.372 -
26.373 - Result<T>[] arr = newResults(myLkps.length);
26.374 -
26.375 - for (int i = 0; i < arr.length; i++) {
26.376 - arr[i] = myLkps[i].lookup(weakL.result.template);
26.377 - }
26.378 -
26.379 - synchronized (proxy()) {
26.380 - if (current != data) {
26.381 - continue;
26.382 - }
26.383 -
26.384 - Lookup[] currentLkps = data.getLookups(false);
26.385 - if (currentLkps.length != myLkps.length) {
26.386 - continue BIG_LOOP;
26.387 - }
26.388 - for (int i = 0; i < currentLkps.length; i++) {
26.389 - if (currentLkps[i] != myLkps[i]) {
26.390 - continue BIG_LOOP;
26.391 - }
26.392 - }
26.393 -
26.394 - // some other thread might compute the result mean while.
26.395 - // if not finish the computation yourself
26.396 - if (weakL.getResults() != null) {
26.397 - return weakL.getResults();
26.398 - }
26.399 -
26.400 - weakL.setResults(arr);
26.401 - }
26.402 - for (int i = 0; i < arr.length; i++) {
26.403 - arr[i].addLookupListener(weakL);
26.404 - }
26.405 - return arr;
26.406 - }
26.407 - }
26.408 -
26.409 - /** Called when there is a change in the list of proxied lookups.
26.410 - * @param added set of added lookups
26.411 - * @param remove set of removed lookups
26.412 - * @param current array of current lookups
26.413 - */
26.414 - final void lookupChange(
26.415 - ImmutableInternalData newData, Lookup[] current, ImmutableInternalData oldData,
26.416 - Set<Lookup> added, Set<Lookup> removed,
26.417 - Map<Result,LookupListener> toAdd, Map<Result,LookupListener> toRemove
26.418 - ) {
26.419 - if (weakL.getResults() == null) {
26.420 - // not computed yet, do not need to do anything
26.421 - return;
26.422 - }
26.423 -
26.424 - Lookup[] old = oldData.getLookups(false);
26.425 -
26.426 - // map (Lookup, Lookup.Result)
26.427 - Map<Lookup,Result<T>> map = new IdentityHashMap<Lookup,Result<T>>(old.length * 2);
26.428 -
26.429 - for (int i = 0; i < old.length; i++) {
26.430 - if (removed.contains(old[i])) {
26.431 - // removed lookup
26.432 - if (toRemove != null) {
26.433 - toRemove.put(weakL.getResults()[i], weakL);
26.434 - }
26.435 - } else {
26.436 - // remember the association
26.437 - map.put(old[i], weakL.getResults()[i]);
26.438 - }
26.439 - }
26.440 -
26.441 - Lookup.Result<T>[] arr = newResults(current.length);
26.442 -
26.443 - for (int i = 0; i < current.length; i++) {
26.444 - if (added.contains(current[i])) {
26.445 - // new lookup
26.446 - arr[i] = current[i].lookup(weakL.result.template);
26.447 - if (toAdd != null) {
26.448 - toAdd.put(arr[i], weakL);
26.449 - }
26.450 - } else {
26.451 - // old lookup
26.452 - arr[i] = map.get(current[i]);
26.453 -
26.454 - if (arr[i] == null) {
26.455 - // assert
26.456 - throw new IllegalStateException();
26.457 - }
26.458 - }
26.459 - }
26.460 -
26.461 - // remember the new results
26.462 - weakL.setResults(arr);
26.463 - }
26.464 -
26.465 - /** Just delegates.
26.466 - */
26.467 - public void addLookupListener(LookupListener l) {
26.468 - synchronized (proxy()) {
26.469 - if (listeners == null) {
26.470 - listeners = new EventListenerList();
26.471 - }
26.472 - }
26.473 -
26.474 - listeners.add(LookupListener.class, l);
26.475 - initResults();
26.476 - }
26.477 -
26.478 - /** Just delegates.
26.479 - */
26.480 - public void removeLookupListener(LookupListener l) {
26.481 - if (listeners != null) {
26.482 - listeners.remove(LookupListener.class, l);
26.483 - }
26.484 - }
26.485 -
26.486 - /** Access to all instances in the result.
26.487 - * @return collection of all instances
26.488 - */
26.489 - @SuppressWarnings("unchecked")
26.490 - public java.util.Collection<T> allInstances() {
26.491 - return computeResult(0);
26.492 - }
26.493 -
26.494 - /** Classes of all results. Set of the most concreate classes
26.495 - * that are registered in the system.
26.496 - * @return set of Class objects
26.497 - */
26.498 - @SuppressWarnings("unchecked")
26.499 - @Override
26.500 - public java.util.Set<Class<? extends T>> allClasses() {
26.501 - return (java.util.Set<Class<? extends T>>) computeResult(1);
26.502 - }
26.503 -
26.504 - /** All registered items. The collection of all pairs of
26.505 - * ii and their classes.
26.506 - * @return collection of Lookup.Item
26.507 - */
26.508 - @SuppressWarnings("unchecked")
26.509 - @Override
26.510 - public java.util.Collection<? extends Item<T>> allItems() {
26.511 - return computeResult(2);
26.512 - }
26.513 -
26.514 - /** Computes results from proxied lookups.
26.515 - * @param indexToCache 0 = allInstances, 1 = allClasses, 2 = allItems
26.516 - * @return the collection or set of the objects
26.517 - */
26.518 - private java.util.Collection computeResult(int indexToCache) {
26.519 - // results to use
26.520 - Lookup.Result<T>[] arr = myBeforeLookup();
26.521 -
26.522 - // if the call to beforeLookup resulted in deletion of caches
26.523 - synchronized (proxy()) {
26.524 - Collection[] cc = getCache();
26.525 - if (cc != null && cc != NO_CACHE) {
26.526 - Collection result = cc[indexToCache];
26.527 - if (result != null) {
26.528 - return result;
26.529 - }
26.530 - }
26.531 - }
26.532 -
26.533 - // initialize the collection to hold result
26.534 - Collection<Object> compute;
26.535 - Collection<Object> ret;
26.536 -
26.537 - if (indexToCache == 1) {
26.538 - HashSet<Object> s = new HashSet<Object>();
26.539 - compute = s;
26.540 - ret = Collections.unmodifiableSet(s);
26.541 - } else {
26.542 - List<Object> l = new ArrayList<Object>(arr.length * 2);
26.543 - compute = l;
26.544 - ret = Collections.unmodifiableList(l);
26.545 - }
26.546 -
26.547 - // fill the collection
26.548 - for (int i = 0; i < arr.length; i++) {
26.549 - switch (indexToCache) {
26.550 - case 0:
26.551 - compute.addAll(arr[i].allInstances());
26.552 - break;
26.553 - case 1:
26.554 - compute.addAll(arr[i].allClasses());
26.555 - break;
26.556 - case 2:
26.557 - compute.addAll(arr[i].allItems());
26.558 - break;
26.559 - default:
26.560 - assert false : "Wrong index: " + indexToCache;
26.561 - }
26.562 - }
26.563 -
26.564 -
26.565 -
26.566 - synchronized (proxy()) {
26.567 - Collection[] cc = getCache();
26.568 - if (cc == null || cc == NO_CACHE) {
26.569 - // initialize the cache to indicate this result is in use
26.570 - setCache(cc = new Collection[3]);
26.571 - }
26.572 -
26.573 - if (arr == weakL.getResults()) {
26.574 - // updates the results, if the results have not been
26.575 - // changed during the computation of allInstances
26.576 - cc[indexToCache] = ret;
26.577 - }
26.578 - }
26.579 -
26.580 - return ret;
26.581 - }
26.582 -
26.583 - /** When the result changes, fire the event.
26.584 - */
26.585 - public void resultChanged(LookupEvent ev) {
26.586 - collectFires(null);
26.587 - }
26.588 -
26.589 - protected void collectFires(Collection<Object> evAndListeners) {
26.590 - boolean modified = true;
26.591 -
26.592 - try {
26.593 - // clear cached instances
26.594 - Collection oldItems;
26.595 - Collection oldInstances;
26.596 - synchronized (proxy()) {
26.597 - final Collection[] cc = getCache();
26.598 - if (cc == NO_CACHE) {
26.599 - return;
26.600 - }
26.601 -
26.602 - oldInstances = cc == null ? null : cc[0];
26.603 - oldItems = cc == null ? null : cc[2];
26.604 -
26.605 -
26.606 - if (listeners == null || listeners.getListenerCount() == 0) {
26.607 - // clear the cache
26.608 - setCache(new Collection[3]);
26.609 - return;
26.610 - }
26.611 -
26.612 - // ignore events if they arrive as a result of call to allItems
26.613 - // or allInstances, bellow...
26.614 - setCache(NO_CACHE);
26.615 - }
26.616 -
26.617 - if (oldItems != null) {
26.618 - Collection newItems = allItems();
26.619 - if (oldItems.equals(newItems)) {
26.620 - modified = false;
26.621 - }
26.622 - } else {
26.623 - if (oldInstances != null) {
26.624 - Collection newInstances = allInstances();
26.625 - if (oldInstances.equals(newInstances)) {
26.626 - modified = false;
26.627 - }
26.628 - } else {
26.629 - synchronized (proxy()) {
26.630 - if (getCache() == NO_CACHE) {
26.631 - // we have to initialize the cache
26.632 - // to show that the result has been initialized
26.633 - setCache(new Collection[3]);
26.634 - }
26.635 - }
26.636 - }
26.637 - }
26.638 - } finally {
26.639 - synchronized (proxy()) {
26.640 - if (getCache() == NO_CACHE) {
26.641 - setCache(null);
26.642 - }
26.643 - }
26.644 - }
26.645 -
26.646 - if (modified) {
26.647 - LookupEvent ev = new LookupEvent(this);
26.648 - AbstractLookup.notifyListeners(listeners.getListenerList(), ev, evAndListeners);
26.649 - }
26.650 - }
26.651 -
26.652 - /** Implementation of my before lookup.
26.653 - * @return results to work on.
26.654 - */
26.655 - private Lookup.Result<T>[] myBeforeLookup() {
26.656 - Template<T> template = weakL.result.template;
26.657 -
26.658 - proxy().beforeLookup(template);
26.659 -
26.660 - Lookup.Result<T>[] arr = initResults();
26.661 -
26.662 - // invoke update on the results
26.663 - for (int i = 0; i < arr.length; i++) {
26.664 - if (arr[i] instanceof WaitableResult) {
26.665 - WaitableResult w = (WaitableResult) arr[i];
26.666 - w.beforeLookup(template);
26.667 - }
26.668 - }
26.669 -
26.670 - return arr;
26.671 - }
26.672 -
26.673 - /** Used by proxy results to synchronize before lookup.
26.674 - */
26.675 - protected void beforeLookup(Lookup.Template t) {
26.676 - if (t.getType() == weakL.result.template.getType()) {
26.677 - myBeforeLookup();
26.678 - }
26.679 - }
26.680 -
26.681 - private Collection[] getCache() {
26.682 - return cache;
26.683 - }
26.684 -
26.685 - private void setCache(Collection[] cache) {
26.686 - assert Thread.holdsLock(proxy());
26.687 - this.cache = cache;
26.688 - }
26.689 - private static final Collection[] NO_CACHE = new Collection[0];
26.690 - }
26.691 - private static final class WeakRef<T> extends WeakReference<R> implements Runnable {
26.692 - final WeakResult<T> result;
26.693 - final ProxyLookup proxy;
26.694 - final Template<T> template;
26.695 -
26.696 - public WeakRef(R r, WeakResult<T> result, ProxyLookup proxy, Template<T> template) {
26.697 - super(r);
26.698 - this.result = result;
26.699 - this.template = template;
26.700 - this.proxy = proxy;
26.701 - }
26.702 -
26.703 - public void run() {
26.704 - result.removeListeners();
26.705 - proxy.unregisterTemplate(template);
26.706 - }
26.707 - }
26.708 -
26.709 -
26.710 - private static final class WeakResult<T> extends WaitableResult<T> implements LookupListener, Runnable {
26.711 - /** all results */
26.712 - private Lookup.Result<T>[] results;
26.713 - private final WeakRef<T> result;
26.714 -
26.715 - public WeakResult(ProxyLookup proxy, R r, Template<T> t) {
26.716 - this.result = new WeakRef<T>(r, this, proxy, t);
26.717 - }
26.718 -
26.719 - final void removeListeners() {
26.720 - Lookup.Result<T>[] arr = this.getResults();
26.721 - if (arr == null) {
26.722 - return;
26.723 - }
26.724 -
26.725 - for(int i = 0; i < arr.length; i++) {
26.726 - arr[i].removeLookupListener(this);
26.727 - }
26.728 - }
26.729 -
26.730 - protected void beforeLookup(Lookup.Template t) {
26.731 - R r = result.get();
26.732 - if (r != null) {
26.733 - r.beforeLookup(t);
26.734 - } else {
26.735 - removeListeners();
26.736 - }
26.737 - }
26.738 -
26.739 - protected void collectFires(Collection<Object> evAndListeners) {
26.740 - R<?> r = result.get();
26.741 - if (r != null) {
26.742 - r.collectFires(evAndListeners);
26.743 - } else {
26.744 - removeListeners();
26.745 - }
26.746 - }
26.747 -
26.748 - public void addLookupListener(LookupListener l) {
26.749 - assert false;
26.750 - }
26.751 -
26.752 - public void removeLookupListener(LookupListener l) {
26.753 - assert false;
26.754 - }
26.755 -
26.756 - public Collection<T> allInstances() {
26.757 - assert false;
26.758 - return null;
26.759 - }
26.760 -
26.761 - public void resultChanged(LookupEvent ev) {
26.762 - R r = result.get();
26.763 - if (r != null) {
26.764 - r.resultChanged(ev);
26.765 - } else {
26.766 - removeListeners();
26.767 - }
26.768 - }
26.769 -
26.770 - @Override
26.771 - public Collection<? extends Item<T>> allItems() {
26.772 - assert false;
26.773 - return null;
26.774 - }
26.775 -
26.776 - @Override
26.777 - public Set<Class<? extends T>> allClasses() {
26.778 - assert false;
26.779 - return null;
26.780 - }
26.781 -
26.782 - public void run() {
26.783 - removeListeners();
26.784 - }
26.785 -
26.786 - private Lookup.Result<T>[] getResults() {
26.787 - return results;
26.788 - }
26.789 -
26.790 - private void setResults(Lookup.Result<T>[] results) {
26.791 - this.results = results;
26.792 - }
26.793 - } // end of WeakResult
26.794 -
26.795 - static abstract class ImmutableInternalData extends Object {
26.796 - static final ImmutableInternalData EMPTY = new EmptyInternalData();
26.797 - static final Lookup[] EMPTY_ARR = new Lookup[0];
26.798 -
26.799 -
26.800 - protected ImmutableInternalData() {
26.801 - }
26.802 -
26.803 - public static ImmutableInternalData create(Object lkp, Map<Template, Reference<R>> results) {
26.804 - if (results.size() == 0 && lkp == EMPTY_ARR) {
26.805 - return EMPTY;
26.806 - }
26.807 - if (results.size() == 1) {
26.808 - Entry<Template,Reference<R>> e = results.entrySet().iterator().next();
26.809 - return new SingleInternalData(lkp, e.getKey(), e.getValue());
26.810 - }
26.811 -
26.812 - return new RealInternalData(lkp, results);
26.813 - }
26.814 -
26.815 - protected abstract boolean isEmpty();
26.816 - protected abstract Map<Template, Reference<R>> getResults();
26.817 - protected abstract Object getRawLookups();
26.818 -
26.819 - final Collection<Reference<R>> references() {
26.820 - return getResults().values();
26.821 - }
26.822 -
26.823 - final <T> ImmutableInternalData removeTemplate(ProxyLookup proxy, Template<T> template) {
26.824 - if (getResults().containsKey(template)) {
26.825 - HashMap<Template,Reference<R>> c = new HashMap<Template, Reference<ProxyLookup.R>>(getResults());
26.826 - Reference<R> ref = c.remove(template);
26.827 - if (ref != null && ref.get() != null) {
26.828 - // seems like there is a reference to a result for this template
26.829 - // thta is still alive
26.830 - return this;
26.831 - }
26.832 - return create(getRawLookups(), c);
26.833 - } else {
26.834 - return this;
26.835 - }
26.836 - }
26.837 -
26.838 - <T> R<T> findResult(ProxyLookup proxy, ImmutableInternalData[] newData, Template<T> template) {
26.839 - assert Thread.holdsLock(proxy);
26.840 -
26.841 - Map<Template,Reference<R>> map = getResults();
26.842 -
26.843 - Reference<R> ref = map.get(template);
26.844 - R r = (ref == null) ? null : ref.get();
26.845 -
26.846 - if (r != null) {
26.847 - newData[0] = this;
26.848 - return convertResult(r);
26.849 - }
26.850 -
26.851 - HashMap<Template, Reference<R>> res = new HashMap<Template, Reference<R>>(map);
26.852 - R<T> newR = new R<T>(proxy, template);
26.853 - res.put(template, new java.lang.ref.SoftReference<R>(newR));
26.854 - newR.data = newData[0] = create(getRawLookups(), res);
26.855 - return newR;
26.856 - }
26.857 - final ImmutableInternalData setLookupsNoFire(Lookup[] lookups, boolean skipCheck) {
26.858 - Object l;
26.859 -
26.860 - if (!skipCheck) {
26.861 - Lookup[] previous = getLookups(false);
26.862 - if (previous == lookups) {
26.863 - return this;
26.864 - }
26.865 -
26.866 - if (previous.length == lookups.length) {
26.867 - int same = 0;
26.868 - for (int i = 0; i < previous.length; i++) {
26.869 - if (lookups[i] != previous[i]) {
26.870 - break;
26.871 - }
26.872 - same++;
26.873 - }
26.874 - if (same == previous.length) {
26.875 - return this;
26.876 - }
26.877 - }
26.878 - }
26.879 -
26.880 - if (lookups.length == 1) {
26.881 - l = lookups[0];
26.882 - assert l != null : "Cannot assign null delegate";
26.883 - } else {
26.884 - if (lookups.length == 0) {
26.885 - l = EMPTY_ARR;
26.886 - } else {
26.887 - l = lookups.clone();
26.888 - }
26.889 - }
26.890 -
26.891 - if (isEmpty() && l == EMPTY_ARR) {
26.892 - return this;
26.893 - }
26.894 -
26.895 - return create(l, getResults());
26.896 - }
26.897 - final Lookup[] getLookups(boolean clone) {
26.898 - Object l = this.getRawLookups();
26.899 - if (l instanceof Lookup) {
26.900 - return new Lookup[] { (Lookup)l };
26.901 - } else {
26.902 - Lookup[] arr = (Lookup[])l;
26.903 - if (clone) {
26.904 - arr = arr.clone();
26.905 - }
26.906 - return arr;
26.907 - }
26.908 - }
26.909 - final List<Lookup> getLookupsList() {
26.910 - return Arrays.asList(getLookups(false));
26.911 - }
26.912 -
26.913 - } // end of ImmutableInternalData
26.914 -
26.915 - private static final class SingleInternalData extends ImmutableInternalData {
26.916 - /** lookups to delegate to (either Lookup or array of Lookups) */
26.917 - private final Object lookups;
26.918 - private final Template template;
26.919 - private final Reference<ProxyLookup.R> result;
26.920 -
26.921 - public SingleInternalData(Object lookups, Template<?> template, Reference<ProxyLookup.R> result) {
26.922 - this.lookups = lookups;
26.923 - this.template = template;
26.924 - this.result = result;
26.925 - }
26.926 -
26.927 - protected final boolean isEmpty() {
26.928 - return false;
26.929 - }
26.930 -
26.931 - protected Map<Template, Reference<R>> getResults() {
26.932 - return Collections.singletonMap(template, result);
26.933 - }
26.934 -
26.935 - protected Object getRawLookups() {
26.936 - return lookups;
26.937 - }
26.938 - }
26.939 - private static final class RealInternalData extends ImmutableInternalData {
26.940 - /** lookups to delegate to (either Lookup or array of Lookups) */
26.941 - private final Object lookups;
26.942 -
26.943 - /** map of templates to currently active results */
26.944 - private final Map<Template,Reference<R>> results;
26.945 -
26.946 - public RealInternalData(Object lookups, Map<Template, Reference<ProxyLookup.R>> results) {
26.947 - this.results = results;
26.948 - this.lookups = lookups;
26.949 - }
26.950 -
26.951 - protected final boolean isEmpty() {
26.952 - return false;
26.953 - }
26.954 -
26.955 - protected Map<Template, Reference<R>> getResults() {
26.956 - boolean strict = false;
26.957 - assert strict = true;
26.958 - return strict ? Collections.unmodifiableMap(results) : results;
26.959 - }
26.960 -
26.961 - protected Object getRawLookups() {
26.962 - return lookups;
26.963 - }
26.964 - }
26.965 -
26.966 - private static final class EmptyInternalData extends ImmutableInternalData {
26.967 - EmptyInternalData() {
26.968 - }
26.969 -
26.970 - protected final boolean isEmpty() {
26.971 - return true;
26.972 - }
26.973 -
26.974 - protected Map<Template, Reference<R>> getResults() {
26.975 - return Collections.emptyMap();
26.976 - }
26.977 -
26.978 - @Override
26.979 - protected Object getRawLookups() {
26.980 - return EMPTY_ARR;
26.981 - }
26.982 - } // end of EmptyInternalData
26.983 -}
27.1 --- a/lookup/src/main/java/org/openide/util/lookup/ServiceProvider.java Wed Jan 27 17:46:23 2010 -0500
27.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
27.3 @@ -1,102 +0,0 @@
27.4 -/*
27.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
27.6 - *
27.7 - * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
27.8 - *
27.9 - * The contents of this file are subject to the terms of either the GNU
27.10 - * General Public License Version 2 only ("GPL") or the Common
27.11 - * Development and Distribution License("CDDL") (collectively, the
27.12 - * "License"). You may not use this file except in compliance with the
27.13 - * License. You can obtain a copy of the License at
27.14 - * http://www.netbeans.org/cddl-gplv2.html
27.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
27.16 - * specific language governing permissions and limitations under the
27.17 - * License. When distributing the software, include this License Header
27.18 - * Notice in each file and include the License file at
27.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
27.20 - * particular file as subject to the "Classpath" exception as provided
27.21 - * by Sun in the GPL Version 2 section of the License file that
27.22 - * accompanied this code. If applicable, add the following below the
27.23 - * License Header, with the fields enclosed by brackets [] replaced by
27.24 - * your own identifying information:
27.25 - * "Portions Copyrighted [year] [name of copyright owner]"
27.26 - *
27.27 - * If you wish your version of this file to be governed by only the CDDL
27.28 - * or only the GPL Version 2, indicate your decision by adding
27.29 - * "[Contributor] elects to include this software in this distribution
27.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
27.31 - * single choice of license, a recipient has the option to distribute
27.32 - * your version of this file under either the CDDL, the GPL Version 2 or
27.33 - * to extend the choice of license to its licensees as provided above.
27.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
27.35 - * Version 2 license, then the option applies only if the new code is
27.36 - * made subject to such option by the copyright holder.
27.37 - *
27.38 - * Contributor(s):
27.39 - *
27.40 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
27.41 - */
27.42 -
27.43 -package org.openide.util.lookup;
27.44 -
27.45 -import java.lang.annotation.ElementType;
27.46 -import java.lang.annotation.Retention;
27.47 -import java.lang.annotation.RetentionPolicy;
27.48 -import java.lang.annotation.Target;
27.49 -import org.openide.util.Lookup;
27.50 -
27.51 -/**
27.52 - * Declarative registration of a singleton service provider.
27.53 - * By marking an implementation class with this annotation,
27.54 - * you automatically register that implementation, normally in {@link Lookup#getDefault}.
27.55 - * The class must be public and have a public no-argument constructor.
27.56 - * <p>Example of usage:
27.57 - * <pre>
27.58 - * package my.module;
27.59 - * import org.netbeans.spi.whatever.Thing;
27.60 - * import org.openide.util.lookup.ServiceProvider;
27.61 - * @ServiceProvider(service=Thing.class)
27.62 - * public class MyThing implements Thing {...}
27.63 - * </pre>
27.64 - * <p>would result in a resource file <code>META-INF/services/org.netbeans.spi.whatever.Thing</code>
27.65 - * containing the single line of text: <code>my.module.MyThing</code>
27.66 - * @see Lookups#metaInfServices(ClassLoader)
27.67 - * @since org.openide.util 7.20
27.68 - */
27.69 -@Retention(RetentionPolicy.SOURCE)
27.70 -@Target(ElementType.TYPE)
27.71 -public @interface ServiceProvider {
27.72 -
27.73 - /**
27.74 - * The interface (or abstract class) to register this implementation under.
27.75 - * It is an error if the implementation class is not in fact assignable to the interface.
27.76 - * <p>If you need to register one class under multiple interfaces, use {@link ServiceProviders}.
27.77 - * <p>Requests to look up the specified interface should result in this implementation.
27.78 - * Requests for any other types may or may not result in this implementation even if the
27.79 - * implementation is assignable to those types.
27.80 - */
27.81 - Class<?> service();
27.82 -
27.83 - /**
27.84 - * An optional position in which to register this service relative to others.
27.85 - * Lower-numbered services are returned in the lookup result first.
27.86 - * Services with no specified position are returned last.
27.87 - */
27.88 - int position() default Integer.MAX_VALUE;
27.89 -
27.90 - /**
27.91 - * An optional list of implementations (given as fully-qualified class names) which this implementation supersedes.
27.92 - * If specified, those implementations will not be loaded even if they were registered.
27.93 - * Useful on occasion to cancel a generic implementation and replace it with a more advanced one.
27.94 - */
27.95 - String[] supersedes() default {};
27.96 -
27.97 - /**
27.98 - * An optional path to register this implementation in.
27.99 - * For example, <code>Projects/sometype/Nodes</code> could be used.
27.100 - * This style of registration would be recognized by {@link Lookups#forPath}
27.101 - * rather than {@link Lookup#getDefault}.
27.102 - */
27.103 - String path() default "";
27.104 -
27.105 -}
28.1 --- a/lookup/src/main/java/org/openide/util/lookup/ServiceProviders.java Wed Jan 27 17:46:23 2010 -0500
28.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
28.3 @@ -1,60 +0,0 @@
28.4 -/*
28.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
28.6 - *
28.7 - * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
28.8 - *
28.9 - * The contents of this file are subject to the terms of either the GNU
28.10 - * General Public License Version 2 only ("GPL") or the Common
28.11 - * Development and Distribution License("CDDL") (collectively, the
28.12 - * "License"). You may not use this file except in compliance with the
28.13 - * License. You can obtain a copy of the License at
28.14 - * http://www.netbeans.org/cddl-gplv2.html
28.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
28.16 - * specific language governing permissions and limitations under the
28.17 - * License. When distributing the software, include this License Header
28.18 - * Notice in each file and include the License file at
28.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
28.20 - * particular file as subject to the "Classpath" exception as provided
28.21 - * by Sun in the GPL Version 2 section of the License file that
28.22 - * accompanied this code. If applicable, add the following below the
28.23 - * License Header, with the fields enclosed by brackets [] replaced by
28.24 - * your own identifying information:
28.25 - * "Portions Copyrighted [year] [name of copyright owner]"
28.26 - *
28.27 - * If you wish your version of this file to be governed by only the CDDL
28.28 - * or only the GPL Version 2, indicate your decision by adding
28.29 - * "[Contributor] elects to include this software in this distribution
28.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
28.31 - * single choice of license, a recipient has the option to distribute
28.32 - * your version of this file under either the CDDL, the GPL Version 2 or
28.33 - * to extend the choice of license to its licensees as provided above.
28.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
28.35 - * Version 2 license, then the option applies only if the new code is
28.36 - * made subject to such option by the copyright holder.
28.37 - *
28.38 - * Contributor(s):
28.39 - *
28.40 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
28.41 - */
28.42 -
28.43 -package org.openide.util.lookup;
28.44 -
28.45 -import java.lang.annotation.ElementType;
28.46 -import java.lang.annotation.Retention;
28.47 -import java.lang.annotation.RetentionPolicy;
28.48 -import java.lang.annotation.Target;
28.49 -
28.50 -/**
28.51 - * Similar to {@link ServiceProvider} but permits multiple registrations of one class.
28.52 - * @since org.openide.util 7.20
28.53 - */
28.54 -@Retention(RetentionPolicy.SOURCE)
28.55 -@Target(ElementType.TYPE)
28.56 -public @interface ServiceProviders {
28.57 -
28.58 - /**
28.59 - * List of service provider registrations.
28.60 - */
28.61 - ServiceProvider[] value();
28.62 -
28.63 -}
29.1 --- a/lookup/src/main/java/org/openide/util/lookup/SimpleLookup.java Wed Jan 27 17:46:23 2010 -0500
29.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
29.3 @@ -1,250 +0,0 @@
29.4 -/*
29.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
29.6 - *
29.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
29.8 - *
29.9 - * The contents of this file are subject to the terms of either the GNU
29.10 - * General Public License Version 2 only ("GPL") or the Common
29.11 - * Development and Distribution License("CDDL") (collectively, the
29.12 - * "License"). You may not use this file except in compliance with the
29.13 - * License. You can obtain a copy of the License at
29.14 - * http://www.netbeans.org/cddl-gplv2.html
29.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
29.16 - * specific language governing permissions and limitations under the
29.17 - * License. When distributing the software, include this License Header
29.18 - * Notice in each file and include the License file at
29.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
29.20 - * particular file as subject to the "Classpath" exception as provided
29.21 - * by Sun in the GPL Version 2 section of the License file that
29.22 - * accompanied this code. If applicable, add the following below the
29.23 - * License Header, with the fields enclosed by brackets [] replaced by
29.24 - * your own identifying information:
29.25 - * "Portions Copyrighted [year] [name of copyright owner]"
29.26 - *
29.27 - * Contributor(s):
29.28 - *
29.29 - * The Original Software is NetBeans. The Initial Developer of the Original
29.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
29.31 - * Microsystems, Inc. All Rights Reserved.
29.32 - *
29.33 - * If you wish your version of this file to be governed by only the CDDL
29.34 - * or only the GPL Version 2, indicate your decision by adding
29.35 - * "[Contributor] elects to include this software in this distribution
29.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
29.37 - * single choice of license, a recipient has the option to distribute
29.38 - * your version of this file under either the CDDL, the GPL Version 2 or
29.39 - * to extend the choice of license to its licensees as provided above.
29.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
29.41 - * Version 2 license, then the option applies only if the new code is
29.42 - * made subject to such option by the copyright holder.
29.43 - */
29.44 -package org.openide.util.lookup;
29.45 -
29.46 -import org.openide.util.Lookup;
29.47 -import org.openide.util.LookupListener;
29.48 -
29.49 -import java.util.*;
29.50 -
29.51 -
29.52 -/**
29.53 - * Simple lookup implementation. It can be used to create temporary lookups
29.54 - * that do not change over time. The result stores references to all objects
29.55 - * passed in the constructor. Those objecst are the only ones returned as
29.56 - * result.
29.57 - * @author David Strupl
29.58 - */
29.59 -class SimpleLookup extends org.openide.util.Lookup {
29.60 - /** This variable is initialized in constructor and thus null
29.61 - * value is not allowed as its value. */
29.62 - private Collection<Item<?>> allItems;
29.63 -
29.64 - /**
29.65 - * Creates new Result object with supplied instances parameter.
29.66 - * @param instances to be used to return from the lookup
29.67 - */
29.68 - SimpleLookup(Collection<Object> instances) {
29.69 - allItems = new ArrayList<Item<?>>(instances.size());
29.70 -
29.71 - for (Iterator i = instances.iterator(); i.hasNext();) {
29.72 - allItems.add(new InstanceContent.SimpleItem<Object>(i.next()));
29.73 - }
29.74 - }
29.75 -
29.76 - <T,R> SimpleLookup(Collection<T> keys, InstanceContent.Convertor<? super T,R> conv) {
29.77 - allItems = new ArrayList<Item<?>>(keys.size());
29.78 -
29.79 - for (T item : keys) {
29.80 - allItems.add(new InstanceContent.ConvertingItem<T,R>(item, conv));
29.81 - }
29.82 - }
29.83 -
29.84 - public String toString() {
29.85 - return "SimpleLookup" + lookup(new Template<Object>(Object.class)).allInstances();
29.86 - }
29.87 -
29.88 - public <T> Result<T> lookup(Template<T> template) {
29.89 - if (template == null) {
29.90 - throw new NullPointerException();
29.91 - }
29.92 -
29.93 - return new SimpleResult<T>(template);
29.94 - }
29.95 -
29.96 - public <T> T lookup(Class<T> clazz) {
29.97 - for (Iterator i = allItems.iterator(); i.hasNext();) {
29.98 - Object o = i.next();
29.99 -
29.100 - if (o instanceof AbstractLookup.Pair) {
29.101 - AbstractLookup.Pair<?> p = (AbstractLookup.Pair<?>)o;
29.102 - if (p.instanceOf(clazz)) {
29.103 - Object ret = p.getInstance();
29.104 - if (clazz.isInstance(ret)) {
29.105 - return clazz.cast(ret);
29.106 - }
29.107 - }
29.108 - }
29.109 - }
29.110 - return null;
29.111 - }
29.112 -
29.113 - /** A method that defines matching between Item and Template.
29.114 - * @param item the item to match
29.115 - * @return true if item matches the template requirements, false if not
29.116 - */
29.117 - private static boolean matches(Template<?> t, AbstractLookup.Pair<?> item) {
29.118 - if (!AbstractLookup.matches(t, item, true)) {
29.119 - return false;
29.120 - }
29.121 -
29.122 - Class<?> type = t.getType();
29.123 -
29.124 - if ((type != null) && !type.isAssignableFrom(item.getType())) {
29.125 - return false;
29.126 - }
29.127 -
29.128 - return true;
29.129 - }
29.130 -
29.131 - /**
29.132 - * Result used in SimpleLookup. It holds a reference to the collection
29.133 - * passed in constructor. As the contents of this lookup result never
29.134 - * changes the addLookupListener and removeLookupListener are empty.
29.135 - */
29.136 - private class SimpleResult<T> extends Lookup.Result<T> {
29.137 - /** can be null and is initialized lazily */
29.138 - private Set<Class<? extends T>> classes;
29.139 -
29.140 - /** can be null and is initialized lazily */
29.141 - private Collection<? extends Item<T>> items;
29.142 -
29.143 - /** Template used for this result. It is never null.*/
29.144 - private Template<T> template;
29.145 -
29.146 - /** can be null and is initialized lazily */
29.147 - private Collection<T> results;
29.148 -
29.149 - /** Just remembers the supplied argument in variable template.*/
29.150 - SimpleResult(Template<T> template) {
29.151 - this.template = template;
29.152 - }
29.153 -
29.154 - /**
29.155 - * Intentionally does nothing because the lookup does not change
29.156 - * and no notification is needed.
29.157 - */
29.158 - public void addLookupListener(LookupListener l) {
29.159 - }
29.160 -
29.161 - /**
29.162 - * Intentionally does nothing because the lookup does not change
29.163 - * and no notification is needed.
29.164 - */
29.165 - public void removeLookupListener(LookupListener l) {
29.166 - }
29.167 -
29.168 - /**
29.169 - * Lazy initializes the results collection. Uses a call to allItems
29.170 - * to obtain the instances.
29.171 - */
29.172 - public java.util.Collection<? extends T> allInstances() {
29.173 - synchronized (this) {
29.174 - if (results != null) {
29.175 - return results;
29.176 - }
29.177 - }
29.178 -
29.179 -
29.180 - Collection<T> res = new ArrayList<T>(allItems.size());
29.181 -
29.182 - for (Item<T> item : allItems()) {
29.183 - res.add(item.getInstance());
29.184 - }
29.185 -
29.186 - synchronized (this) {
29.187 - results = Collections.unmodifiableCollection(res);
29.188 - }
29.189 -
29.190 - return results;
29.191 - }
29.192 -
29.193 - /**
29.194 - * Lazy initializes variable classes. Uses a call to allItems to
29.195 - * compute the result.
29.196 - */
29.197 - public Set<Class<? extends T>> allClasses() {
29.198 - synchronized (this) {
29.199 - if (classes != null) {
29.200 - return classes;
29.201 - }
29.202 - }
29.203 -
29.204 - Set<Class<? extends T>> res = new HashSet<Class<? extends T>>();
29.205 -
29.206 - for (Item<T> item : allItems()) {
29.207 - res.add(item.getType());
29.208 - }
29.209 -
29.210 - synchronized (this) {
29.211 - classes = Collections.unmodifiableSet(res);
29.212 - }
29.213 -
29.214 - return classes;
29.215 - }
29.216 -
29.217 - /**
29.218 - * Lazy initializes variable items. Creates an item for each
29.219 - * element in the instances collection. It puts either SimpleItem
29.220 - * or ConvertingItem to the collection.
29.221 - */
29.222 - public Collection<? extends Item<T>> allItems() {
29.223 - synchronized (this) {
29.224 - if (items != null) {
29.225 - return items;
29.226 - }
29.227 - }
29.228 -
29.229 - Collection<Item<T>> res = new ArrayList<Item<T>>(allItems.size());
29.230 -
29.231 - for (Iterator<Item<?>> i = allItems.iterator(); i.hasNext();) {
29.232 - Item<?> o = i.next();
29.233 -
29.234 - if (o instanceof AbstractLookup.Pair) {
29.235 - if (matches(template, (AbstractLookup.Pair) o)) {
29.236 - res.add(cast(o));
29.237 - }
29.238 - }
29.239 - }
29.240 -
29.241 - synchronized (this) {
29.242 - items = Collections.unmodifiableCollection(res);
29.243 - }
29.244 -
29.245 - return items;
29.246 - }
29.247 -
29.248 - @SuppressWarnings("unchecked")
29.249 - private Item<T> cast(Item<?> i) {
29.250 - return (Item<T>)i;
29.251 - }
29.252 - }
29.253 -}
30.1 --- a/lookup/src/main/java/org/openide/util/lookup/SimpleProxyLookup.java Wed Jan 27 17:46:23 2010 -0500
30.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
30.3 @@ -1,359 +0,0 @@
30.4 -/*
30.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
30.6 - *
30.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
30.8 - *
30.9 - * The contents of this file are subject to the terms of either the GNU
30.10 - * General Public License Version 2 only ("GPL") or the Common
30.11 - * Development and Distribution License("CDDL") (collectively, the
30.12 - * "License"). You may not use this file except in compliance with the
30.13 - * License. You can obtain a copy of the License at
30.14 - * http://www.netbeans.org/cddl-gplv2.html
30.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
30.16 - * specific language governing permissions and limitations under the
30.17 - * License. When distributing the software, include this License Header
30.18 - * Notice in each file and include the License file at
30.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
30.20 - * particular file as subject to the "Classpath" exception as provided
30.21 - * by Sun in the GPL Version 2 section of the License file that
30.22 - * accompanied this code. If applicable, add the following below the
30.23 - * License Header, with the fields enclosed by brackets [] replaced by
30.24 - * your own identifying information:
30.25 - * "Portions Copyrighted [year] [name of copyright owner]"
30.26 - *
30.27 - * Contributor(s):
30.28 - *
30.29 - * The Original Software is NetBeans. The Initial Developer of the Original
30.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
30.31 - * Microsystems, Inc. All Rights Reserved.
30.32 - *
30.33 - * If you wish your version of this file to be governed by only the CDDL
30.34 - * or only the GPL Version 2, indicate your decision by adding
30.35 - * "[Contributor] elects to include this software in this distribution
30.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
30.37 - * single choice of license, a recipient has the option to distribute
30.38 - * your version of this file under either the CDDL, the GPL Version 2 or
30.39 - * to extend the choice of license to its licensees as provided above.
30.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
30.41 - * Version 2 license, then the option applies only if the new code is
30.42 - * made subject to such option by the copyright holder.
30.43 - */
30.44 -package org.openide.util.lookup;
30.45 -
30.46 -import java.lang.ref.Reference;
30.47 -import java.lang.ref.WeakReference;
30.48 -import org.openide.util.Lookup;
30.49 -import org.openide.util.LookupEvent;
30.50 -import org.openide.util.LookupListener;
30.51 -
30.52 -import java.util.*;
30.53 -
30.54 -
30.55 -/**
30.56 - * Simple proxy lookup. Keeps reference to a lookup it delegates to and
30.57 - * forwards all requests.
30.58 - *
30.59 - * @author Jaroslav Tulach
30.60 - */
30.61 -final class SimpleProxyLookup extends org.openide.util.Lookup {
30.62 - /** the provider to check for the status */
30.63 - private Provider provider;
30.64 -
30.65 - /** the lookup we currently delegate to */
30.66 - private Lookup delegate;
30.67 -
30.68 - /** map of all templates to Reference (results) associated to this lookup */
30.69 - private WeakHashMap<Template<?>,Reference<ProxyResult<?>>> results;
30.70 -
30.71 - /**
30.72 - * @param provider provider to delegate to
30.73 - */
30.74 - SimpleProxyLookup(Provider provider) {
30.75 - this.provider = provider;
30.76 - }
30.77 -
30.78 - /** Checks whether we still delegate to the same lookup */
30.79 - private Lookup checkLookup() {
30.80 - Lookup l = provider.getLookup();
30.81 -
30.82 - // iterator over Reference (ProxyResult)
30.83 - Iterator<Reference<ProxyResult<?>>> toCheck = null;
30.84 -
30.85 - synchronized (this) {
30.86 - if (l != delegate) {
30.87 - this.delegate = l;
30.88 -
30.89 - if (results != null) {
30.90 - toCheck = new ArrayList<Reference<ProxyResult<?>>>(results.values()).iterator();
30.91 - }
30.92 - }
30.93 - }
30.94 -
30.95 - if (toCheck != null) {
30.96 - // update
30.97 - ArrayList<Object> evAndListeners = new ArrayList<Object>();
30.98 - for (Iterator<Reference<ProxyResult<?>>> it = toCheck; it.hasNext(); ) {
30.99 - java.lang.ref.Reference<ProxyResult<?>> ref = it.next();
30.100 - if (ref == null) {
30.101 - continue;
30.102 - }
30.103 -
30.104 - ProxyResult<?> p = ref.get();
30.105 -
30.106 - if (p != null && p.updateLookup(l)) {
30.107 - p.collectFires(evAndListeners);
30.108 - }
30.109 - }
30.110 -
30.111 - for (Iterator it = evAndListeners.iterator(); it.hasNext(); ) {
30.112 - LookupEvent ev = (LookupEvent)it.next();
30.113 - LookupListener ll = (LookupListener)it.next();
30.114 - ll.resultChanged(ev);
30.115 - }
30.116 - }
30.117 -
30.118 - return delegate;
30.119 - }
30.120 -
30.121 - @SuppressWarnings("unchecked")
30.122 - private static <T> ProxyResult<T> cast(ProxyResult<?> p) {
30.123 - return (ProxyResult<T>)p;
30.124 - }
30.125 -
30.126 - public <T> Result<T> lookup(Template<T> template) {
30.127 - synchronized (this) {
30.128 - if (results == null) {
30.129 - results = new WeakHashMap<Template<?>,Reference<ProxyResult<?>>>();
30.130 - } else {
30.131 - Reference<ProxyResult<?>> ref = results.get(template);
30.132 -
30.133 - if (ref != null) {
30.134 - ProxyResult<?> p = ref.get();
30.135 -
30.136 - if (p != null) {
30.137 - return cast(p);
30.138 - }
30.139 - }
30.140 - }
30.141 -
30.142 - ProxyResult<T> p = new ProxyResult<T>(template);
30.143 - Reference<ProxyResult<?>> ref = new WeakReference<ProxyResult<?>>(p);
30.144 - results.put(template, ref);
30.145 -
30.146 - return p;
30.147 - }
30.148 - }
30.149 -
30.150 - public <T> T lookup(Class<T> clazz) {
30.151 - if (clazz == null) {
30.152 - checkLookup();
30.153 - return null;
30.154 - }
30.155 - return checkLookup().lookup(clazz);
30.156 - }
30.157 -
30.158 - public <T> Item<T> lookupItem(Template<T> template) {
30.159 - return checkLookup().lookupItem(template);
30.160 - }
30.161 -
30.162 - /**
30.163 - * Result used in SimpleLookup. It holds a reference to the collection
30.164 - * passed in constructor. As the contents of this lookup result never
30.165 - * changes the addLookupListener and removeLookupListener are empty.
30.166 - */
30.167 - private final class ProxyResult<T> extends WaitableResult<T> implements LookupListener {
30.168 - /** Template used for this result. It is never null.*/
30.169 - private Template<T> template;
30.170 -
30.171 - /** result to delegate to */
30.172 - private Lookup.Result<T> delegate;
30.173 -
30.174 - /** listeners set */
30.175 - private javax.swing.event.EventListenerList listeners;
30.176 - private LookupListener lastListener;
30.177 -
30.178 - /** Just remembers the supplied argument in variable template.*/
30.179 - ProxyResult(Template<T> template) {
30.180 - this.template = template;
30.181 - }
30.182 -
30.183 - /** Checks state of the result
30.184 - */
30.185 - private Result<T> checkResult() {
30.186 - updateLookup(checkLookup());
30.187 -
30.188 - return this.delegate;
30.189 - }
30.190 -
30.191 - /** Updates the state of the lookup.
30.192 - * @return true if the lookup really changed
30.193 - */
30.194 - public boolean updateLookup(Lookup l) {
30.195 - Collection<? extends Item<T>> oldPairs = (delegate != null) ? delegate.allItems() : null;
30.196 -
30.197 - LookupListener removedListener;
30.198 -
30.199 - synchronized (this) {
30.200 - if ((delegate != null) && (lastListener != null)) {
30.201 - removedListener = lastListener;
30.202 - delegate.removeLookupListener(lastListener);
30.203 - } else {
30.204 - removedListener = null;
30.205 - }
30.206 - }
30.207 -
30.208 - // cannot call to foreign code
30.209 - Lookup.Result<T> res = l.lookup(template);
30.210 -
30.211 - synchronized (this) {
30.212 - if (removedListener == lastListener) {
30.213 - delegate = res;
30.214 - lastListener = new WeakResult<T>(this, delegate);
30.215 - delegate.addLookupListener(lastListener);
30.216 - }
30.217 - }
30.218 -
30.219 - if (oldPairs == null) {
30.220 - // nobody knows about a change
30.221 - return false;
30.222 - }
30.223 -
30.224 - Collection<? extends Item<T>> newPairs = delegate.allItems();
30.225 -
30.226 - // See #34961 for explanation.
30.227 - if (!(oldPairs instanceof List)) {
30.228 - if (oldPairs == Collections.EMPTY_SET) {
30.229 - // avoid allocation
30.230 - oldPairs = Collections.emptyList();
30.231 - } else {
30.232 - oldPairs = new ArrayList<Item<T>>(oldPairs);
30.233 - }
30.234 - }
30.235 -
30.236 - if (!(newPairs instanceof List)) {
30.237 - newPairs = new ArrayList<Item<T>>(newPairs);
30.238 - }
30.239 -
30.240 - return !oldPairs.equals(newPairs);
30.241 - }
30.242 -
30.243 - public synchronized void addLookupListener(LookupListener l) {
30.244 - if (listeners == null) {
30.245 - listeners = new javax.swing.event.EventListenerList();
30.246 - }
30.247 -
30.248 - listeners.add(LookupListener.class, l);
30.249 - }
30.250 -
30.251 - public synchronized void removeLookupListener(LookupListener l) {
30.252 - if (listeners != null) {
30.253 - listeners.remove(LookupListener.class, l);
30.254 - }
30.255 - }
30.256 -
30.257 - public java.util.Collection<? extends T> allInstances() {
30.258 - return checkResult().allInstances();
30.259 - }
30.260 -
30.261 - public Set<Class<? extends T>> allClasses() {
30.262 - return checkResult().allClasses();
30.263 - }
30.264 -
30.265 - public Collection<? extends Item<T>> allItems() {
30.266 - return checkResult().allItems();
30.267 - }
30.268 -
30.269 - protected void beforeLookup(Lookup.Template t) {
30.270 - Lookup.Result r = checkResult();
30.271 -
30.272 - if (r instanceof WaitableResult) {
30.273 - ((WaitableResult) r).beforeLookup(t);
30.274 - }
30.275 - }
30.276 -
30.277 - /** A change in lookup occured.
30.278 - * @param ev event describing the change
30.279 - *
30.280 - */
30.281 - public void resultChanged(LookupEvent anEvent) {
30.282 - collectFires(null);
30.283 - }
30.284 -
30.285 - protected void collectFires(Collection<Object> evAndListeners) {
30.286 - javax.swing.event.EventListenerList l = this.listeners;
30.287 -
30.288 - if (l == null) {
30.289 - return;
30.290 - }
30.291 -
30.292 - Object[] listeners = l.getListenerList();
30.293 -
30.294 - if (listeners.length == 0) {
30.295 - return;
30.296 - }
30.297 -
30.298 - LookupEvent ev = new LookupEvent(this);
30.299 - AbstractLookup.notifyListeners(listeners, ev, evAndListeners);
30.300 - }
30.301 - }
30.302 - // end of ProxyResult
30.303 - private final class WeakResult<T> extends WaitableResult<T> implements LookupListener {
30.304 - private Lookup.Result source;
30.305 - private Reference<ProxyResult<T>> result;
30.306 -
30.307 - public WeakResult(ProxyResult<T> r, Lookup.Result<T> s) {
30.308 - this.result = new WeakReference<ProxyResult<T>>(r);
30.309 - this.source = s;
30.310 - }
30.311 -
30.312 - protected void beforeLookup(Lookup.Template t) {
30.313 - ProxyResult r = (ProxyResult)result.get();
30.314 - if (r != null) {
30.315 - r.beforeLookup(t);
30.316 - } else {
30.317 - source.removeLookupListener(this);
30.318 - }
30.319 - }
30.320 -
30.321 - protected void collectFires(Collection<Object> evAndListeners) {
30.322 - ProxyResult<T> r = result.get();
30.323 - if (r != null) {
30.324 - r.collectFires(evAndListeners);
30.325 - } else {
30.326 - source.removeLookupListener(this);
30.327 - }
30.328 - }
30.329 -
30.330 - public void addLookupListener(LookupListener l) {
30.331 - assert false;
30.332 - }
30.333 -
30.334 - public void removeLookupListener(LookupListener l) {
30.335 - assert false;
30.336 - }
30.337 -
30.338 - public Collection<T> allInstances() {
30.339 - assert false;
30.340 - return null;
30.341 - }
30.342 -
30.343 - public void resultChanged(LookupEvent ev) {
30.344 - ProxyResult r = (ProxyResult)result.get();
30.345 - if (r != null) {
30.346 - r.resultChanged(ev);
30.347 - } else {
30.348 - source.removeLookupListener(this);
30.349 - }
30.350 - }
30.351 -
30.352 - public Collection<? extends Item<T>> allItems() {
30.353 - assert false;
30.354 - return null;
30.355 - }
30.356 -
30.357 - public Set<Class<? extends T>> allClasses() {
30.358 - assert false;
30.359 - return null;
30.360 - }
30.361 - } // end of WeakResult
30.362 -}
31.1 --- a/lookup/src/main/java/org/openide/util/lookup/SingletonLookup.java Wed Jan 27 17:46:23 2010 -0500
31.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
31.3 @@ -1,173 +0,0 @@
31.4 -/*
31.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
31.6 - *
31.7 - * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
31.8 - *
31.9 - * The contents of this file are subject to the terms of either the GNU
31.10 - * General Public License Version 2 only ("GPL") or the Common
31.11 - * Development and Distribution License("CDDL") (collectively, the
31.12 - * "License"). You may not use this file except in compliance with the
31.13 - * License. You can obtain a copy of the License at
31.14 - * http://www.netbeans.org/cddl-gplv2.html
31.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
31.16 - * specific language governing permissions and limitations under the
31.17 - * License. When distributing the software, include this License Header
31.18 - * Notice in each file and include the License file at
31.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
31.20 - * particular file as subject to the "Classpath" exception as provided
31.21 - * by Sun in the GPL Version 2 section of the License file that
31.22 - * accompanied this code. If applicable, add the following below the
31.23 - * License Header, with the fields enclosed by brackets [] replaced by
31.24 - * your own identifying information:
31.25 - * "Portions Copyrighted [year] [name of copyright owner]"
31.26 - *
31.27 - * If you wish your version of this file to be governed by only the CDDL
31.28 - * or only the GPL Version 2, indicate your decision by adding
31.29 - * "[Contributor] elects to include this software in this distribution
31.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
31.31 - * single choice of license, a recipient has the option to distribute
31.32 - * your version of this file under either the CDDL, the GPL Version 2 or
31.33 - * to extend the choice of license to its licensees as provided above.
31.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
31.35 - * Version 2 license, then the option applies only if the new code is
31.36 - * made subject to such option by the copyright holder.
31.37 - *
31.38 - * Contributor(s):
31.39 - *
31.40 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
31.41 - */
31.42 -
31.43 -package org.openide.util.lookup;
31.44 -
31.45 -import java.util.Collection;
31.46 -import java.util.Collections;
31.47 -import java.util.Set;
31.48 -import org.openide.util.Lookup;
31.49 -import org.openide.util.LookupListener;
31.50 -
31.51 -/**
31.52 - * Unmodifiable lookup that contains just one fixed object.
31.53 - *
31.54 - * @author Marian Petras
31.55 - */
31.56 -class SingletonLookup extends Lookup {
31.57 -
31.58 - private final Object objectToLookup;
31.59 - private final String id;
31.60 -
31.61 - SingletonLookup(Object objectToLookup) {
31.62 - this(objectToLookup, null);
31.63 - }
31.64 -
31.65 - SingletonLookup(Object objectToLookup, String id) {
31.66 - if (objectToLookup == null) {
31.67 - throw new IllegalArgumentException("null"); //NOI18N
31.68 - }
31.69 -
31.70 - this.objectToLookup = objectToLookup;
31.71 - this.id = id;
31.72 - }
31.73 -
31.74 - @Override
31.75 - public <T> T lookup(Class<T> clazz) {
31.76 - if (clazz == null) {
31.77 - throw new IllegalArgumentException("null"); //NOI18N
31.78 - }
31.79 -
31.80 - return (clazz.isInstance(objectToLookup))
31.81 - ? clazz.cast(objectToLookup)
31.82 - : null;
31.83 - }
31.84 -
31.85 - @Override
31.86 - public <T> Result<T> lookup(Template<T> template) {
31.87 - if (template == null) {
31.88 - throw new IllegalArgumentException("null"); //NOI18N
31.89 - }
31.90 -
31.91 - Lookup.Item<T> item = lookupItem(template);
31.92 - if (item != null) {
31.93 - return new SingletonResult<T>(item);
31.94 - } else {
31.95 - return Lookup.EMPTY.lookup(template);
31.96 - }
31.97 - }
31.98 -
31.99 - @Override
31.100 - public <T> Collection<? extends T> lookupAll(Class<T> clazz) {
31.101 - if (clazz == null) {
31.102 - throw new IllegalArgumentException("null"); //NOI18N
31.103 - }
31.104 -
31.105 - return (clazz.isInstance(objectToLookup))
31.106 - ? Collections.singletonList(clazz.cast(objectToLookup))
31.107 - : Collections.<T>emptyList();
31.108 - }
31.109 -
31.110 - @Override
31.111 - @SuppressWarnings("unchecked")
31.112 - public <T> Item<T> lookupItem(Template<T> template) {
31.113 - if (template == null) {
31.114 - throw new IllegalArgumentException("null"); //NOI18N
31.115 - }
31.116 -
31.117 - String templateId = template.getId();
31.118 - if ((templateId != null) && !templateId.equals(id)) {
31.119 - return null;
31.120 - }
31.121 -
31.122 - Object templateInst = template.getInstance();
31.123 - if ((templateInst != null) && (objectToLookup != templateInst)) {
31.124 - return null;
31.125 - }
31.126 -
31.127 - Class<T> clazz = template.getType();
31.128 - if ((clazz != null) && !clazz.isInstance(objectToLookup)) {
31.129 - return null;
31.130 - }
31.131 -
31.132 - Lookup.Item<T> item;
31.133 - if (clazz != null) {
31.134 - item = Lookups.lookupItem(clazz.cast(objectToLookup), id);
31.135 - } else {
31.136 - item = Lookups.lookupItem((T) objectToLookup, id);
31.137 - }
31.138 - return item;
31.139 - }
31.140 -
31.141 - static class SingletonResult<T> extends Lookup.Result<T> {
31.142 -
31.143 - private final Lookup.Item<T> item;
31.144 -
31.145 - SingletonResult(Lookup.Item<T> item) {
31.146 - this.item = item;
31.147 - }
31.148 -
31.149 - @Override
31.150 - public void addLookupListener(LookupListener l) {
31.151 - // this result never changes - no need to register a listener
31.152 - }
31.153 -
31.154 - @Override
31.155 - public void removeLookupListener(LookupListener l) {
31.156 - // this result never changes - no need to register a listener
31.157 - }
31.158 -
31.159 - @Override
31.160 - public Set<Class<? extends T>> allClasses() {
31.161 - return Collections.<Class<? extends T>>singleton(item.getType());
31.162 - }
31.163 -
31.164 - @Override
31.165 - public Collection<? extends Item<T>> allItems() {
31.166 - return Collections.singletonList(item);
31.167 - }
31.168 -
31.169 - @Override
31.170 - public Collection<? extends T> allInstances() {
31.171 - return Collections.singletonList(item.getInstance());
31.172 - }
31.173 -
31.174 - }
31.175 -
31.176 -}
32.1 --- a/lookup/src/main/java/org/openide/util/lookup/WaitableResult.java Wed Jan 27 17:46:23 2010 -0500
32.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
32.3 @@ -1,62 +0,0 @@
32.4 -/*
32.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
32.6 - *
32.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
32.8 - *
32.9 - * The contents of this file are subject to the terms of either the GNU
32.10 - * General Public License Version 2 only ("GPL") or the Common
32.11 - * Development and Distribution License("CDDL") (collectively, the
32.12 - * "License"). You may not use this file except in compliance with the
32.13 - * License. You can obtain a copy of the License at
32.14 - * http://www.netbeans.org/cddl-gplv2.html
32.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
32.16 - * specific language governing permissions and limitations under the
32.17 - * License. When distributing the software, include this License Header
32.18 - * Notice in each file and include the License file at
32.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
32.20 - * particular file as subject to the "Classpath" exception as provided
32.21 - * by Sun in the GPL Version 2 section of the License file that
32.22 - * accompanied this code. If applicable, add the following below the
32.23 - * License Header, with the fields enclosed by brackets [] replaced by
32.24 - * your own identifying information:
32.25 - * "Portions Copyrighted [year] [name of copyright owner]"
32.26 - *
32.27 - * Contributor(s):
32.28 - *
32.29 - * The Original Software is NetBeans. The Initial Developer of the Original
32.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
32.31 - * Microsystems, Inc. All Rights Reserved.
32.32 - *
32.33 - * If you wish your version of this file to be governed by only the CDDL
32.34 - * or only the GPL Version 2, indicate your decision by adding
32.35 - * "[Contributor] elects to include this software in this distribution
32.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
32.37 - * single choice of license, a recipient has the option to distribute
32.38 - * your version of this file under either the CDDL, the GPL Version 2 or
32.39 - * to extend the choice of license to its licensees as provided above.
32.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
32.41 - * Version 2 license, then the option applies only if the new code is
32.42 - * made subject to such option by the copyright holder.
32.43 - */
32.44 -package org.openide.util.lookup;
32.45 -
32.46 -import java.util.Collection;
32.47 -import org.openide.util.Lookup;
32.48 -
32.49 -
32.50 -/** A special subclass of lookup that is able to wait before queries.
32.51 - *
32.52 - * @author Jaroslav Tulach
32.53 - */
32.54 -abstract class WaitableResult<T> extends Lookup.Result<T> {
32.55 - /** Used by proxy results to synchronize before lookup.
32.56 - */
32.57 - protected abstract void beforeLookup(Lookup.Template t);
32.58 -
32.59 - /** Needed to group notification of outside the package listeners
32.60 - * after all AbstractLookup and ProxyLookups have been updated.
32.61 - * @param evAndListeners LookupEvent, LookupListener, LookupEvent, LookupListener, etc.
32.62 - */
32.63 - protected abstract void collectFires(Collection<Object> evAndListeners);
32.64 -
32.65 -}
33.1 --- a/lookup/src/main/java/org/openide/util/lookup/doc-files/index.html Wed Jan 27 17:46:23 2010 -0500
33.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
33.3 @@ -1,208 +0,0 @@
33.4 -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
33.5 -<!--
33.6 - - DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
33.7 - -
33.8 - - Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
33.9 - -
33.10 - - The contents of this file are subject to the terms of either the GNU
33.11 - - General Public License Version 2 only ("GPL") or the Common
33.12 - - Development and Distribution License("CDDL") (collectively, the
33.13 - - "License"). You may not use this file except in compliance with the
33.14 - - License. You can obtain a copy of the License at
33.15 - - http://www.netbeans.org/cddl-gplv2.html
33.16 - - or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
33.17 - - specific language governing permissions and limitations under the
33.18 - - License. When distributing the software, include this License Header
33.19 - - Notice in each file and include the License file at
33.20 - - nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
33.21 - - particular file as subject to the "Classpath" exception as provided
33.22 - - by Sun in the GPL Version 2 section of the License file that
33.23 - - accompanied this code. If applicable, add the following below the
33.24 - - License Header, with the fields enclosed by brackets [] replaced by
33.25 - - your own identifying information:
33.26 - - "Portions Copyrighted [year] [name of copyright owner]"
33.27 - -
33.28 - - Contributor(s):
33.29 - -
33.30 - - The Original Software is NetBeans. The Initial Developer of the Original
33.31 - - Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
33.32 - - Microsystems, Inc. All Rights Reserved.
33.33 - -
33.34 - - If you wish your version of this file to be governed by only the CDDL
33.35 - - or only the GPL Version 2, indicate your decision by adding
33.36 - - "[Contributor] elects to include this software in this distribution
33.37 - - under the [CDDL or GPL Version 2] license." If you do not indicate a
33.38 - - single choice of license, a recipient has the option to distribute
33.39 - - your version of this file under either the CDDL, the GPL Version 2 or
33.40 - - to extend the choice of license to its licensees as provided above.
33.41 - - However, if you add GPL Version 2 code and therefore, elected the GPL
33.42 - - Version 2 license, then the option applies only if the new code is
33.43 - - made subject to such option by the copyright holder.
33.44 - -->
33.45 -<HTML>
33.46 -<HEAD>
33.47 -<TITLE>Lookup Library</TITLE>
33.48 -<link rel="Stylesheet" href="@TOP@/prose.css" type="text/css" title="NetBeans Open APIs Style">
33.49 -</HEAD>
33.50 -<BODY>
33.51 -
33.52 -<P>
33.53 -
33.54 -This is the home page of the <em>lookup library</em> implementation, which
33.55 -is intended to solve a general problem that every <cite>component-based system</CITE>
33.56 -has had to face: how different components <b>register</b> to the system
33.57 -and how other parts of the system can <b>look</b> them <b>up</B>.
33.58 -<P>
33.59 -There already are libraries trying to solve this problem, usually by querying for
33.60 -an interface and finding its appropriate implementaion. The most famous is
33.61 -<A href="http://www.jini.org/">Jini</A>, the platform for development of
33.62 -distributed network services. Our library does something similar, but tries
33.63 -to stay small and easy
33.64 -to use. The NetBeans <em>Lookup
33.65 -Library</EM>'s main focus is a modular application consisting of independent modules
33.66 -that want to communicate with each other. It does not try to solve networking or
33.67 -legacy application integration. It is simple but powerful.
33.68 -
33.69 -<H2>Why would you want to use it?</H2>
33.70 -
33.71 -A well-written modular program separates <em>development</EM>
33.72 -and <em>deployment</EM>.
33.73 -There are many situations where a component needs some functionality but
33.74 -does not actually care about the implementation. It is up to the <em>system
33.75 -adminstrator</em> that deploys (installs) the application to decide which
33.76 -implementation to use.
33.77 -<P>
33.78 -The most simple and most often used method for allowing other implementations
33.79 -to be plugged in is the <em>system property</em> pattern:
33.80 -
33.81 -<pre>
33.82 - <font class="keyword">public</font> <font class="type">Toolkit</font> <font class="function-name">getDefaultToolkit</font> () {
33.83 - java.awt.<font class="type">Toolkit</font> <font class="variable-name">t</font> = <font class="constant">null</font>;
33.84 - <font class="type">String</font> <font class="variable-name">classname</font> = System.getProperty (<font class="string">"java.awt.Toolkit"</font>);
33.85 - <font class="keyword">if</font> (classname != <font class="constant">null</font>) {
33.86 - <font class="keyword">try</font> {
33.87 - <font class="type">Class</font> <font class="variable-name">c</font> = Class.forName (classname);
33.88 - t = (java.awt.<font class="type">Toolkit</font>)c.newInstance ();
33.89 - } <font class="keyword">catch</font> (<font class="type">Exception</font> <font class="variable-name">ex</font>) {
33.90 - System.out.println (<font class="string">"Cannot initialize toolkit: "</font> + classname);
33.91 - ex.printStackTrace ();
33.92 - }
33.93 - }
33.94 - <font class="comment">// fallback </font>
33.95 - <font class="keyword">if</font> (t == <font class="constant">null</font>) {
33.96 - t = <font class="keyword">new</font> <font class="type">GenericAWTToolkit</font> ();
33.97 - }
33.98 - }
33.99 -</pre>
33.100 -
33.101 -
33.102 -The idea is simple. The <em>deployer</em> can start the Java VM with the flag
33.103 -<code>-Djava.awt.Toolkit=org.myorg.MyToolkit</code> where the <code>MyToolkit</code>
33.104 -is his class with default constructor and the code in the <code>getDefaultToolkit</CODE>
33.105 -method will instantiate the class and use it.
33.106 -<P>
33.107 -In principle this is general enough of a solution and works well, except that writing the
33.108 -code above is error prone and it also requires passing the arguments to the virtual machine.
33.109 -It would be much nicer if the registation could be done just by putting a JAR file with the <code>MyToolkit</code> class
33.110 -into the application classpath.
33.111 -<P>
33.112 -Actually this has been realized also by the JDK development team and addressed in
33.113 -JDK 1.3 as part of the <a href="http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#Provider%20Configuration%20File">provider extension mechanism</A>.
33.114 -The <code>MyToolkit</code> could be registered by adding a file
33.115 -<code>/META-INF/services/java.awt.Toolkit</code> with one line
33.116 -<code>org.myorg.MyToolkit</code> into the JAR file that contains the
33.117 -<code>MyToolkit</CODE> implementation. The code in <code>getDefaultToolkit</CODE>
33.118 -will scan all JAR files in classpath and search for that file,
33.119 -create an instance of <code>MyToolkit</code> and use it.
33.120 -The deployer can influence which toolkit will be created by
33.121 -adding the right JAR files into the classpath.
33.122 -<P>
33.123 -Of course the code to access the <code>META-INF/services/</code> files is even
33.124 -more error prone than the <em>property pattern</EM>. And this is exactly the
33.125 -place where the <em>lookup library</em> can help. It provides an implementation of
33.126 -the search algorithm with an easy interface. Just write:
33.127 -<pre>
33.128 - <font class="keyword">import</font> <font class="type">java.awt.Toolkit</font>;
33.129 - <font class="keyword">import</font> <font class="type">org.openide.util.Lookup;</font>;
33.130 - <font class="type">Toolkit</font> <font class="variable-name">t</font> = (<font class="type">Toolkit</font>)Lookup.getDefault().<a href="@TOP@org/openide/util/Lookup.html#lookup(java.lang.Class)">lookup</a>(Toolkit.<font class="keyword">class</font>);
33.131 -</PRE>
33.132 -and if the JAR with <code>MyToolkit</CODE> is in the class path, the simple call
33.133 -above will do the rest.
33.134 -<P>
33.135 -So whenever one writes an application divided into several independent modules (jar files)
33.136 -that are being developed and deployed independently, there is a need for registering
33.137 -and discovering components. First of all, a set of interfaces can be defined to enable
33.138 -inter-module communication (like the abstract class <code>java.awt.Toolkit</CODE>).
33.139 -After that a set of modules providing implementation can written (<code>MyToolkit</code> and other concurent implementations)
33.140 -and after that, whenever a module trying to utilitize the functionality wants to access
33.141 -the <code>Toolkit</code> via lookup, the real implementation is returned.
33.142 -<P>
33.143 -It is the responsibility of lookup to find a suitable implementation of the
33.144 -requested service and return an object implementing the service. This is the
33.145 -the basic functionality and while the library provides you with a little bit
33.146 -more, even this simple usage might be extremaly useful: the client code knows
33.147 -nothing about the implementation and the implementation can be switched in
33.148 -deployment time by simply replacing one implementation jar with other. There
33.149 -is no code change required.
33.150 -
33.151 -<H2> Local lookup usage </H2>
33.152 -The example in previous paragraph demostrated the usage of lookup as a global
33.153 -registry (by using the <CODE>Lookup.getDefault()</CODE> call). One can also
33.154 -consider another scenario where the lookup can help.
33.155 -<P>
33.156 -Let's switch hats to be an API designer for a while. The goal is to introduce a
33.157 -new object into the system. But you either are not sure yet what all the roles
33.158 -of the new object will be or you (more importantly) want to be able to add (or
33.159 -change) roles of the object dynamically. So why not to introduce following
33.160 -method to the object's interface:
33.161 -<pre>
33.162 -<font class="keyword">public class </FONT> <font class="type">MorphingObject</FONT> {
33.163 - <font class="keyword">public</FONT> <font class="type"><a href="@TOP@org/openide/util/Lookup.html">Lookup</A></FONT> getLookup() {
33.164 - <font class="keyword">return</FONT> <font class="variable-name">myLookup;</FONT>
33.165 - }
33.166 - ...
33.167 -}
33.168 -</pre>
33.169 -By exposing the method getLookup you can attach different functionality to the
33.170 -MorphingObject at runtime and whoever gets a reference to your object can ask it
33.171 -whether the object supports a given interface like this:
33.172 -<pre>
33.173 -<font class="type">MorphingObject</FONT> <font class="variable-name">morph</FONT> = ...
33.174 -<font class="type">AnInterface</font> <font class="variable-name">impl</font> = (<font
33.175 -class="type">AnInterface</font>)morph.getLookup().<a
33.176 -href="@TOP@org/openide/util/Lookup.html#lookup(java.lang.Class)">lookup</a>(AnInterface.<font class="keyword">class</font>);
33.177 -<font class="keyword">if</font> (impl == <font class="constant">null</font>) {
33.178 - <font class="keyword">return;</font><font class="comment">/* AnInterface not supported now! */</font>
33.179 -}
33.180 -impl.useIt();
33.181 -</PRE>
33.182 -
33.183 -<H2>Additional functionality</H2>
33.184 -The NetBeans lookup library also provides:
33.185 -<UL>
33.186 -<LI>Support for dynamically changing the lookup content.</LI>
33.187 -<LI>The ability to return multiple results.</LI>
33.188 -<LI>Notification of changes. After retrieving the result, the client can attach a
33.189 -listener and be notified when the result of the lookup is changed.</LI>
33.190 -<LI>Lazy initialization of the implementation. The implementation objects are
33.191 -initialized only after someone asks for them. Even the implementation classes
33.192 -are not loaded if they are not going to be used! </LI>
33.193 -</UL>
33.194 -
33.195 -<H2>Further information</H2>
33.196 -<UL>
33.197 - <LI><A HREF="lookup-api.html">Lookup Library APIs</A> for those writing the client code.
33.198 -Specifying the query, getting the result and listenning on changes.</LI>
33.199 - <LI><A HREF="lookup-spi.html">Lookup Library SPIs</A> for those writing the
33.200 -implementaion code and registering it with lookup. Includes also writing own
33.201 -lookup implementation.</LI>
33.202 - <LI>Download <A HREF="http://www.netbeans.org/">NetBeans platform</A> which
33.203 -contains <code>org-openide-util.jar</code></LI>
33.204 - <A HREF="http://hg.netbeans.org/main-golden/file/tip/openide.util/src/org/openide/util/lookup/">
33.205 - implementation package (org.openide.util.lookup) </A>
33.206 - + classes Lookup, LookupEvent, LookupListener in
33.207 - <A href="http://hg.netbeans.org/main-golden/file/tip/openide.util/src/org/openide/util/">util package</A></LI>
33.208 - <li><a href="http://www.martinfowler.com/articles/injection.html">Inversion of Control Containers and the Dependency Injection pattern</a> (Martin Fowler)</li>
33.209 -</UL>
33.210 -</BODY>
33.211 -</HTML>
34.1 --- a/lookup/src/main/java/org/openide/util/lookup/doc-files/lookup-api.html Wed Jan 27 17:46:23 2010 -0500
34.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
34.3 @@ -1,188 +0,0 @@
34.4 -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
34.5 -<!--
34.6 - - DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
34.7 - -
34.8 - - Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
34.9 - -
34.10 - - The contents of this file are subject to the terms of either the GNU
34.11 - - General Public License Version 2 only ("GPL") or the Common
34.12 - - Development and Distribution License("CDDL") (collectively, the
34.13 - - "License"). You may not use this file except in compliance with the
34.14 - - License. You can obtain a copy of the License at
34.15 - - http://www.netbeans.org/cddl-gplv2.html
34.16 - - or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
34.17 - - specific language governing permissions and limitations under the
34.18 - - License. When distributing the software, include this License Header
34.19 - - Notice in each file and include the License file at
34.20 - - nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
34.21 - - particular file as subject to the "Classpath" exception as provided
34.22 - - by Sun in the GPL Version 2 section of the License file that
34.23 - - accompanied this code. If applicable, add the following below the
34.24 - - License Header, with the fields enclosed by brackets [] replaced by
34.25 - - your own identifying information:
34.26 - - "Portions Copyrighted [year] [name of copyright owner]"
34.27 - -
34.28 - - Contributor(s):
34.29 - -
34.30 - - The Original Software is NetBeans. The Initial Developer of the Original
34.31 - - Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
34.32 - - Microsystems, Inc. All Rights Reserved.
34.33 - -
34.34 - - If you wish your version of this file to be governed by only the CDDL
34.35 - - or only the GPL Version 2, indicate your decision by adding
34.36 - - "[Contributor] elects to include this software in this distribution
34.37 - - under the [CDDL or GPL Version 2] license." If you do not indicate a
34.38 - - single choice of license, a recipient has the option to distribute
34.39 - - your version of this file under either the CDDL, the GPL Version 2 or
34.40 - - to extend the choice of license to its licensees as provided above.
34.41 - - However, if you add GPL Version 2 code and therefore, elected the GPL
34.42 - - Version 2 license, then the option applies only if the new code is
34.43 - - made subject to such option by the copyright holder.
34.44 - -->
34.45 -<HTML>
34.46 -<HEAD>
34.47 -<TITLE>Lookup Library API</TITLE>
34.48 -<link rel="Stylesheet" href="@TOP@/prose.css" type="text/css" title="NetBeans Open APIs Style">
34.49 -</HEAD>
34.50 -<BODY>
34.51 -<H1>Lookup library API</H1>
34.52 -<p>
34.53 -This document describes usage of the API provided by the Lookup Library. In this
34.54 -document we assume that someone has already provided us with a lookup
34.55 -implementation (for those seeking how to write a lookup implementation please
34.56 -check <A href="lookup-spi.html">the SPI document</A>).
34.57 -
34.58 -<H2> Getting the lookup </H2>
34.59 -
34.60 -The first question you might ask is this: how can I get hold of a
34.61 -lookup instance? There are basically two ways how you can get it.
34.62 -
34.63 -<H3> Global lookup </H3>
34.64 -As you can see in the
34.65 -
34.66 -<a href="@TOP@org/openide/util/Lookup.html">Lookup</a>
34.67 -
34.68 -Javadoc there is a static method
34.69 -
34.70 -<pre><a href="@TOP@org/openide/util/Lookup.html#getDefault()">public static Lookup getDefault()</a></pre>
34.71 -
34.72 -The object returned from this method is
34.73 -a global lookup that can serve as a central place for registering services.
34.74 -The default implementation is a lookup that implements
34.75 -<a href="http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.html#Service%20Provider">
34.76 -the JDK JAR services</A>
34.77 -mechanism and delegates to <samp>META-INF/services/name.of.Class</samp> files.
34.78 -<P>
34.79 -If you want to add your class to this lookup just create a file in your
34.80 -jar file under the <code>META-INF</code> directory (e.g. <samp>META-INF/services/com.my.APIClass</samp>)
34.81 -and let the file contain only one line of text
34.82 -
34.83 -<pre>com.foo.impl.ImplOfTheAPI</pre>
34.84 -
34.85 -<p>(This is more easily done using the <code>@ServiceProvider</code> annotation.)</p>
34.86 -
34.87 -The following code will return you a newly created instance of
34.88 -<code>com.foo.impl.ImplOfTheAPI</code>:
34.89 -
34.90 -<PRE>
34.91 - <font class="keyword">import</FONT> org.openide.util.Lookup;
34.92 - return Lookup.getDefault().lookup(com.my.APIClass.class);
34.93 -</PRE>
34.94 -
34.95 -<H3> Local lookup </H3>
34.96 -
34.97 -This is just a reminder that whenever you find a method called getLookup
34.98 -or similar returning a lookup instance, the provided lookup is <EM>not</EM> the
34.99 -general lookup described in the previous paragraph. Rather, it is a private lookup
34.100 -implementation that is usually bound to the object you invoked the method on.
34.101 -
34.102 -<H2> Use of Lookup.Template and Lookup.Result </H2>
34.103 -
34.104 -There are more ways how you can ask lookup besides the variant with one class
34.105 -parameter. If you want more functionality, you have to implement the interface
34.106 -Lookup.Template and pass an instance of such object to the lookup call.
34.107 -<p>
34.108 -<EM>Note:</EM> If you use Lookup.Template, the object returned from the lookup is
34.109 -<EM>not</EM> the object you are looking for but rather a result object
34.110 -(Lookup.Result). You can call methods on such a result object to get the actual
34.111 -results.
34.112 -<p>
34.113 -Let's examine following example:
34.114 -
34.115 -<pre>
34.116 - <font class="keyword">import</FONT> org.openide.util.Lookup;
34.117 -
34.118 - <font class="type">Lookup</font> <font class="variable-name">lookup</font> = ...;
34.119 - Lookup.<font class="type">Template</font> <font class="variable-name">template</font> = <font class="keyword">new</font> Lookup.<font class="type">Template</font>(MyService.<font class="keyword">class</font>);
34.120 - Lookup.<font class="type">Result</font> <font class="variable-name">result</font> = lookup.lookup(template);
34.121 - <font class="type">Collection</font> <font class="variable-name">c</font> = result.allInstances();
34.122 - <font class="keyword">for</font> (<font class="type">Iterator</font> <font class="variable-name">i</font> = c.iterator(); i.hasNext(); ) {
34.123 - <font class="type">MyService</font> <font class="variable-name">s</font> = (<font class="type">MyService</font>)i.next();
34.124 - s.callMyService();
34.125 - }
34.126 -</pre>
34.127 -
34.128 -In this example the call to method lookup(...) returns immediately because the
34.129 -result object can be constructed even without real results. The first time you
34.130 -ask for the result object by calling r.allInstances(), the lookup has to supply you
34.131 -the real results and this method can block until the required data are really
34.132 -available.
34.133 -<p>
34.134 -If you are not interested in all objects as in the previous example, you can use the
34.135 -template to ask for one resulting object (wrapped in special Item instance):
34.136 -<pre>
34.137 - <font class="keyword">import</FONT> org.openide.util.Lookup;
34.138 -
34.139 - <font class="type">Lookup</font> <font class="variable-name">lookup</font> = ...;
34.140 - Lookup.<font class="type">Template</font> <font class="variable-name">template</font> = <font class="keyword">new</font> Lookup.<font class="type">Template</font>(MyService.<font class="keyword">class</font>);
34.141 - Lookup.<font class="type">Item</font> <font class="variable-name">item</font> = lookup.lookupItem(template);
34.142 - <font class="type">MyService</font> <font class="variable-name">s</font> = (<font class="type">MyService</font>)item.getInstance();
34.143 - s.callMyService();
34.144 -</pre>
34.145 -
34.146 -Again, the Item object can construct the real instance only if you call
34.147 -getInstance. The item can be useful even without calling getInstance - you can get
34.148 -its display name or an unique id. You can use this information, for example, for
34.149 -constructing menu items without the need to instantiate (or even load!)
34.150 -the class implementing the functionality. Only when the real functionality is
34.151 -needed (e.g. the user has selected the menu item) you can call getInstance
34.152 -and call the real meat of the implementation.
34.153 -
34.154 -<H2> Listenning on lookup changes </H2>
34.155 -There is one additional piece of functionality bound to the Lookup.Result object worth
34.156 -mentioning: you can attach a listener to it and be informed about any changes in
34.157 -the lookup. This might be extremly usefull when the lookup dynamically changes
34.158 -(from other threads). The listener can keep state of your object up-to-date even
34.159 -in cases where the lookup changes asynchronously.
34.160 -<p>
34.161 -So here is some sample code using the listenner:
34.162 -
34.163 -<pre>
34.164 - <font class="keyword">import</FONT> org.openide.util.Lookup;
34.165 - <font class="keyword">import</FONT> org.openide.util.LookupListener;
34.166 - <font class="keyword">import</FONT> org.openide.util.LookupEvent;
34.167 -
34.168 - <font class="type">Lookup</font> <font class="variable-name">lookup</font> = ...;
34.169 - Lookup.<font class="type">Template</font> <font class="variable-name">template</font> = <font class="keyword">new</font> Lookup.<font class="type">Template</font>(MyService.<font class="keyword">class</font>);
34.170 - <font class="keyword">final</font> <font class="variable-name">Lookup</font>.<font class="type">Result</font> <font class="variable-name">result</font> = lookup.lookup(template);
34.171 - result.addLookupListener(<font class="keyword">new</font> <font class="type">LookupListener</font>() {
34.172 - <font class="keyword">public</font> <font class="type">void</font> <font class="function-name">resultChanged</font>(<font class="type">LookupEvent</font> <font class="variable-name">e</font>) {
34.173 - reaction(result);
34.174 - }
34.175 - });
34.176 - reaction(result);
34.177 - }
34.178 - <font class="keyword">private</font> <font class="keyword">static</font> <font class="type">void</font> <font class="function-name">reaction</font>(Lookup.<font class="type">Result</font> <font class="variable-name">r</font>) {
34.179 - <font class="keyword">for</font> (<font class="type">Iterator</font> <font class="variable-name">i</font> = r.allInstances().iterator(); i.hasNext(); ) {
34.180 - <font class="type">MyService</font> <font class="variable-name">s</font> = (<font class="type">MyService</font>)i.next();
34.181 - s.callMyService();
34.182 - }
34.183 - }
34.184 -</pre>
34.185 -
34.186 -Please note that we first attach a listener and then call the reaction method.
34.187 -This ensures that we always get the newest possible state. Also you must be
34.188 -careful in the reaction method since it can be called from two different
34.189 -threads simultaneously (your code has to be prepared for this).
34.190 -</BODY>
34.191 -</HTML>
35.1 --- a/lookup/src/main/java/org/openide/util/lookup/doc-files/lookup-spi.html Wed Jan 27 17:46:23 2010 -0500
35.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
35.3 @@ -1,147 +0,0 @@
35.4 -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
35.5 -<!--
35.6 - - DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
35.7 - -
35.8 - - Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
35.9 - -
35.10 - - The contents of this file are subject to the terms of either the GNU
35.11 - - General Public License Version 2 only ("GPL") or the Common
35.12 - - Development and Distribution License("CDDL") (collectively, the
35.13 - - "License"). You may not use this file except in compliance with the
35.14 - - License. You can obtain a copy of the License at
35.15 - - http://www.netbeans.org/cddl-gplv2.html
35.16 - - or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
35.17 - - specific language governing permissions and limitations under the
35.18 - - License. When distributing the software, include this License Header
35.19 - - Notice in each file and include the License file at
35.20 - - nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
35.21 - - particular file as subject to the "Classpath" exception as provided
35.22 - - by Sun in the GPL Version 2 section of the License file that
35.23 - - accompanied this code. If applicable, add the following below the
35.24 - - License Header, with the fields enclosed by brackets [] replaced by
35.25 - - your own identifying information:
35.26 - - "Portions Copyrighted [year] [name of copyright owner]"
35.27 - -
35.28 - - Contributor(s):
35.29 - -
35.30 - - The Original Software is NetBeans. The Initial Developer of the Original
35.31 - - Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
35.32 - - Microsystems, Inc. All Rights Reserved.
35.33 - -
35.34 - - If you wish your version of this file to be governed by only the CDDL
35.35 - - or only the GPL Version 2, indicate your decision by adding
35.36 - - "[Contributor] elects to include this software in this distribution
35.37 - - under the [CDDL or GPL Version 2] license." If you do not indicate a
35.38 - - single choice of license, a recipient has the option to distribute
35.39 - - your version of this file under either the CDDL, the GPL Version 2 or
35.40 - - to extend the choice of license to its licensees as provided above.
35.41 - - However, if you add GPL Version 2 code and therefore, elected the GPL
35.42 - - Version 2 license, then the option applies only if the new code is
35.43 - - made subject to such option by the copyright holder.
35.44 - -->
35.45 -<HTML>
35.46 -<HEAD>
35.47 -<TITLE>Lookup Library SPI</TITLE>
35.48 -<link rel="Stylesheet" href="@TOP@/prose.css" type="text/css" title="NetBeans Open APIs Style">
35.49 -</HEAD>
35.50 -<BODY>
35.51 -<H1>Lookup library SPI</H1>
35.52 -This document describe usage of the SPI provided by the Lookup Library
35.53 -(for those seeking how to use lookup instance please
35.54 -check <A href="lookup-api.html">the API document</A>).
35.55 -<p>
35.56 -By using the SPI you can create lookups that can be used by the users of the
35.57 -Lookup API. While the Lookup API consists of a couple of classes in the package
35.58 -<em>org.openide.util.*</EM>,
35.59 -the SPI has its own package <em>org.openide.util.lookup.*</EM>.
35.60 -
35.61 -<H2> Simple lookups </H2>
35.62 -Let us start with the simplest case. You have decided that your newly created
35.63 -object will provide an API in the form of a getLookup() method. You have to
35.64 -return a functional lookup from this call. You can use static methods in class
35.65 -<a href="@TOP@org/openide/util/lookup/Lookups.html">
35.66 -<code>Lookups</code></A> to create a lookup for you. If you want only one
35.67 -object to be returned, just call
35.68 -<a href="@TOP@org/openide/util/lookup/Lookups.html#singleton(java.lang.Object)">
35.69 -<code>Lookups.singleton(x)</code></A> where x is the object to be
35.70 -returned by the lookup. Or if you want to supply more objects, use a call to the method
35.71 -<a href="@TOP@org/openide/util/lookup/Lookups.html#fixed(java.lang.Object...)">
35.72 -<code>fixed(Object []x)</CODE></A>.
35.73 -<EM> Note: </EM> The lookups returned from methods <code>singleton(...)</code> and
35.74 -<code>fixed(...)</code> do <EM>
35.75 -not </EM> support dynamic changes and attaching listeners. Their content is
35.76 -fixed from the time you call the creating method.
35.77 -
35.78 -<H2> ProxyLookup </H2>
35.79 -There can be situations where you get a lookup object from someone else and you
35.80 -want your lookup to return exactly the instances from the original lookup plus
35.81 -your own results. Here the class ProxyLookup comes into the play.
35.82 -<p>
35.83 -You simply create a new lookup like this:
35.84 -
35.85 -<pre>
35.86 - <font class="keyword">import</FONT> org.openide.util.Lookup;
35.87 - <font class="keyword">import</FONT> org.openide.util.lookup.*;
35.88 -
35.89 - <font class="type">Lookup</font> <font class="variable-name">lookup1</font> = ...;
35.90 -
35.91 - <font class="type">Lookup</font> <font class="variable-name">lookup2</font> = Lookups.singleton(MyService.<font class="keyword">class</font>);
35.92 - <font class="keyword">return</font> <font class="keyword">new</font> <font class="type">ProxyLookup</font>(<font class="keyword">new</font> <font class="type">Lookup</font>[] { lookup, lookup2 });
35.93 -</pre>
35.94 -
35.95 -<H2> AbstractLookup </H2>
35.96 -<!-- This paragraph originally copied from
35.97 -@TOP@org/openide/doc-files/services-api.html#lookup-impl
35.98 --->
35.99 -
35.100 -<p>The most powerful way to provide a lookup is to directly define
35.101 -what instances and items it should provide, by subclassing. For this,
35.102 -
35.103 -<a href="@TOP@org/openide/util/lookup/AbstractLookup.html"><code>AbstractLookup</code></a>
35.104 -
35.105 -is recommended as it is easiest to use.
35.106 -
35.107 -<p>The simplest way to use <code>AbstractLookup</code> is to use its
35.108 -public constructor (in which case you need not subclass it). Here you
35.109 -provide an
35.110 -
35.111 -<a href="@TOP@org/openide/util/lookup/AbstractLookup.Content.html"><code>AbstractLookup.Content</code></a>
35.112 -
35.113 -object which you have created and hold on to privately, and which
35.114 -keeps track of instances and permits them to be registered and
35.115 -deregistered. Often
35.116 -
35.117 -<a href="@TOP@org/openide/util/lookup/InstanceContent.html"><code>InstanceContent</code></a>
35.118 -
35.119 -is used as the content implementation. To add something to the lookup,
35.120 -simply use
35.121 -
35.122 -<a href="@TOP@org/openide/util/lookup/InstanceContent.html#add(java.lang.Object)"><code>add(Object)</code></a>
35.123 -
35.124 -(and <code>remove(Object)</code> for the reverse). These may be called
35.125 -at any time and will update the set of registered instances (firing
35.126 -result changes as needed).
35.127 -
35.128 -<pre>
35.129 - <font class="keyword">import</FONT> org.openide.util.lookup.*;
35.130 - <font class="type">InstanceContent</font> <font class="variable-name">ic</font> = <font class="keyword">new</font> <font class="type">InstanceContent</font> ();
35.131 - ic.add(firstObject);
35.132 - <font class="keyword">return</font> <font class="keyword">new</font> <font class="type">AbstractLookup</font> (ic);
35.133 -</pre>
35.134 -
35.135 -<p>In case it is expensive to actually compute the object in the
35.136 -lookup, but there is some cheap "key" which can easily generate it,
35.137 -you may instead register the key by passing in an
35.138 -
35.139 -<a href="@TOP@org/openide/util/lookup/InstanceContent.Convertor.html"><code>InstanceContent.Convertor</code></a>.
35.140 -
35.141 -This convertor translates the key to the real instance that the lookup
35.142 -client sees, if and when needed. For example, if you have a long list
35.143 -of class names and wish to register default instances of each class,
35.144 -you might actually register the class name as the key, and supply a
35.145 -convertor which really loads the class and instantiates it. This makes
35.146 -it easy to set up the lookup, but nothing is really loaded until
35.147 -someone asks for it.
35.148 -
35.149 -</BODY>
35.150 -</HTML>
36.1 --- a/lookup/src/main/java/org/openide/util/lookup/package.html Wed Jan 27 17:46:23 2010 -0500
36.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
36.3 @@ -1,48 +0,0 @@
36.4 -<!--
36.5 -DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
36.6 -
36.7 -Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
36.8 -
36.9 -
36.10 -The contents of this file are subject to the terms of either the GNU
36.11 -General Public License Version 2 only ("GPL") or the Common
36.12 -Development and Distribution License("CDDL") (collectively, the
36.13 -"License"). You may not use this file except in compliance with the
36.14 -License. You can obtain a copy of the License at
36.15 -http://www.netbeans.org/cddl-gplv2.html
36.16 -or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
36.17 -specific language governing permissions and limitations under the
36.18 -License. When distributing the software, include this License Header
36.19 -Notice in each file and include the License file at
36.20 -nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
36.21 -particular file as subject to the "Classpath" exception as provided
36.22 -by Sun in the GPL Version 2 section of the License file that
36.23 -accompanied this code. If applicable, add the following below the
36.24 -License Header, with the fields enclosed by brackets [] replaced by
36.25 -your own identifying information:
36.26 -"Portions Copyrighted [year] [name of copyright owner]"
36.27 -
36.28 -Contributor(s):
36.29 -
36.30 -The Original Software is NetBeans. The Initial Developer of the Original
36.31 -Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
36.32 -Microsystems, Inc. All Rights Reserved.
36.33 -
36.34 -If you wish your version of this file to be governed by only the CDDL
36.35 -or only the GPL Version 2, indicate your decision by adding
36.36 -"[Contributor] elects to include this software in this distribution
36.37 -under the [CDDL or GPL Version 2] license." If you do not indicate a
36.38 -single choice of license, a recipient has the option to distribute
36.39 -your version of this file under either the CDDL, the GPL Version 2 or
36.40 -to extend the choice of license to its licensees as provided above.
36.41 -However, if you add GPL Version 2 code and therefore, elected the GPL
36.42 -Version 2 license, then the option applies only if the new code is
36.43 -made subject to such option by the copyright holder.
36.44 --->
36.45 -
36.46 -<html>
36.47 -<body>
36.48 -Support classes for the Registration and {@link org.openide.util.Lookup} extension mechanism.
36.49 -Read more: <a href="doc-files/index.html">Lookup Library</a>
36.50 -</body>
36.51 -</html>
37.1 --- a/lookup/src/main/java/org/openide/util/package.html Wed Jan 27 17:46:23 2010 -0500
37.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
37.3 @@ -1,50 +0,0 @@
37.4 -<!--
37.5 - - DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
37.6 - -
37.7 - - Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
37.8 - -
37.9 - - The contents of this file are subject to the terms of either the GNU
37.10 - - General Public License Version 2 only ("GPL") or the Common
37.11 - - Development and Distribution License("CDDL") (collectively, the
37.12 - - "License"). You may not use this file except in compliance with the
37.13 - - License. You can obtain a copy of the License at
37.14 - - http://www.netbeans.org/cddl-gplv2.html
37.15 - - or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
37.16 - - specific language governing permissions and limitations under the
37.17 - - License. When distributing the software, include this License Header
37.18 - - Notice in each file and include the License file at
37.19 - - nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
37.20 - - particular file as subject to the "Classpath" exception as provided
37.21 - - by Sun in the GPL Version 2 section of the License file that
37.22 - - accompanied this code. If applicable, add the following below the
37.23 - - License Header, with the fields enclosed by brackets [] replaced by
37.24 - - your own identifying information:
37.25 - - "Portions Copyrighted [year] [name of copyright owner]"
37.26 - -
37.27 - - Contributor(s):
37.28 - -
37.29 - - The Original Software is NetBeans. The Initial Developer of the Original
37.30 - - Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
37.31 - - Microsystems, Inc. All Rights Reserved.
37.32 - -
37.33 - - If you wish your version of this file to be governed by only the CDDL
37.34 - - or only the GPL Version 2, indicate your decision by adding
37.35 - - "[Contributor] elects to include this software in this distribution
37.36 - - under the [CDDL or GPL Version 2] license." If you do not indicate a
37.37 - - single choice of license, a recipient has the option to distribute
37.38 - - your version of this file under either the CDDL, the GPL Version 2 or
37.39 - - to extend the choice of license to its licensees as provided above.
37.40 - - However, if you add GPL Version 2 code and therefore, elected the GPL
37.41 - - Version 2 license, then the option applies only if the new code is
37.42 - - made subject to such option by the copyright holder.
37.43 - -->
37.44 -
37.45 -<html>
37.46 -<body>
37.47 -
37.48 -Client API part of the
37.49 -<a href="http://top/org/openide/util/lookup/doc-files/lookup-api.html">Lookup</a>
37.50 -interfaces.
37.51 -
37.52 -</body>
37.53 -</html>
38.1 --- a/lookup/src/main/resources/META-INF/services/javax.annotation.processing.Processor Wed Jan 27 17:46:23 2010 -0500
38.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
38.3 @@ -1,1 +0,0 @@
38.4 -org.netbeans.modules.openide.util.ServiceProviderProcessor
39.1 --- a/lookup/src/test/java/org/bar/Comparator2.java Wed Jan 27 17:46:23 2010 -0500
39.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
39.3 @@ -1,7 +0,0 @@
39.4 -
39.5 -package org.bar;
39.6 -
39.7 -public class Comparator2 implements java.util.Comparator {
39.8 - public int compare(Object o1, Object o2) {return 0;}
39.9 - public boolean equals(Object obj) {return true;}
39.10 -}
40.1 --- a/lookup/src/test/java/org/bar/Comparator3.java Wed Jan 27 17:46:23 2010 -0500
40.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
40.3 @@ -1,7 +0,0 @@
40.4 -
40.5 -package org.bar;
40.6 -
40.7 -public class Comparator3 implements java.util.Comparator {
40.8 - public int compare(Object o1, Object o2) {return 0;}
40.9 - public boolean equals(Object obj) {return true;}
40.10 -}
41.1 --- a/lookup/src/test/java/org/bar/Implementation2.java Wed Jan 27 17:46:23 2010 -0500
41.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
41.3 @@ -1,3 +0,0 @@
41.4 -package org.bar;
41.5 -import org.foo.Interface;
41.6 -public class Implementation2 implements Interface {}
42.1 --- a/lookup/src/test/java/org/bar/Iterator2.java Wed Jan 27 17:46:23 2010 -0500
42.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
42.3 @@ -1,11 +0,0 @@
42.4 -
42.5 -package org.bar;
42.6 -
42.7 -public class Iterator2 implements java.util.Iterator {
42.8 - public boolean hasNext() {return false;}
42.9 -
42.10 - public Object next() {return null;}
42.11 -
42.12 - public void remove() {}
42.13 -
42.14 -}
43.1 --- a/lookup/src/test/java/org/foo/Interface.java Wed Jan 27 17:46:23 2010 -0500
43.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
43.3 @@ -1,2 +0,0 @@
43.4 -package org.foo;
43.5 -public interface Interface {}
44.1 --- a/lookup/src/test/java/org/foo/impl/Comparator1.java Wed Jan 27 17:46:23 2010 -0500
44.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
44.3 @@ -1,7 +0,0 @@
44.4 -
44.5 -package org.foo.impl;
44.6 -
44.7 -public class Comparator1 implements java.util.Comparator {
44.8 - public int compare(Object o1, Object o2) {return 0;}
44.9 - public boolean equals(Object obj) {return true;}
44.10 -}
45.1 --- a/lookup/src/test/java/org/foo/impl/Implementation1.java Wed Jan 27 17:46:23 2010 -0500
45.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
45.3 @@ -1,3 +0,0 @@
45.4 -package org.foo.impl;
45.5 -import org.foo.Interface;
45.6 -public class Implementation1 implements Interface {}
46.1 --- a/lookup/src/test/java/org/foo/impl/Iterator1.java Wed Jan 27 17:46:23 2010 -0500
46.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
46.3 @@ -1,11 +0,0 @@
46.4 -
46.5 -package org.foo.impl;
46.6 -
46.7 -public class Iterator1 implements java.util.Iterator {
46.8 - public boolean hasNext() {return false;}
46.9 -
46.10 - public Object next() {return null;}
46.11 -
46.12 - public void remove() {}
46.13 -
46.14 -}
47.1 --- a/lookup/src/test/java/org/foo/impl/Runnable1.java Wed Jan 27 17:46:23 2010 -0500
47.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
47.3 @@ -1,6 +0,0 @@
47.4 -
47.5 -package org.foo.impl;
47.6 -
47.7 -public class Runnable1 implements Runnable {
47.8 - public void run () {}
47.9 -}
48.1 --- a/lookup/src/test/java/org/netbeans/modules/openide/util/ActiveQueueTest.java Wed Jan 27 17:46:23 2010 -0500
48.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
48.3 @@ -1,132 +0,0 @@
48.4 -/*
48.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
48.6 - *
48.7 - * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
48.8 - *
48.9 - * The contents of this file are subject to the terms of either the GNU
48.10 - * General Public License Version 2 only ("GPL") or the Common
48.11 - * Development and Distribution License("CDDL") (collectively, the
48.12 - * "License"). You may not use this file except in compliance with the
48.13 - * License. You can obtain a copy of the License at
48.14 - * http://www.netbeans.org/cddl-gplv2.html
48.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
48.16 - * specific language governing permissions and limitations under the
48.17 - * License. When distributing the software, include this License Header
48.18 - * Notice in each file and include the License file at
48.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
48.20 - * particular file as subject to the "Classpath" exception as provided
48.21 - * by Sun in the GPL Version 2 section of the License file that
48.22 - * accompanied this code. If applicable, add the following below the
48.23 - * License Header, with the fields enclosed by brackets [] replaced by
48.24 - * your own identifying information:
48.25 - * "Portions Copyrighted [year] [name of copyright owner]"
48.26 - *
48.27 - * If you wish your version of this file to be governed by only the CDDL
48.28 - * or only the GPL Version 2, indicate your decision by adding
48.29 - * "[Contributor] elects to include this software in this distribution
48.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
48.31 - * single choice of license, a recipient has the option to distribute
48.32 - * your version of this file under either the CDDL, the GPL Version 2 or
48.33 - * to extend the choice of license to its licensees as provided above.
48.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
48.35 - * Version 2 license, then the option applies only if the new code is
48.36 - * made subject to such option by the copyright holder.
48.37 - *
48.38 - * Contributor(s):
48.39 - *
48.40 - * Portions Copyrighted 2009 Sun Microsystems, Inc.
48.41 - */
48.42 -
48.43 -package org.netbeans.modules.openide.util;
48.44 -
48.45 -import java.lang.ref.Reference;
48.46 -import java.lang.ref.ReferenceQueue;
48.47 -import java.lang.ref.WeakReference;
48.48 -import java.net.URL;
48.49 -import java.net.URLClassLoader;
48.50 -import org.netbeans.junit.NbTestCase;
48.51 -
48.52 -/**
48.53 - *
48.54 - * @author Jaroslav Tulach <jtulach@netbeans.org>
48.55 - */
48.56 -public class ActiveQueueTest extends NbTestCase{
48.57 -
48.58 - public ActiveQueueTest(String name) {
48.59 - super(name);
48.60 - }
48.61 -
48.62 - public void testMemoryLeak() throws Exception {
48.63 - final Class<?> u1 = ActiveQueue.class;
48.64 - class L extends URLClassLoader {
48.65 - public L() {
48.66 - super(new URL[] {u1.getProtectionDomain().getCodeSource().getLocation()}, u1.getClassLoader().getParent());
48.67 - }
48.68 - @Override
48.69 - protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
48.70 - if (name.equals(u1.getName()) || name.startsWith(u1.getName() + "$")) {
48.71 - Class c = findLoadedClass(name);
48.72 - if (c == null) {
48.73 - c = findClass(name);
48.74 - }
48.75 - if (resolve) {
48.76 - resolveClass(c);
48.77 - }
48.78 - return c;
48.79 - } else {
48.80 - return super.loadClass(name, resolve);
48.81 - }
48.82 - }
48.83 - }
48.84 - ClassLoader l = new L();
48.85 - Class<?> u2 = l.loadClass(u1.getName());
48.86 - assertEquals(l, u2.getClassLoader());
48.87 - Object obj = new Object();
48.88 - @SuppressWarnings("unchecked")
48.89 - ReferenceQueue<Object> q = (ReferenceQueue<Object>) u2.getMethod("queue").invoke(null);
48.90 - RunnableRef ref = new RunnableRef(obj, q);
48.91 - synchronized (ref) {
48.92 - obj = null;
48.93 - assertGC("Ref should be GC'ed as usual", ref);
48.94 - ref.wait();
48.95 - assertTrue("Run method has been executed", ref.executed);
48.96 - }
48.97 - Reference<?> r = new WeakReference<Object>(u2);
48.98 - q = null;
48.99 - u2 = null;
48.100 - l = null;
48.101 - assertGC("#86625: Utilities.class can also be collected now", r);
48.102 - }
48.103 -
48.104 -
48.105 - private static class RunnableRef extends WeakReference<Object>
48.106 - implements Runnable {
48.107 - public boolean wait;
48.108 - public boolean entered;
48.109 - public boolean executed;
48.110 -
48.111 - public RunnableRef (Object o) {
48.112 - this(o, ActiveQueue.queue());
48.113 - }
48.114 -
48.115 - public RunnableRef(Object o, ReferenceQueue<Object> q) {
48.116 - super(o, q);
48.117 - }
48.118 -
48.119 - public synchronized void run () {
48.120 - entered = true;
48.121 - if (wait) {
48.122 - // notify we are here
48.123 - notify ();
48.124 - try {
48.125 - wait ();
48.126 - } catch (InterruptedException ex) {
48.127 - }
48.128 - }
48.129 - executed = true;
48.130 -
48.131 - notifyAll ();
48.132 - }
48.133 - }
48.134 -
48.135 -}
48.136 \ No newline at end of file
49.1 --- a/lookup/src/test/java/org/netbeans/modules/openide/util/ServiceProviderProcessorTest.java Wed Jan 27 17:46:23 2010 -0500
49.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
49.3 @@ -1,180 +0,0 @@
49.4 -/*
49.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
49.6 - *
49.7 - * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
49.8 - *
49.9 - * The contents of this file are subject to the terms of either the GNU
49.10 - * General Public License Version 2 only ("GPL") or the Common
49.11 - * Development and Distribution License("CDDL") (collectively, the
49.12 - * "License"). You may not use this file except in compliance with the
49.13 - * License. You can obtain a copy of the License at
49.14 - * http://www.netbeans.org/cddl-gplv2.html
49.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
49.16 - * specific language governing permissions and limitations under the
49.17 - * License. When distributing the software, include this License Header
49.18 - * Notice in each file and include the License file at
49.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
49.20 - * particular file as subject to the "Classpath" exception as provided
49.21 - * by Sun in the GPL Version 2 section of the License file that
49.22 - * accompanied this code. If applicable, add the following below the
49.23 - * License Header, with the fields enclosed by brackets [] replaced by
49.24 - * your own identifying information:
49.25 - * "Portions Copyrighted [year] [name of copyright owner]"
49.26 - *
49.27 - * If you wish your version of this file to be governed by only the CDDL
49.28 - * or only the GPL Version 2, indicate your decision by adding
49.29 - * "[Contributor] elects to include this software in this distribution
49.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
49.31 - * single choice of license, a recipient has the option to distribute
49.32 - * your version of this file under either the CDDL, the GPL Version 2 or
49.33 - * to extend the choice of license to its licensees as provided above.
49.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
49.35 - * Version 2 license, then the option applies only if the new code is
49.36 - * made subject to such option by the copyright holder.
49.37 - *
49.38 - * Contributor(s):
49.39 - *
49.40 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
49.41 - */
49.42 -
49.43 -package org.netbeans.modules.openide.util;
49.44 -
49.45 -import java.io.ByteArrayOutputStream;
49.46 -import java.io.File;
49.47 -import java.util.ArrayList;
49.48 -import java.util.Arrays;
49.49 -import java.util.Collections;
49.50 -import java.util.Comparator;
49.51 -import java.util.List;
49.52 -import org.netbeans.junit.NbTestCase;
49.53 -import org.openide.util.Lookup;
49.54 -import org.openide.util.lookup.Lookups;
49.55 -import org.openide.util.lookup.ServiceProvider;
49.56 -import org.openide.util.lookup.ServiceProviders;
49.57 -import org.openide.util.test.AnnotationProcessorTestUtils;
49.58 -
49.59 -public class ServiceProviderProcessorTest extends NbTestCase {
49.60 -
49.61 - public ServiceProviderProcessorTest(String n) {
49.62 - super(n);
49.63 - }
49.64 -
49.65 - private static List<Class<?>> classesOf(Iterable<?> objects) {
49.66 - List<Class<?>> cs = new ArrayList<Class<?>>();
49.67 - for (Object o : objects) {
49.68 - cs.add(o.getClass());
49.69 - }
49.70 - return cs;
49.71 - }
49.72 -
49.73 - private static List<Class<?>> classesOfLookup(Class<?> xface) {
49.74 - return classesOf(Lookup.getDefault().lookupAll(xface));
49.75 - }
49.76 -
49.77 - private static List<Class<?>> sortClassList(List<Class<?>> classes) {
49.78 - List<Class<?>> sorted = new ArrayList<Class<?>>(classes);
49.79 - Collections.sort(sorted, new Comparator<Class<?>>() {
49.80 - public int compare(Class<?> c1, Class<?> c2) {
49.81 - return c1.getName().compareTo(c2.getName());
49.82 - }
49.83 - });
49.84 - return sorted;
49.85 - }
49.86 -
49.87 - public void testBasicUsage() throws Exception {
49.88 - assertEquals(Collections.singletonList(Implementation.class), classesOfLookup(Interface.class));
49.89 - }
49.90 - public interface Interface {}
49.91 - @ServiceProvider(service=Interface.class)
49.92 - public static class Implementation implements Interface {}
49.93 -
49.94 - public void testPosition() throws Exception {
49.95 - assertEquals(Arrays.<Class<?>>asList(OrderedImpl3.class, OrderedImpl2.class, OrderedImpl1.class), classesOfLookup(OrderedInterface.class));
49.96 - }
49.97 - public interface OrderedInterface {}
49.98 - @ServiceProvider(service=OrderedInterface.class)
49.99 - public static class OrderedImpl1 implements OrderedInterface {}
49.100 - @ServiceProvider(service=OrderedInterface.class, position=200)
49.101 - public static class OrderedImpl2 implements OrderedInterface {}
49.102 - @ServiceProvider(service=OrderedInterface.class, position=100)
49.103 - public static class OrderedImpl3 implements OrderedInterface {}
49.104 -
49.105 - public void testPath() throws Exception {
49.106 - assertEquals(Collections.singletonList(PathImplementation.class), classesOf(Lookups.forPath("some/path").lookupAll(Interface.class)));
49.107 - }
49.108 - @ServiceProvider(service=Interface.class, path="some/path")
49.109 - public static class PathImplementation implements Interface {}
49.110 -
49.111 - public void testSupersedes() throws Exception {
49.112 - assertEquals(Arrays.<Class<?>>asList(Overrider.class, Unrelated.class), sortClassList(classesOfLookup(CancellableInterface.class)));
49.113 - }
49.114 - public interface CancellableInterface {}
49.115 - @ServiceProvider(service=CancellableInterface.class)
49.116 - public static class Overridden implements CancellableInterface {}
49.117 - @ServiceProvider(service=CancellableInterface.class, supersedes="org.netbeans.modules.openide.util.ServiceProviderProcessorTest$Overridden")
49.118 - public static class Overrider implements CancellableInterface {}
49.119 - @ServiceProvider(service=CancellableInterface.class)
49.120 - public static class Unrelated implements CancellableInterface {}
49.121 -
49.122 - public void testMultipleRegistrations() throws Exception {
49.123 - assertEquals(Collections.singletonList(Multitasking.class), classesOfLookup(Interface1.class));
49.124 - assertEquals(Collections.singletonList(Multitasking.class), classesOfLookup(Interface2.class));
49.125 - }
49.126 - public interface Interface1 {}
49.127 - public interface Interface2 {}
49.128 - @ServiceProviders({@ServiceProvider(service=Interface1.class), @ServiceProvider(service=Interface2.class)})
49.129 - public static class Multitasking implements Interface1, Interface2 {}
49.130 -
49.131 - public void testErrorReporting() throws Exception {
49.132 - clearWorkDir();
49.133 - File src = new File(getWorkDir(), "src");
49.134 - File dest = new File(getWorkDir(), "classes");
49.135 - String xfaceName = Interface.class.getCanonicalName();
49.136 -
49.137 - AnnotationProcessorTestUtils.makeSource(src, "p.C1",
49.138 - "@org.openide.util.lookup.ServiceProvider(service=" + xfaceName + ".class)",
49.139 - "public class C1 implements " + xfaceName + " {}");
49.140 - ByteArrayOutputStream baos = new ByteArrayOutputStream();
49.141 - assertTrue(AnnotationProcessorTestUtils.runJavac(src, "C1", dest, null, baos));
49.142 -
49.143 - AnnotationProcessorTestUtils.makeSource(src, "p.C2",
49.144 - "@org.openide.util.lookup.ServiceProvider(service=" + xfaceName + ".class)",
49.145 - "class C2 implements " + xfaceName + " {}");
49.146 - baos = new ByteArrayOutputStream();
49.147 - assertFalse(AnnotationProcessorTestUtils.runJavac(src, "C2", dest, null, baos));
49.148 - assertTrue(baos.toString(), baos.toString().contains("public"));
49.149 -
49.150 - AnnotationProcessorTestUtils.makeSource(src, "p.C3",
49.151 - "@org.openide.util.lookup.ServiceProvider(service=" + xfaceName + ".class)",
49.152 - "public class C3 implements " + xfaceName + " {",
49.153 - "public C3(boolean x) {}",
49.154 - "}");
49.155 - baos = new ByteArrayOutputStream();
49.156 - assertFalse(AnnotationProcessorTestUtils.runJavac(src, "C3", dest, null, baos));
49.157 - assertTrue(baos.toString(), baos.toString().contains("constructor"));
49.158 -
49.159 - AnnotationProcessorTestUtils.makeSource(src, "p.C4",
49.160 - "@org.openide.util.lookup.ServiceProvider(service=" + xfaceName + ".class)",
49.161 - "public class C4 implements " + xfaceName + " {",
49.162 - "C4() {}",
49.163 - "}");
49.164 - baos = new ByteArrayOutputStream();
49.165 - assertFalse(AnnotationProcessorTestUtils.runJavac(src, "C4", dest, null, baos));
49.166 - assertTrue(baos.toString(), baos.toString().contains("constructor"));
49.167 -
49.168 - AnnotationProcessorTestUtils.makeSource(src, "p.C5",
49.169 - "@org.openide.util.lookup.ServiceProvider(service=" + xfaceName + ".class)",
49.170 - "public abstract class C5 implements " + xfaceName + " {}");
49.171 - baos = new ByteArrayOutputStream();
49.172 - assertFalse(AnnotationProcessorTestUtils.runJavac(src, "C5", dest, null, baos));
49.173 - assertTrue(baos.toString(), baos.toString().contains("abstract"));
49.174 -
49.175 - AnnotationProcessorTestUtils.makeSource(src, "p.C6",
49.176 - "@org.openide.util.lookup.ServiceProvider(service=" + xfaceName + ".class)",
49.177 - "public class C6 {}");
49.178 - baos = new ByteArrayOutputStream();
49.179 - assertFalse(AnnotationProcessorTestUtils.runJavac(src, "C6", dest, null, baos));
49.180 - assertTrue(baos.toString(), baos.toString().contains("assignable"));
49.181 - }
49.182 -
49.183 -}
50.1 --- a/lookup/src/test/java/org/openide/util/lookup/AbstractLookupArrayStorageTest.java Wed Jan 27 17:46:23 2010 -0500
50.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
50.3 @@ -1,120 +0,0 @@
50.4 -/*
50.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
50.6 - *
50.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
50.8 - *
50.9 - * The contents of this file are subject to the terms of either the GNU
50.10 - * General Public License Version 2 only ("GPL") or the Common
50.11 - * Development and Distribution License("CDDL") (collectively, the
50.12 - * "License"). You may not use this file except in compliance with the
50.13 - * License. You can obtain a copy of the License at
50.14 - * http://www.netbeans.org/cddl-gplv2.html
50.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
50.16 - * specific language governing permissions and limitations under the
50.17 - * License. When distributing the software, include this License Header
50.18 - * Notice in each file and include the License file at
50.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
50.20 - * particular file as subject to the "Classpath" exception as provided
50.21 - * by Sun in the GPL Version 2 section of the License file that
50.22 - * accompanied this code. If applicable, add the following below the
50.23 - * License Header, with the fields enclosed by brackets [] replaced by
50.24 - * your own identifying information:
50.25 - * "Portions Copyrighted [year] [name of copyright owner]"
50.26 - *
50.27 - * Contributor(s):
50.28 - *
50.29 - * The Original Software is NetBeans. The Initial Developer of the Original
50.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
50.31 - * Microsystems, Inc. All Rights Reserved.
50.32 - *
50.33 - * If you wish your version of this file to be governed by only the CDDL
50.34 - * or only the GPL Version 2, indicate your decision by adding
50.35 - * "[Contributor] elects to include this software in this distribution
50.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
50.37 - * single choice of license, a recipient has the option to distribute
50.38 - * your version of this file under either the CDDL, the GPL Version 2 or
50.39 - * to extend the choice of license to its licensees as provided above.
50.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
50.41 - * Version 2 license, then the option applies only if the new code is
50.42 - * made subject to such option by the copyright holder.
50.43 - */
50.44 -
50.45 -package org.openide.util.lookup;
50.46 -
50.47 -import junit.framework.*;
50.48 -import org.netbeans.junit.*;
50.49 -import org.openide.util.Lookup;
50.50 -
50.51 -public class AbstractLookupArrayStorageTest extends AbstractLookupBaseHid {
50.52 - public AbstractLookupArrayStorageTest(java.lang.String testName) {
50.53 - super(testName, null);
50.54 - }
50.55 -
50.56 - public static TestSuite suite () {
50.57 - NbTestSuite suite = new NbTestSuite ();
50.58 - suite.addTest (new PL (2));
50.59 - suite.addTest (new AL (1));
50.60 - suite.addTest (new AL (-1));
50.61 - suite.addTest (new PL (-1));
50.62 - suite.addTest (new AL (5));
50.63 - suite.addTest (new PL (3));
50.64 - suite.addTest (new AL (2000));
50.65 - suite.addTest (new PL (2000));
50.66 - return suite;
50.67 - }
50.68 -
50.69 - static final class AL extends ArrayTestSuite {
50.70 - public AL (int trash) {
50.71 - super (trash);
50.72 - }
50.73 -
50.74 - public Lookup createLookup (Lookup lookup) {
50.75 - return lookup;
50.76 - }
50.77 -
50.78 - public void clearCaches () {
50.79 - }
50.80 -
50.81 - }
50.82 -
50.83 - static final class PL extends ArrayTestSuite {
50.84 - public PL (int trash) {
50.85 - super (trash);
50.86 - }
50.87 -
50.88 - public Lookup createLookup (Lookup lookup) {
50.89 - return new ProxyLookup (new Lookup[] { lookup });
50.90 - }
50.91 -
50.92 - public void clearCaches () {
50.93 - }
50.94 -
50.95 - }
50.96 -
50.97 - private static abstract class ArrayTestSuite extends NbTestSuite
50.98 - implements AbstractLookupBaseHid.Impl {
50.99 - private int trash;
50.100 -
50.101 - public ArrayTestSuite (int trash) {
50.102 - super (AbstractLookupArrayStorageTest.class);
50.103 - this.trash = trash;
50.104 -
50.105 - int cnt = this.countTestCases();
50.106 - for (int i = 0; i < cnt; i++) {
50.107 - Object o = this.testAt (i);
50.108 - AbstractLookupBaseHid t = (AbstractLookupBaseHid)o;
50.109 - t.impl = this;
50.110 - }
50.111 - }
50.112 -
50.113 - public Lookup createInstancesLookup (InstanceContent ic) {
50.114 - if (trash == -1) {
50.115 - return new AbstractLookup (ic, new ArrayStorage ());
50.116 - } else {
50.117 - return new AbstractLookup (ic, new ArrayStorage (new Integer (trash)));
50.118 - }
50.119 - }
50.120 -
50.121 -
50.122 - }
50.123 -}
51.1 --- a/lookup/src/test/java/org/openide/util/lookup/AbstractLookupAsynchExecutorTest.java Wed Jan 27 17:46:23 2010 -0500
51.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
51.3 @@ -1,108 +0,0 @@
51.4 -/*
51.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
51.6 - *
51.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
51.8 - *
51.9 - * The contents of this file are subject to the terms of either the GNU
51.10 - * General Public License Version 2 only ("GPL") or the Common
51.11 - * Development and Distribution License("CDDL") (collectively, the
51.12 - * "License"). You may not use this file except in compliance with the
51.13 - * License. You can obtain a copy of the License at
51.14 - * http://www.netbeans.org/cddl-gplv2.html
51.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
51.16 - * specific language governing permissions and limitations under the
51.17 - * License. When distributing the software, include this License Header
51.18 - * Notice in each file and include the License file at
51.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
51.20 - * particular file as subject to the "Classpath" exception as provided
51.21 - * by Sun in the GPL Version 2 section of the License file that
51.22 - * accompanied this code. If applicable, add the following below the
51.23 - * License Header, with the fields enclosed by brackets [] replaced by
51.24 - * your own identifying information:
51.25 - * "Portions Copyrighted [year] [name of copyright owner]"
51.26 - *
51.27 - * Contributor(s):
51.28 - *
51.29 - * The Original Software is NetBeans. The Initial Developer of the Original
51.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
51.31 - * Microsystems, Inc. All Rights Reserved.
51.32 - *
51.33 - * If you wish your version of this file to be governed by only the CDDL
51.34 - * or only the GPL Version 2, indicate your decision by adding
51.35 - * "[Contributor] elects to include this software in this distribution
51.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
51.37 - * single choice of license, a recipient has the option to distribute
51.38 - * your version of this file under either the CDDL, the GPL Version 2 or
51.39 - * to extend the choice of license to its licensees as provided above.
51.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
51.41 - * Version 2 license, then the option applies only if the new code is
51.42 - * made subject to such option by the copyright holder.
51.43 - */
51.44 -
51.45 -package org.openide.util.lookup;
51.46 -
51.47 -import java.util.ArrayList;
51.48 -import java.util.List;
51.49 -import java.util.concurrent.Executor;
51.50 -import org.netbeans.junit.NbTestCase;
51.51 -import org.openide.util.Lookup;
51.52 -import org.openide.util.LookupEvent;
51.53 -import org.openide.util.LookupListener;
51.54 -
51.55 -public class AbstractLookupAsynchExecutorTest extends NbTestCase implements Executor {
51.56 - private List<Runnable> toRun = new ArrayList<Runnable>();
51.57 -
51.58 -
51.59 - public AbstractLookupAsynchExecutorTest(java.lang.String testName) {
51.60 - super(testName);
51.61 - }
51.62 -
51.63 - public void testCanProxyLookupHaveWrongResults() {
51.64 - final InstanceContent ic = new InstanceContent(this);
51.65 - final AbstractLookup lookup = new AbstractLookup(ic);
51.66 -
51.67 - class L implements LookupListener {
51.68 - ProxyLookup pl;
51.69 - Lookup.Result<String> original;
51.70 - Lookup.Result<String> wrapped;
51.71 - boolean ok;
51.72 -
51.73 - public void test() {
51.74 - pl = new ProxyLookup(lookup);
51.75 - original = lookup.lookupResult(String.class);
51.76 -
51.77 - original.addLookupListener(this);
51.78 -
51.79 - wrapped = pl.lookupResult(String.class);
51.80 -
51.81 - assertEquals("Original empty", 0, original.allInstances().size());
51.82 - assertEquals("Wrapped empty", 0, wrapped.allInstances().size());
51.83 -
51.84 - ic.add("Hello!");
51.85 - }
51.86 -
51.87 - public void resultChanged(LookupEvent ev) {
51.88 - ok = true;
51.89 - assertContainsHello();
51.90 - }
51.91 -
51.92 - public void assertContainsHello() {
51.93 - assertEquals("Original has hello", 1, original.allInstances().size());
51.94 - assertEquals("Wrapped has hello", 1, wrapped.allInstances().size());
51.95 - }
51.96 -
51.97 - }
51.98 - L listener = new L();
51.99 - listener.test();
51.100 - listener.assertContainsHello();
51.101 - for (Runnable r : toRun) {
51.102 - r.run();
51.103 - }
51.104 - assertTrue("Listener called", listener.ok);
51.105 - }
51.106 -
51.107 - public void execute(Runnable command) {
51.108 - toRun.add(command);
51.109 - }
51.110 -
51.111 -}
52.1 --- a/lookup/src/test/java/org/openide/util/lookup/AbstractLookupBaseHid.java Wed Jan 27 17:46:23 2010 -0500
52.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
52.3 @@ -1,2088 +0,0 @@
52.4 -/*
52.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
52.6 - *
52.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
52.8 - *
52.9 - * The contents of this file are subject to the terms of either the GNU
52.10 - * General Public License Version 2 only ("GPL") or the Common
52.11 - * Development and Distribution License("CDDL") (collectively, the
52.12 - * "License"). You may not use this file except in compliance with the
52.13 - * License. You can obtain a copy of the License at
52.14 - * http://www.netbeans.org/cddl-gplv2.html
52.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
52.16 - * specific language governing permissions and limitations under the
52.17 - * License. When distributing the software, include this License Header
52.18 - * Notice in each file and include the License file at
52.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
52.20 - * particular file as subject to the "Classpath" exception as provided
52.21 - * by Sun in the GPL Version 2 section of the License file that
52.22 - * accompanied this code. If applicable, add the following below the
52.23 - * License Header, with the fields enclosed by brackets [] replaced by
52.24 - * your own identifying information:
52.25 - * "Portions Copyrighted [year] [name of copyright owner]"
52.26 - *
52.27 - * Contributor(s):
52.28 - *
52.29 - * The Original Software is NetBeans. The Initial Developer of the Original
52.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
52.31 - * Microsystems, Inc. All Rights Reserved.
52.32 - *
52.33 - * If you wish your version of this file to be governed by only the CDDL
52.34 - * or only the GPL Version 2, indicate your decision by adding
52.35 - * "[Contributor] elects to include this software in this distribution
52.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
52.37 - * single choice of license, a recipient has the option to distribute
52.38 - * your version of this file under either the CDDL, the GPL Version 2 or
52.39 - * to extend the choice of license to its licensees as provided above.
52.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
52.41 - * Version 2 license, then the option applies only if the new code is
52.42 - * made subject to such option by the copyright holder.
52.43 - */
52.44 -
52.45 -package org.openide.util.lookup;
52.46 -
52.47 -import java.io.ByteArrayInputStream;
52.48 -import java.io.ByteArrayOutputStream;
52.49 -import java.io.ObjectInputStream;
52.50 -import java.io.ObjectOutputStream;
52.51 -import java.io.Serializable;
52.52 -import java.lang.ref.WeakReference;
52.53 -import java.lang.ref.Reference;
52.54 -import java.util.ArrayList;
52.55 -import java.util.Arrays;
52.56 -import java.util.Collection;
52.57 -import java.util.Collections;
52.58 -import java.util.Iterator;
52.59 -import java.util.LinkedList;
52.60 -import java.util.List;
52.61 -import java.util.concurrent.Executors;
52.62 -import java.util.concurrent.TimeUnit;
52.63 -import javax.swing.ActionMap;
52.64 -import javax.swing.InputMap;
52.65 -import org.netbeans.junit.NbTestCase;
52.66 -import org.openide.util.Lookup;
52.67 -import org.openide.util.Lookup.Template;
52.68 -import org.openide.util.LookupEvent;
52.69 -import org.openide.util.LookupListener;
52.70 -
52.71 -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
52.72 -public class AbstractLookupBaseHid extends NbTestCase {
52.73 - private static AbstractLookupBaseHid running;
52.74 -
52.75 - /** instance content to work with */
52.76 - InstanceContent ic;
52.77 - /** the lookup to work on */
52.78 - protected Lookup instanceLookup;
52.79 - /** the lookup created to work with */
52.80 - private Lookup lookup;
52.81 - /** implementation of methods that can influence the behaviour */
52.82 - Impl impl;
52.83 -
52.84 - protected AbstractLookupBaseHid(String testName, Impl impl) {
52.85 - super(testName);
52.86 - if (impl == null && (this instanceof Impl)) {
52.87 - impl = (Impl)this;
52.88 - }
52.89 - this.impl = impl;
52.90 - }
52.91 -
52.92 - protected @Override void setUp() {
52.93 - this.ic = new InstanceContent ();
52.94 -
52.95 - beforeActualTest(getName());
52.96 -
52.97 - this.instanceLookup = createInstancesLookup (ic);
52.98 - this.lookup = createLookup (instanceLookup);
52.99 - running = this;
52.100 - }
52.101 -
52.102 - protected @Override void tearDown() {
52.103 - running = null;
52.104 - }
52.105 -
52.106 - /** The methods to influence test behaviour */
52.107 - public static interface Impl {
52.108 - /** Creates the initial abstract lookup.
52.109 - */
52.110 - public Lookup createInstancesLookup (InstanceContent ic);
52.111 - /** Creates an lookup for given lookup. This class just returns
52.112 - * the object passed in, but subclasses can be different.
52.113 - * @param lookup in lookup
52.114 - * @return a lookup to use
52.115 - */
52.116 - public Lookup createLookup (Lookup lookup);
52.117 -
52.118 - /** If the impl has any caches that would prevent the system
52.119 - * to not garbage collect correctly, then clear them now.
52.120 - */
52.121 - public void clearCaches ();
52.122 - }
52.123 -
52.124 - private Lookup createInstancesLookup (InstanceContent ic) {
52.125 - return impl.createInstancesLookup (ic);
52.126 - }
52.127 -
52.128 - private Lookup createLookup (Lookup lookup) {
52.129 - return impl.createLookup (lookup);
52.130 - }
52.131 -
52.132 - /** instances that we register */
52.133 - private static Object[] INSTANCES = new Object[] {
52.134 - new Integer (10),
52.135 - new Object ()
52.136 - };
52.137 -
52.138 - /** Test if first is really first.
52.139 - */
52.140 - public void testFirst () {
52.141 - Integer i1 = 1;
52.142 - Integer i2 = 2;
52.143 -
52.144 - ic.add (i1);
52.145 - ic.add (i2);
52.146 -
52.147 - Integer found = lookup.lookup(Integer.class);
52.148 - if (found != i1) {
52.149 - fail ("First object is not first: " + found + " != " + i1);
52.150 - }
52.151 -
52.152 - List<Integer> list = new ArrayList<Integer>();
52.153 - list.add (i2);
52.154 - list.add (i1);
52.155 - ic.set (list, null);
52.156 -
52.157 - found = lookup.lookup (Integer.class);
52.158 - if (found != i2) {
52.159 - fail ("Second object is not first after reorder: " + found + " != " + i2);
52.160 - }
52.161 -
52.162 - }
52.163 -
52.164 - public void testToString() {
52.165 - String txt = lookup.toString();
52.166 - assertNotNull("Something is there", txt);
52.167 - assertTrue("Something2: " + txt, txt.length() > 0);
52.168 - }
52.169 -
52.170 -
52.171 - /** Tests ordering of items in the lookup.
52.172 - */
52.173 - public void testOrder () {
52.174 - addInstances (INSTANCES);
52.175 -
52.176 - if (INSTANCES[0] != lookup.lookup (INSTANCES[0].getClass ())) {
52.177 - fail ("First object in intances not found");
52.178 - }
52.179 -
52.180 - Iterator<?> all = lookup.lookupAll(Object.class).iterator();
52.181 - checkIterator ("Difference between instances added and found", all, Arrays.asList (INSTANCES));
52.182 - }
52.183 -
52.184 - /** Checks the reorder of items in lookup reflects the result.
52.185 - * Testing both classes and interfaces, because they are often treated
52.186 - * especially.
52.187 - */
52.188 - public void testReorder () {
52.189 - String s1 = "s2";
52.190 - String s2 = "s1";
52.191 - Runnable r1 = new Runnable () {
52.192 - public void run () {}
52.193 - };
52.194 - Runnable r2 = new Runnable () {
52.195 - public void run () {}
52.196 - };
52.197 - List<Object> l = new ArrayList<Object>();
52.198 -
52.199 - l.add (s1);
52.200 - l.add (s2);
52.201 - l.add (r1);
52.202 - l.add (r2);
52.203 - ic.set (l, null);
52.204 -
52.205 - assertEquals ("s1 is found", s1, lookup.lookup (String.class));
52.206 - assertEquals ("r1 is found", r1, lookup.lookup (Runnable.class));
52.207 -
52.208 - Collections.reverse (l);
52.209 -
52.210 - ic.set (l, null);
52.211 -
52.212 - assertEquals ("s2 is found", s2, lookup.lookup (String.class));
52.213 - assertEquals ("r2 is found", r2, lookup.lookup (Runnable.class));
52.214 - }
52.215 -
52.216 - /** Tries to set empty collection to the lookup.
52.217 - */
52.218 - public void testSetEmpty () {
52.219 - ic.add ("A serializable string");
52.220 - lookup.lookup (Serializable.class);
52.221 -
52.222 - ic.set (Collections.emptyList(), null);
52.223 - }
52.224 -
52.225 - /** Tests a more complex reorder on nodes.
52.226 - */
52.227 - public void testComplexReorder () {
52.228 - Integer i1 = 1;
52.229 - Long i2 = 2L;
52.230 -
52.231 - List<Object> l = new ArrayList<Object>();
52.232 - l.add (i1);
52.233 - l.add (i2);
52.234 - ic.set (l, null);
52.235 -
52.236 - assertEquals ("Find integer", i1, lookup.lookup (Integer.class));
52.237 - assertEquals ("Find long", i2, lookup.lookup (Long.class));
52.238 - assertEquals ("Find number", i1, lookup.lookup (Number.class));
52.239 -
52.240 - Collections.reverse (l);
52.241 -
52.242 - ic.set (l, null);
52.243 -
52.244 - assertEquals ("Find integer", i1, lookup.lookup (Integer.class));
52.245 - assertEquals ("Find long", i2, lookup.lookup (Long.class));
52.246 - assertEquals ("Find number", i2, lookup.lookup (Number.class));
52.247 - }
52.248 -
52.249 - /** Checks whether setPairs keeps the order.
52.250 - */
52.251 - public void testSetPairs () {
52.252 - // test setPairs method
52.253 - List<Object> li = new ArrayList<Object>();
52.254 - li.addAll (Arrays.asList (INSTANCES));
52.255 - ic.set (li, null);
52.256 -
52.257 - Lookup.Result<Object> res = lookup.lookupResult(Object.class);
52.258 - Iterator<?> all = res.allInstances().iterator();
52.259 - checkIterator ("Original order not kept", all, li);
52.260 -
52.261 - // reverse the order
52.262 - Collections.reverse (li);
52.263 -
52.264 - // change the pairs
52.265 - LL listener = new LL (res);
52.266 - res.addLookupListener (listener);
52.267 - ic.set (li, null);
52.268 - if (listener.getCount () != 1) {
52.269 - fail ("Result has not changed even we set reversed order");
52.270 - }
52.271 -
52.272 - all = res.allInstances ().iterator ();
52.273 - checkIterator ("Reversed order not kept", all, li);
52.274 - }
52.275 -
52.276 - /** Checks whether setPairs fires correct events.
52.277 - */
52.278 - public void testSetPairsFire () {
52.279 - // test setPairs method
52.280 - List<Object> li = new ArrayList<Object>();
52.281 - li.addAll (Arrays.asList (INSTANCES));
52.282 - ic.set (li, null);
52.283 -
52.284 - Lookup.Result<Integer> res = lookup.lookupResult(Integer.class);
52.285 - Iterator<?> all = res.allInstances().iterator();
52.286 - checkIterator ("Integer is not there", all, Collections.nCopies (1, INSTANCES[0]));
52.287 -
52.288 - // change the pairs
52.289 - LL listener = new LL (res);
52.290 - res.addLookupListener (listener);
52.291 -
52.292 - List<Object> l2 = new ArrayList<Object>(li);
52.293 - l2.remove (INSTANCES[0]);
52.294 - ic.set (l2, null);
52.295 -
52.296 - all = lookup.lookupAll(Object.class).iterator();
52.297 - checkIterator ("The removed integer is not noticed", all, l2);
52.298 -
52.299 - if (listener.getCount () != 1) {
52.300 - fail ("Nothing has not been fired");
52.301 - }
52.302 - }
52.303 -
52.304 - /** Checks whether set pairs does not fire when they should not.
52.305 - */
52.306 - public void testSetPairsDoesNotFire () {
52.307 - Object tmp = new Object ();
52.308 -
52.309 - List<Object> li = new ArrayList<Object>();
52.310 - li.add (tmp);
52.311 - li.addAll (Arrays.asList (INSTANCES));
52.312 - ic.set (li, null);
52.313 -
52.314 - Lookup.Result<Integer> res = lookup.lookupResult(Integer.class);
52.315 - Iterator<?> all = res.allInstances ().iterator ();
52.316 - checkIterator ("Integer is not there", all, Collections.nCopies (1, INSTANCES[0]));
52.317 -
52.318 - // change the pairs
52.319 - LL listener = new LL (res);
52.320 - res.addLookupListener (listener);
52.321 -
52.322 - List<Object> l2 = new ArrayList<Object>(li);
52.323 - l2.remove (tmp);
52.324 - ic.set (l2, null);
52.325 -
52.326 - all = lookup.lookupAll(Object.class).iterator();
52.327 - checkIterator ("The removed integer is not noticed", all, l2);
52.328 -
52.329 - if (listener.getCount () != 0) {
52.330 - fail ("Something has been fired");
52.331 - }
52.332 - }
52.333 -
52.334 - /** Test whether after registration it is possible to find registered objects
52.335 - *
52.336 - */
52.337 - public void testLookupAndAdd () throws Exception {
52.338 - addInstances (INSTANCES);
52.339 -
52.340 - for (int i = 0; i < INSTANCES.length; i++) {
52.341 - Object obj = INSTANCES[i];
52.342 - findAll (lookup, obj.getClass (), true);
52.343 - }
52.344 - }
52.345 -
52.346 - /** Tries to find all classes and superclasses in the lookup.
52.347 - */
52.348 - private void findAll(Lookup lookup, Class<?> clazz, boolean shouldBeThere) {
52.349 - if (clazz == null) return;
52.350 -
52.351 - Object found = lookup.lookup (clazz);
52.352 - if (found == null) {
52.353 - if (shouldBeThere) {
52.354 - // should find at either instance or something else, but must
52.355 - // find at least something
52.356 - fail ("Lookup (" + clazz.getName () + ") found nothing");
52.357 - }
52.358 - } else {
52.359 - if (!shouldBeThere) {
52.360 - // should find at either instance or something else, but must
52.361 - // find at least something
52.362 - fail ("Lookup (" + clazz.getName () + ") found " + found);
52.363 - }
52.364 - }
52.365 -
52.366 - Lookup.Result<?> res = lookup.lookupResult(clazz);
52.367 - Collection<?> collection = res.allInstances();
52.368 -
52.369 - for (int i = 0; i < INSTANCES.length; i++) {
52.370 - boolean isSubclass = clazz.isInstance (INSTANCES[i]);
52.371 - boolean isThere = collection.contains (INSTANCES[i]);
52.372 -
52.373 - if (isSubclass != isThere) {
52.374 - // a problem found
52.375 - // should find at either instance or something else, but must
52.376 - // find at least something
52.377 - fail ("Lookup.Result (" + clazz.getName () + ") for " + INSTANCES[i] + " is subclass: " + isSubclass + " isThere: " + isThere);
52.378 - }
52.379 - }
52.380 -
52.381 - // go on for superclasses
52.382 -
52.383 - findAll (lookup, clazz.getSuperclass (), shouldBeThere);
52.384 -
52.385 - Class[] ies = clazz.getInterfaces ();
52.386 - for (int i = 0; i < ies.length; i++) {
52.387 - findAll (lookup, ies[i], shouldBeThere);
52.388 - }
52.389 - }
52.390 -
52.391 - /** Test if it is possible to remove a registered object. */
52.392 - public void testRemoveRegisteredObject() {
52.393 - Integer inst = new Integer(10);
52.394 -
52.395 - ic.add(inst);
52.396 - if (lookup.lookup(inst.getClass()) == null) {
52.397 - // should find an instance
52.398 - fail("Lookup (" + inst.getClass().getName () + ") found nothing");
52.399 - }
52.400 -
52.401 - ic.remove(inst);
52.402 - if (lookup.lookup(inst.getClass()) != null) {
52.403 - // should NOT find an instance
52.404 - fail("Lookup (" + inst.getClass().getName () +
52.405 - ") found an instance after remove operation");
52.406 - }
52.407 - }
52.408 -
52.409 - public void testCanReturnReallyStrangeResults () throws Exception {
52.410 - class QueryingPair extends AbstractLookup.Pair<Object> {
52.411 - private Integer i = 434;
52.412 -
52.413 - //
52.414 - // do the test
52.415 - //
52.416 -
52.417 - public void doTest () throws Exception {
52.418 - ic.add (i);
52.419 - ic.addPair (this);
52.420 -
52.421 - Object found = lookup.lookup (QueryingPair.class);
52.422 - assertEquals ("This object is found", this, found);
52.423 - }
52.424 -
52.425 -
52.426 - //
52.427 - // Implementation of pair
52.428 - //
52.429 -
52.430 - public String getId() {
52.431 - return getType ().toString();
52.432 - }
52.433 -
52.434 - public String getDisplayName() {
52.435 - return getId ();
52.436 - }
52.437 -
52.438 - public Class<?> getType() {
52.439 - return getClass ();
52.440 - }
52.441 -
52.442 - protected boolean creatorOf(Object obj) {
52.443 - return obj == this;
52.444 - }
52.445 -
52.446 - protected boolean instanceOf(Class<?> c) {
52.447 - assertEquals ("Integer found or exception is thrown", i, lookup.lookup (Integer.class));
52.448 - return c.isAssignableFrom(getType ());
52.449 - }
52.450 -
52.451 - public Object getInstance() {
52.452 - return this;
52.453 - }
52.454 -
52.455 -
52.456 - }
52.457 -
52.458 -
52.459 - QueryingPair qp = new QueryingPair ();
52.460 - qp.doTest ();
52.461 - }
52.462 -
52.463 - /** Test of firing events. */
52.464 - public void testLookupListener() {
52.465 - Object inst = 10;
52.466 - Lookup.Result<?> res = lookup.lookupResult(inst.getClass());
52.467 - res.allInstances ();
52.468 -
52.469 - LL listener = new LL(res);
52.470 - res.addLookupListener(listener);
52.471 -
52.472 - ic.add(inst);
52.473 - if (listener.getCount() == 0) {
52.474 - fail("None event fired during NbLookup.addPair()");
52.475 - }
52.476 -
52.477 - ic.remove(inst);
52.478 - if (listener.getCount() == 0) {
52.479 - fail("None event fired during NbLookup.removePair()");
52.480 - }
52.481 -
52.482 - ic.add(inst);
52.483 - if (listener.getCount() == 0) {
52.484 - fail("None event fired during second NbLookup.addPair()");
52.485 - }
52.486 -
52.487 - ic.remove(inst);
52.488 - if (listener.getCount() == 0) {
52.489 - fail("None event fired during second NbLookup.removePair()");
52.490 - }
52.491 - }
52.492 -
52.493 - /** Testing identity of the lookup.
52.494 - */
52.495 - public void testId () {
52.496 - Lookup.Template<?> templ;
52.497 - int cnt;
52.498 -
52.499 - addInstances (INSTANCES);
52.500 -
52.501 - Lookup.Result<?> res = lookup.lookupResult(Object.class);
52.502 - for (AbstractLookup.Item<?> item : res.allItems()) {
52.503 -
52.504 - templ = new Lookup.Template<Object>(null, item.getId(), null);
52.505 - cnt = lookup.lookup (templ).allInstances ().size ();
52.506 - if (cnt != 1) {
52.507 - fail ("Identity lookup failed. Instances = " + cnt);
52.508 - }
52.509 -
52.510 - templ = makeTemplate(item.getType(), item.getId());
52.511 - cnt = lookup.lookup (templ).allInstances ().size ();
52.512 - if (cnt != 1) {
52.513 - fail ("Identity lookup with type failed. Instances = " + cnt);
52.514 - }
52.515 -
52.516 - templ = makeTemplate(this.getClass(), item.getId());
52.517 - cnt = lookup.lookup (templ).allInstances ().size ();
52.518 - if (cnt != 0) {
52.519 - fail ("Identity lookup with wrong type failed. Instances = " + cnt);
52.520 - }
52.521 -
52.522 - templ = new Lookup.Template<Object>(null, null, item.getInstance());
52.523 - cnt = lookup.lookup (templ).allInstances ().size ();
52.524 - if (cnt != 1) {
52.525 - fail ("Instance lookup failed. Instances = " + cnt);
52.526 - }
52.527 -
52.528 - templ = new Lookup.Template<Object>(null, item.getId(), item.getInstance());
52.529 - cnt = lookup.lookup (templ).allInstances ().size ();
52.530 - if (cnt != 1) {
52.531 - fail ("Instance & identity lookup failed. Instances = " + cnt);
52.532 - }
52.533 -
52.534 - }
52.535 - }
52.536 - private static <T> Lookup.Template<T> makeTemplate(Class<T> clazz, String id) { // captures type parameter
52.537 - return new Lookup.Template<T>(clazz, id, null);
52.538 - }
52.539 -
52.540 - /** Tests adding and removing.
52.541 - */
52.542 - public void testAddAndRemove () throws Exception {
52.543 - Object map = new javax.swing.ActionMap ();
52.544 - LL ll = new LL ();
52.545 -
52.546 - Lookup.Result<?> res = lookup.lookupResult(map.getClass());
52.547 - res.allItems();
52.548 - res.addLookupListener (ll);
52.549 - ll.source = res;
52.550 -
52.551 - ic.add (map);
52.552 -
52.553 - assertEquals ("First change when adding", ll.getCount (), 1);
52.554 -
52.555 - ic.remove (map);
52.556 -
52.557 - assertEquals ("Second when removing", ll.getCount (), 1);
52.558 -
52.559 - ic.add (map);
52.560 -
52.561 - assertEquals ("Third when readding", ll.getCount (), 1);
52.562 -
52.563 - ic.remove (map);
52.564 -
52.565 - assertEquals ("Forth when reremoving", ll.getCount (), 1);
52.566 -
52.567 - }
52.568 -
52.569 - /** Will a class garbage collect even it is registered in lookup.
52.570 - */
52.571 - public void testGarbageCollect () throws Exception {
52.572 - ClassLoader l = new CL ();
52.573 - Class<?> c = l.loadClass(Garbage.class.getName());
52.574 - Reference<?> ref = new WeakReference<Object>(c);
52.575 -
52.576 - lookup.lookup (c);
52.577 -
52.578 - // now test garbage collection
52.579 - c = null;
52.580 - l = null;
52.581 - impl.clearCaches ();
52.582 - assertGC ("The classloader has not been garbage collected!", ref);
52.583 - }
52.584 -
52.585 - /** Items are the same as results.
52.586 - */
52.587 - public void testItemsAndIntances () {
52.588 - addInstances (INSTANCES);
52.589 -
52.590 - Lookup.Result<Object> r = lookup.lookupResult(Object.class);
52.591 - Collection<? extends Lookup.Item<?>> items = r.allItems();
52.592 - Collection<?> insts = r.allInstances();
52.593 -
52.594 - if (items.size () != insts.size ()) {
52.595 - fail ("Different size of sets");
52.596 - }
52.597 -
52.598 - for (Lookup.Item<?> item : items) {
52.599 - if (!insts.contains (item.getInstance ())) {
52.600 - fail ("Intance " + item.getInstance () + " is missing in " + insts);
52.601 - }
52.602 - }
52.603 - }
52.604 -
52.605 - /** Checks search for interface.
52.606 - */
52.607 - public void testSearchForInterface () {
52.608 - Lookup.Template<Serializable> t = new Lookup.Template<Serializable>(Serializable.class, null, null);
52.609 -
52.610 - assertNull("Nothing to find", lookup.lookupItem (t));
52.611 -
52.612 - Serializable s = new Serializable () {};
52.613 - ic.add (s);
52.614 -
52.615 - Lookup.Item item = lookup.lookupItem (t);
52.616 - assertNotNull ("Something found", item);
52.617 - }
52.618 -
52.619 - /** Test to add broken item if it incorrectly answers instanceOf questions.
52.620 - */
52.621 - public void testIncorectInstanceOf40364 () {
52.622 - final Long sharedLong = new Long (0);
52.623 -
52.624 - class P extends AbstractLookup.Pair<Object> {
52.625 - public boolean isLong;
52.626 -
52.627 - P (boolean b) {
52.628 - isLong = b;
52.629 - }
52.630 -
52.631 - protected boolean creatorOf (Object obj) {
52.632 - return obj == sharedLong;
52.633 - }
52.634 -
52.635 - public String getDisplayName () {
52.636 - return "";
52.637 - }
52.638 -
52.639 - public String getId () {
52.640 - return "";
52.641 - }
52.642 -
52.643 - public Object getInstance () {
52.644 - return sharedLong;
52.645 - }
52.646 -
52.647 - public Class<?> getType() {
52.648 - return isLong ? Long.class : Number.class;
52.649 - }
52.650 -
52.651 - protected boolean instanceOf(Class<?> c) {
52.652 - return c.isAssignableFrom (getType ());
52.653 - }
52.654 -
52.655 - public @Override int hashCode() {
52.656 - return getClass ().hashCode ();
52.657 - }
52.658 -
52.659 - public @Override boolean equals(Object obj) {
52.660 - return obj != null && getClass ().equals (obj.getClass ());
52.661 - }
52.662 - }
52.663 -
52.664 - // to create the right structure in the lookup
52.665 - lookup.lookup (Object.class);
52.666 - lookup.lookup (Long.class);
52.667 - lookup.lookup (Number.class);
52.668 -
52.669 - P lng1 = new P (true);
52.670 - ic.addPair (lng1);
52.671 -
52.672 - P lng2 = new P (false);
52.673 - ic.setPairs (Collections.singleton (lng2));
52.674 -
52.675 - Collection<? extends Lookup.Item<?>> res = lookup.lookupResult(Object.class).allItems();
52.676 - assertEquals ("Just one pair", 1, res.size ());
52.677 - }
52.678 -
52.679 - public void testAbsolutelyCrazyWayToSimulateIssue48590ByChangingTheBehaviourOfEqualOnTheFly () throws Exception {
52.680 - class X implements TestInterfaceInheritanceA, TestInterfaceInheritanceB {
52.681 - }
52.682 - final X shared = new X ();
52.683 -
52.684 - class P extends AbstractLookup.Pair<Object> {
52.685 - public int howLong;
52.686 -
52.687 - P (int b) {
52.688 - howLong = b;
52.689 - }
52.690 -
52.691 - protected boolean creatorOf (Object obj) {
52.692 - return obj == shared;
52.693 - }
52.694 -
52.695 - public String getDisplayName () {
52.696 - return "";
52.697 - }
52.698 -
52.699 - public String getId () {
52.700 - return "";
52.701 - }
52.702 -
52.703 - public Object getInstance () {
52.704 - return shared;
52.705 - }
52.706 -
52.707 - public Class<?> getType() {
52.708 - return howLong == 0 ? TestInterfaceInheritanceB.class : TestInterfaceInheritanceA.class;
52.709 - }
52.710 -
52.711 - protected boolean instanceOf(Class<?> c) {
52.712 - return c.isAssignableFrom (getType ());
52.713 - }
52.714 -
52.715 - public @Override int hashCode() {
52.716 - return getClass ().hashCode ();
52.717 - }
52.718 -
52.719 - public @Override boolean equals(Object obj) {
52.720 - if (obj instanceof P) {
52.721 - P p = (P)obj;
52.722 - if (this.howLong > 0) {
52.723 - this.howLong--;
52.724 - return false;
52.725 - }
52.726 - if (p.howLong > 0) {
52.727 - p.howLong--;
52.728 - return false;
52.729 - }
52.730 - return getClass ().equals (p.getClass ());
52.731 - }
52.732 - return false;
52.733 - }
52.734 - }
52.735 -
52.736 - // to create the right structure in the lookup
52.737 - Lookup.Result<?> a = lookup.lookupResult(TestInterfaceInheritanceA.class);
52.738 - Lookup.Result<?> b = lookup.lookupResult(TestInterfaceInheritanceB.class);
52.739 -
52.740 - P lng1 = new P (0);
52.741 - ic.addPair (lng1);
52.742 -
52.743 - assertEquals ("One in a", 1, a.allItems ().size ());
52.744 - assertEquals ("One in b", 1, b.allItems ().size ());
52.745 -
52.746 - P lng2 = new P (1);
52.747 -
52.748 -
52.749 - /* Following call used to generate this exception:
52.750 - java.lang.IllegalStateException: Duplicate pair in treePair1: pair2: index1: 0 index2: 0 item1: org.openide.util.lookup.AbstractLookupBaseHid$1X@1a457b6 item2: org.openide.util.lookup.AbstractLookupBaseHid$1X@1a457b6 id1: 7a78d3 id2: 929206
52.751 - at org.openide.util.lookup.ALPairComparator.compare(ALPairComparator.java:52)
52.752 - at java.util.Arrays.mergeSort(Arrays.java:1284)
52.753 - at java.util.Arrays.sort(Arrays.java:1223)
52.754 - at java.util.Collections.sort(Collections.java:159)
52.755 - at org.openide.util.lookup.InheritanceTree.retainAllInterface(InheritanceTree.java:753)
52.756 - at org.openide.util.lookup.InheritanceTree.retainAll(InheritanceTree.java:183)
52.757 - at org.openide.util.lookup.DelegatingStorage.retainAll(DelegatingStorage.java:83)
52.758 - at org.openide.util.lookup.AbstractLookup.setPairsAndCollectListeners(AbstractLookup.java:238)
52.759 - at org.openide.util.lookup.AbstractLookup.setPairs(AbstractLookup.java:203)
52.760 - at org.openide.util.lookup.AbstractLookup$Content.setPairs(AbstractLookup.java:885)
52.761 - at org.openide.util.lookup.AbstractLookupBaseHid.testAbsolutelyCrazyWayToSimulateIssue48590ByChangingTheBehaviourOfEqualOnTheFly(AbstractLookupBaseHid.java:696)
52.762 - at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
52.763 - at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
52.764 - at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
52.765 - at org.netbeans.junit.NbTestCase.run(NbTestCase.java:119)
52.766 - */
52.767 - ic.setPairs (Collections.singleton (lng2));
52.768 -
52.769 -
52.770 - }
52.771 -
52.772 - public void testInstancesArePreservedFoundWhenFixing48590 () throws Exception {
52.773 - class X implements Runnable, Serializable {
52.774 - public void run () {
52.775 -
52.776 - }
52.777 -
52.778 - public void assertOnlyMe (String msg, Lookup.Result<?> res) {
52.779 - Collection<?> col = res.allInstances();
52.780 - assertEquals (msg + " just one", 1, col.size ());
52.781 - assertSame (msg + " and it is me", this, col.iterator ().next ());
52.782 - }
52.783 - }
52.784 -
52.785 - Lookup.Result<?> runnable = lookup.lookupResult(Runnable.class);
52.786 - Lookup.Result<?> serial = lookup.lookupResult(Serializable.class);
52.787 -
52.788 -
52.789 - X x = new X ();
52.790 - ic.add (x);
52.791 -
52.792 -
52.793 - x.assertOnlyMe ("x implements it (1)", runnable);
52.794 - x.assertOnlyMe ("x implements it (2)", serial);
52.795 -
52.796 - ic.set (Collections.singleton (x), null);
52.797 -
52.798 - x.assertOnlyMe ("x implements it (3)", runnable);
52.799 - x.assertOnlyMe ("x implements it (4)", serial);
52.800 - }
52.801 -
52.802 - /** Testing lookup of inherited classes. */
52.803 - public void testInheritance() {
52.804 - class A {}
52.805 - class B extends A implements java.rmi.Remote {}
52.806 - class BB extends B {}
52.807 - class C extends A implements java.rmi.Remote {}
52.808 - class D extends A {}
52.809 -
52.810 - A[] types = {new B(), new BB(), new C(), new D()};
52.811 -
52.812 - for (int i = 0; i < types.length; i++) {
52.813 - ic.add(types[i]);
52.814 - if (lookup.lookup(types[i].getClass()) == null) {
52.815 - // should find an instance
52.816 - fail("Lookup (" + types[i].getClass().getName () + ") found nothing");
52.817 - }
52.818 - }
52.819 -
52.820 - int size1, size2;
52.821 -
52.822 - //interface query
52.823 - size1 = lookup.lookupAll(java.rmi.Remote.class).size();
52.824 - size2 = countInstances(types, java.rmi.Remote.class);
52.825 -
52.826 - if (size1 != size2) fail("Lookup with interface failed: " + size1 + " != " + size2);
52.827 -
52.828 - // superclass query
52.829 - size1 = lookup.lookupAll(A.class).size();
52.830 - size2 = countInstances(types, A.class);
52.831 -
52.832 - if (size1 != size2) fail("Lookup with superclass failed: " + size1 + " != " + size2);
52.833 - }
52.834 -
52.835 - /** Test interface inheritance.
52.836 - */
52.837 - public void testInterfaceInheritance() {
52.838 - TestInterfaceInheritanceA[] types = {
52.839 - new TestInterfaceInheritanceB() {},
52.840 - new TestInterfaceInheritanceBB() {},
52.841 - new TestInterfaceInheritanceC() {},
52.842 - new TestInterfaceInheritanceD() {}
52.843 - };
52.844 -
52.845 - for (int i = 0; i < types.length; i++) {
52.846 - ic.add(types[i]);
52.847 - if (lookup.lookup(types[i].getClass()) == null) {
52.848 - // should find an instance
52.849 - fail("Lookup (" + types[i].getClass().getName () + ") found nothing");
52.850 - }
52.851 - }
52.852 -
52.853 - int size1, size2;
52.854 -
52.855 - //interface query
52.856 - LL l = new LL ();
52.857 - Lookup.Result<?> res = lookup.lookupResult(java.rmi.Remote.class);
52.858 - l.source = res;
52.859 - size1 = res.allInstances().size();
52.860 - size2 = countInstances(types, java.rmi.Remote.class);
52.861 -
52.862 - if (size1 != size2) fail("Lookup with interface failed: " + size1 + " != " + size2);
52.863 -
52.864 - // superclass query
52.865 - size1 = lookup.lookupAll(TestInterfaceInheritanceA.class).size();
52.866 - size2 = countInstances(types, TestInterfaceInheritanceA.class);
52.867 -
52.868 - if (size1 != size2) fail("Lookup with superclass failed: " + size1 + " != " + size2);
52.869 -
52.870 - res.addLookupListener (l);
52.871 - ic.remove (types[0]);
52.872 -
52.873 - if (l.getCount () != 1) {
52.874 - fail ("No notification that a Remote is removed");
52.875 - }
52.876 - }
52.877 -
52.878 - /** Checks whether the AbstractLookup is guarded against modifications
52.879 - * while doing some kind of modification.
52.880 - */
52.881 - public void testModificationArePreventedWhenDoingModifications () throws Exception {
52.882 - BrokenPair broken = new BrokenPair (true, false);
52.883 - ic.addPair (broken);
52.884 -
52.885 - Lookup.Template<BrokenPair> templ = new Lookup.Template<BrokenPair>(BrokenPair.class);
52.886 - Lookup.Item<BrokenPair> item = lookup.lookupItem (templ);
52.887 - assertEquals ("Broken is found", broken, item);
52.888 - }
52.889 -
52.890 - public void testModificationArePreventedWhenDoingModificationsResult () throws Exception {
52.891 - BrokenPair broken = new BrokenPair (false, true);
52.892 - ic.addPair (broken);
52.893 -
52.894 - Lookup.Template<BrokenPair> templ = new Lookup.Template<BrokenPair>(BrokenPair.class);
52.895 -
52.896 - Collection<? extends BrokenPair> c = lookup.lookup (templ).allInstances();
52.897 - assertEquals ("One item", 1, c.size ());
52.898 - assertEquals ("Broken is found again", broken, c.iterator().next ());
52.899 - }
52.900 -
52.901 - public void testModificationArePreventedWhenDoingModificationsItemAndResult () throws Exception {
52.902 - BrokenPair broken = new BrokenPair (false, true);
52.903 - ic.addPair (broken);
52.904 -
52.905 - Lookup.Template<BrokenPair> templ = new Lookup.Template<BrokenPair>(BrokenPair.class);
52.906 - Lookup.Item<BrokenPair> item = lookup.lookupItem (templ);
52.907 - assertEquals ("Broken is found", broken, item);
52.908 -
52.909 - Collection<? extends BrokenPair> c = lookup.lookup(templ).allInstances();
52.910 - assertEquals ("One item", 1, c.size ());
52.911 - assertEquals ("Broken is found again", broken, c.iterator().next ());
52.912 - }
52.913 -
52.914 - public void testModificationArePreventedWhenDoingModificationsResultAndItem () throws Exception {
52.915 - BrokenPair broken = new BrokenPair (false, true);
52.916 - ic.addPair (broken);
52.917 -
52.918 - Lookup.Template<BrokenPair> templ = new Lookup.Template<BrokenPair>(BrokenPair.class);
52.919 - Collection<? extends BrokenPair> c = lookup.lookup(templ).allInstances();
52.920 - assertEquals ("One item", 1, c.size ());
52.921 - assertEquals ("Broken is found again", broken, c.iterator().next ());
52.922 -
52.923 - Object item = lookup.lookupItem (templ);
52.924 - assertEquals ("Broken is found", broken, item);
52.925 - }
52.926 -
52.927 - public void testAddALotOfPairsIntoTheLookupOneByOne () throws Exception {
52.928 - Lookup.Result<Integer> res = lookup.lookupResult(Integer.class);
52.929 - for (int i = 0; i < 1000; i++) {
52.930 - ic.add(i);
52.931 - }
52.932 - assertEquals (
52.933 - "there is the right count",
52.934 - 1000,
52.935 - res.allItems().size ()
52.936 - );
52.937 - }
52.938 -
52.939 - public void testAddALotOfPairsIntoTheLookup () throws Exception {
52.940 - List<Integer> arr = new ArrayList<Integer>();
52.941 - for (int i = 0; i < 1000; i++) {
52.942 - arr.add(i);
52.943 - }
52.944 - ic.set (arr, null);
52.945 -
52.946 - assertEquals (
52.947 - "there is the right count",
52.948 - 1000,
52.949 - lookup.lookupResult(Integer.class).allItems().size()
52.950 - );
52.951 - }
52.952 -
52.953 -
52.954 - public void testDoubleAddIssue35274 () throws Exception {
52.955 - class P extends AbstractLookup.Pair<Object> {
52.956 - protected boolean creatorOf(Object obj) { return false; }
52.957 - public String getDisplayName() { return ""; }
52.958 - public String getId() { return ""; }
52.959 - public Object getInstance() { return null; }
52.960 - public Class<?> getType() { return Object.class; }
52.961 - protected boolean instanceOf(Class<?> c) { return c.isAssignableFrom(getType ()); }
52.962 - public @Override int hashCode() {return getClass().hashCode();}
52.963 - public @Override boolean equals(Object obj) {return getClass() == obj.getClass();}
52.964 - }
52.965 -
52.966 - P p = new P ();
52.967 -
52.968 - ic.addPair (p);
52.969 - ic.addPair (p);
52.970 -
52.971 - Lookup.Result<Object> result = lookup.lookupResult(Object.class);
52.972 - Collection res = result.allItems ();
52.973 - assertEquals ("One item there", 1, res.size ());
52.974 - assertTrue ("It is the p", p == res.iterator ().next ());
52.975 -
52.976 - P p2 = new P ();
52.977 - ic.addPair (p2);
52.978 -
52.979 - Reference<?> ref = new WeakReference<Object>(result);
52.980 - result = null;
52.981 - assertGC ("The result can disappear", ref);
52.982 -
52.983 - impl.clearCaches ();
52.984 -
52.985 - result = lookup.lookupResult(Object.class);
52.986 - res = result.allItems ();
52.987 - assertEquals ("One item is still there", 1, res.size ());
52.988 - assertTrue ("But the p2 replaced p", p2 == res.iterator ().next ());
52.989 -
52.990 - }
52.991 -
52.992 - /** Test for proper serialization.
52.993 - */
52.994 - public void testSerializationSupport () throws Exception {
52.995 - doSerializationSupport (1);
52.996 - }
52.997 - public void testDoubleSerializationSupport () throws Exception {
52.998 - doSerializationSupport (2);
52.999 - }
52.1000 -
52.1001 - private void doSerializationSupport (int count) throws Exception {
52.1002 - if (lookup instanceof Serializable) {
52.1003 - ic.addPair (new SerialPair ("1"));
52.1004 - ic.addPair (new SerialPair ("2"));
52.1005 - ic.addPair (new SerialPair ("3"));
52.1006 -
52.1007 - Lookup l = (Lookup)reserialize(lookup);
52.1008 -
52.1009 - assertEquals ("Able to answer simple query", "1", l.lookup (String.class));
52.1010 -
52.1011 - assertEquals ("Three objects there", 3, l.lookup (new Lookup.Template (String.class)).allInstances().size ());
52.1012 -
52.1013 - while (count-- > 0) {
52.1014 - l = (Lookup)reserialize(l);
52.1015 - }
52.1016 -
52.1017 - assertEquals ("Able to answer simple query", "1", l.lookup (String.class));
52.1018 -
52.1019 - assertEquals ("Three objects there", 3, l.lookup (new Lookup.Template (String.class)).allInstances().size ());
52.1020 - }
52.1021 - }
52.1022 -
52.1023 - /** When a lookup with two different versions of the same class
52.1024 - * get's serialized, the results may be very bad.
52.1025 - */
52.1026 - public void testSerializationOfTwoClassesWithTheSameName () throws Exception {
52.1027 - if (lookup instanceof Serializable) {
52.1028 - doTwoSerializedClasses (false, false);
52.1029 - }
52.1030 - }
52.1031 - public void testSerializationOfTwoClassesWithTheSameNameButQueryBeforeSave () throws Exception {
52.1032 - if (lookup instanceof Serializable) {
52.1033 - doTwoSerializedClasses (true, false);
52.1034 - }
52.1035 - }
52.1036 - public void testSerializationOfTwoClassesWithTheSameNameWithBroken () throws Exception {
52.1037 - if (lookup instanceof Serializable) {
52.1038 - doTwoSerializedClasses (false, true);
52.1039 - }
52.1040 - }
52.1041 - public void testSerializationOfTwoClassesWithTheSameNameButQueryBeforeSaveWithBroken () throws Exception {
52.1042 - if (lookup instanceof Serializable) {
52.1043 - doTwoSerializedClasses (true, true);
52.1044 - }
52.1045 - }
52.1046 -
52.1047 - private void doTwoSerializedClasses (boolean queryBeforeSerialization, boolean useBroken) throws Exception {
52.1048 - ClassLoader loader = new CL ();
52.1049 - Class c = loader.loadClass (Garbage.class.getName ());
52.1050 -
52.1051 - // in case of InheritanceTree it creates a slot for class Garbage
52.1052 - lookup.lookup(c);
52.1053 -
52.1054 - // but creates new instance and adds it into the lookup
52.1055 - // without querying for it
52.1056 - loader = new CL ();
52.1057 - c = loader.loadClass (Garbage.class.getName ());
52.1058 -
52.1059 - Object theInstance = c.newInstance ();
52.1060 -
52.1061 - ic.addPair (new SerialPair (theInstance));
52.1062 -
52.1063 - Broken2Pair broken = null;
52.1064 - if (useBroken) {
52.1065 - broken = new Broken2Pair ();
52.1066 - ic.addPair (broken);
52.1067 -
52.1068 - assertNull (
52.1069 - "We need to create the slot for the List as " +
52.1070 - "the Broken2Pair will ask for it after deserialization",
52.1071 - lookup.lookup (java.awt.List.class)
52.1072 - );
52.1073 - }
52.1074 -
52.1075 - if (queryBeforeSerialization) {
52.1076 - assertEquals ("Instance is found", theInstance, lookup.lookup (c));
52.1077 - }
52.1078 -
52.1079 - // replace the old lookup with new one
52.1080 - lookup = (Lookup)reserialize(lookup);
52.1081 -
52.1082 - Lookup.Result result = lookup.lookup (new Lookup.Template (Garbage.class));
52.1083 - assertEquals ("One item is the result", 1, result.allInstances ().size ());
52.1084 - Object r = result.allInstances ().iterator ().next ();
52.1085 - assertNotNull("A value is found", r);
52.1086 - assertEquals ("It is of the right class", Garbage.class, r.getClass());
52.1087 - }
52.1088 -
52.1089 - /** Test of reorder and item change which used to fail on interfaces.
52.1090 - */
52.1091 - public void testReoderingIssue13779 () throws Exception {
52.1092 - LinkedList arr = new LinkedList ();
52.1093 -
52.1094 - class R extends Exception implements Cloneable {
52.1095 - }
52.1096 - Object o1 = new R ();
52.1097 - Object o2 = new R ();
52.1098 - Object o3 = new R ();
52.1099 -
52.1100 - arr.add (o1);
52.1101 - arr.add (o2);
52.1102 -
52.1103 - ic.set (arr, null);
52.1104 -
52.1105 - Lookup.Result objectResult = lookup.lookup (new Lookup.Template (Exception.class));
52.1106 - Lookup.Result interfaceResult = lookup.lookup (new Lookup.Template (Cloneable.class));
52.1107 - objectResult.allItems ();
52.1108 - interfaceResult.allItems ();
52.1109 -
52.1110 - LL l1 = new LL (objectResult);
52.1111 - LL l2 = new LL (interfaceResult);
52.1112 -
52.1113 - objectResult.addLookupListener(l1);
52.1114 - interfaceResult.addLookupListener(l2);
52.1115 -
52.1116 - arr.addFirst (o3);
52.1117 -
52.1118 - ic.set (arr, null);
52.1119 -
52.1120 - assertEquals ("One change on objects", 1, l1.getCount ());
52.1121 - assertEquals ("One change on interfaces", 1, l2.getCount ());
52.1122 -
52.1123 - arr.addFirst (new Cloneable () { });
52.1124 - ic.set (arr, null);
52.1125 -
52.1126 - assertEquals ("No change on objects", 0, l1.getCount ());
52.1127 - assertEquals ("But one change on interfaces", 1, l2.getCount ());
52.1128 -
52.1129 - }
52.1130 -
52.1131 - public void testDeadlockBetweenProxyResultAndLookupIssue47772 () throws Exception {
52.1132 - final String myModule = "My Module";
52.1133 - ic.add (myModule);
52.1134 -
52.1135 - class MyProxy extends ProxyLookup {
52.1136 - public MyProxy () {
52.1137 - super (new Lookup[] { lookup });
52.1138 - }
52.1139 - }
52.1140 - final MyProxy my = new MyProxy ();
52.1141 -
52.1142 - final Lookup.Result allModules = my.lookup (new Lookup.Template (String.class));
52.1143 -
52.1144 - class PairThatNeedsInfoAboutModules extends AbstractLookup.Pair {
52.1145 - public String getDisplayName () {
52.1146 - return "Need a module";
52.1147 - }
52.1148 - public String getId () {
52.1149 - return getDisplayName ();
52.1150 - }
52.1151 - public Class getType () {
52.1152 - return Integer.class;
52.1153 - }
52.1154 - protected boolean instanceOf (Class c) {
52.1155 - if (c == Integer.class) {
52.1156 - synchronized (this) {
52.1157 - notifyAll ();
52.1158 - try {
52.1159 - wait (1000);
52.1160 - } catch (InterruptedException ex) {
52.1161 - fail (ex.getMessage ());
52.1162 - }
52.1163 - }
52.1164 - java.util.Collection coll = allModules.allInstances ();
52.1165 - assertEquals ("Size is 1", 1, coll.size ());
52.1166 - assertEquals ("My module is there", myModule, coll.iterator ().next ());
52.1167 - }
52.1168 - return c.isAssignableFrom (Integer.class);
52.1169 - }
52.1170 -
52.1171 - public Object getInstance () {
52.1172 - return new Integer (10);
52.1173 - }
52.1174 -
52.1175 - protected boolean creatorOf (Object obj) {
52.1176 - return new Integer (10).equals (obj);
52.1177 - }
52.1178 - }
52.1179 -
52.1180 - PairThatNeedsInfoAboutModules pair = new PairThatNeedsInfoAboutModules ();
52.1181 - ic.addPair (pair);
52.1182 -
52.1183 - synchronized (pair) {
52.1184 - class BlockInInstanceOf implements Runnable {
52.1185 - public void run () {
52.1186 - Integer i = my.lookup(Integer.class);
52.1187 - assertEquals (new Integer (10), i);
52.1188 - }
52.1189 - }
52.1190 - BlockInInstanceOf blk = new BlockInInstanceOf ();
52.1191 - Executors.newSingleThreadScheduledExecutor().schedule(blk, 0, TimeUnit.MICROSECONDS);
52.1192 - pair.wait ();
52.1193 - }
52.1194 -
52.1195 - java.util.Collection coll = allModules.allInstances ();
52.1196 - assertEquals ("Size is 1", 1, coll.size ());
52.1197 - assertEquals ("My module is there", myModule, coll.iterator ().next ());
52.1198 - }
52.1199 -
52.1200 - public void testAWayToGenerateProblem13779 () {
52.1201 - ic.add (new Integer (1));
52.1202 - ic.add (new Integer (2));
52.1203 - ic.add (new Integer (1));
52.1204 - ic.add (new Integer (2));
52.1205 -
52.1206 - Collection c = lookup.lookup (new Lookup.Template (Integer.class)).allInstances ();
52.1207 - assertEquals ("There are two objects", 2, c.size ());
52.1208 -
52.1209 - }
52.1210 -
52.1211 - /** Replacing items with different objects.
52.1212 - */
52.1213 - public void testReplacingObjectsDoesNotGenerateException () throws Exception {
52.1214 - LinkedList arr = new LinkedList ();
52.1215 -
52.1216 - class R extends Exception implements Cloneable {
52.1217 - }
52.1218 - arr.add (new R ());
52.1219 - arr.add (new R ());
52.1220 -
52.1221 - ic.set (arr, null);
52.1222 -
52.1223 - arr.clear();
52.1224 -
52.1225 - arr.add (new R ());
52.1226 - arr.add (new R ());
52.1227 -
52.1228 - ic.set (arr, null);
52.1229 - }
52.1230 -
52.1231 - public void testAfterDeserializationNoQueryIsPeformedOnAlreadyQueriedObjects() throws Exception {
52.1232 - if (! (lookup instanceof Serializable)) {
52.1233 - // well this test works only for serializable lookups
52.1234 - return;
52.1235 - }
52.1236 -
52.1237 - SerialPair my = new SerialPair ("no");
52.1238 - ic.addPair (my);
52.1239 -
52.1240 - Lookup.Result res = lookup.lookup (new Lookup.Template (String.class));
52.1241 - assertEquals ("One instance", 1, res.allInstances().size ());
52.1242 - assertEquals ("my.instanceOf called once", 1, my.countInstanceOf);
52.1243 -
52.1244 - Lookup serial = (Lookup)reserialize(lookup);
52.1245 -
52.1246 - Lookup.Result r2 = serial.lookup(new Lookup.Template(String.class));
52.1247 -
52.1248 - assertEquals ("One item", 1, r2.allItems ().size ());
52.1249 - Object one = r2.allItems().iterator().next ();
52.1250 - assertEquals ("The right class", SerialPair.class, one.getClass());
52.1251 - SerialPair p = (SerialPair)one;
52.1252 -
52.1253 - assertEquals ("p.instanceOf has not been queried", 0, p.countInstanceOf);
52.1254 - }
52.1255 -
52.1256 - /** Checks the iterator */
52.1257 - private <T> void checkIterator(String msg, Iterator<? extends T> it1, List<? extends T> list) {
52.1258 - int cnt = 0;
52.1259 - Iterator<? extends T> it2 = list.iterator();
52.1260 - while (it1.hasNext () && it2.hasNext ()) {
52.1261 - T n1 = it1.next();
52.1262 - T n2 = it2.next();
52.1263 -
52.1264 - if (n1 != n2) {
52.1265 - fail (msg + " iterator[" + cnt + "] = " + n1 + " but list[" + cnt + "] = " + n2);
52.1266 - }
52.1267 -
52.1268 - cnt++;
52.1269 - }
52.1270 -
52.1271 - if (it1.hasNext ()) {
52.1272 - fail ("Iterator has more elements than list");
52.1273 - }
52.1274 -
52.1275 - if (it2.hasNext ()) {
52.1276 - fail ("List has more elements than iterator");
52.1277 - }
52.1278 - }
52.1279 -
52.1280 -
52.1281 - public void testResultsAreUnmodifyableOrAtLeastTheyDoNotPropagateToCache() throws Exception {
52.1282 - String s = "Ahoj";
52.1283 -
52.1284 - ic.add(s);
52.1285 -
52.1286 - Lookup.Result res = lookup.lookup(new Template(String.class));
52.1287 -
52.1288 - for (int i = 1; i < 5; i++) {
52.1289 - Collection c1 = res.allInstances();
52.1290 - Collection c2 = res.allClasses();
52.1291 - Collection c3 = res.allItems();
52.1292 -
52.1293 - assertTrue(i + ": c1 has it", c1.contains(s));
52.1294 - assertTrue(i + ": c2 has it", c2.contains(s.getClass()));
52.1295 - assertEquals(i + ": c3 has one", 1, c3.size());
52.1296 - Lookup.Item item = (Lookup.Item) c3.iterator().next();
52.1297 - assertEquals(i + ": c3 has it", s, item.getInstance());
52.1298 -
52.1299 - try {
52.1300 - c1.remove(s);
52.1301 - assertEquals("No elements now", 0, c1.size());
52.1302 - } catch (UnsupportedOperationException ex) {
52.1303 - // ok, this need not be supported
52.1304 - }
52.1305 - try {
52.1306 - c2.remove(s.getClass());
52.1307 - assertEquals("No elements now", 0, c2.size());
52.1308 - } catch (UnsupportedOperationException ex) {
52.1309 - // ok, this need not be supported
52.1310 - }
52.1311 - try {
52.1312 - c3.remove(item);
52.1313 - assertEquals("No elements now", 0, c3.size());
52.1314 - } catch (UnsupportedOperationException ex) {
52.1315 - // ok, this need not be supported
52.1316 - }
52.1317 - }
52.1318 - }
52.1319 -
52.1320 - public void testSomeProblemWithDVBFrameworkSeemsToBeInLookup() {
52.1321 - for (int i = 0; i < 5; i++) {
52.1322 - ic.add(lookup);
52.1323 - assertEquals("Can be found", lookup, lookup.lookup(lookup.getClass()));
52.1324 - ic.set(Collections.EMPTY_LIST, null);
52.1325 - }
52.1326 - }
52.1327 -
52.1328 - public void testListeningAndQueryingByTwoListenersInstances() {
52.1329 - doListeningAndQueryingByTwoListeners(0);
52.1330 - }
52.1331 - public void testListeningAndQueryingByTwoListenersClasses() {
52.1332 - doListeningAndQueryingByTwoListeners(1);
52.1333 - }
52.1334 - public void testListeningAndQueryingByTwoListenersItems() {
52.1335 - doListeningAndQueryingByTwoListeners(2);
52.1336 - }
52.1337 -
52.1338 -
52.1339 - private void doListeningAndQueryingByTwoListeners(final int type) {
52.1340 - class L implements LookupListener {
52.1341 - Lookup.Result integer = lookup.lookup(new Template(Integer.class));
52.1342 - Lookup.Result number = lookup.lookup(new Template(Number.class));
52.1343 - Lookup.Result serial = lookup.lookup(new Template(Serializable.class));
52.1344 -
52.1345 - {
52.1346 - integer.addLookupListener(this);
52.1347 - number.addLookupListener(this);
52.1348 - serial.addLookupListener(this);
52.1349 - }
52.1350 -
52.1351 - int round;
52.1352 -
52.1353 - public void resultChanged(LookupEvent ev) {
52.1354 - Collection c1 = get(type, integer);
52.1355 - Collection c2 = get(type, number);
52.1356 - Collection c3 = get(type, serial);
52.1357 -
52.1358 - assertEquals("round " + round + " c1 vs. c2", c1, c2);
52.1359 - assertEquals("round " + round + " c1 vs. c3", c1, c3);
52.1360 - assertEquals("round " + round + " c2 vs. c3", c2, c3);
52.1361 -
52.1362 - round++;
52.1363 - }
52.1364 -
52.1365 - private Collection get(int type, Lookup.Result res) {
52.1366 - Collection c;
52.1367 - switch(type) {
52.1368 - case 0: c = res.allInstances(); break;
52.1369 - case 1: c = res.allClasses(); break;
52.1370 - case 2: c = res.allItems(); break;
52.1371 - default: c = null; fail("Type: " + type); break;
52.1372 - }
52.1373 -
52.1374 - assertNotNull(c);
52.1375 - return new ArrayList(c);
52.1376 - }
52.1377 - }
52.1378 -
52.1379 - L listener = new L();
52.1380 - listener.resultChanged(null);
52.1381 -
52.1382 - for(int i = 0; i < 100; i++) {
52.1383 - ic.add(new Integer(i));
52.1384 - }
52.1385 -
52.1386 - assertEquals("3x100+1 checks", 301, listener.round);
52.1387 - }
52.1388 -
52.1389 - public void testChangeOfNodeDoesNotFireChangeInActionMap() {
52.1390 - ActionMap am = new ActionMap();
52.1391 - Lookup s = Lookups.singleton(am);
52.1392 - doChangeOfNodeDoesNotFireChangeInActionMap(am, s, false, 0);
52.1393 - }
52.1394 - public void testChangeOfNodeDoesNotFireChangeInActionMapSimple() {
52.1395 - ActionMap am = new ActionMap();
52.1396 - Lookup s = Lookups.singleton(am);
52.1397 - doChangeOfNodeDoesNotFireChangeInActionMap(am, s, true, 0);
52.1398 - }
52.1399 -
52.1400 - public void testChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookupSimple() {
52.1401 - doChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup(true);
52.1402 - }
52.1403 -
52.1404 - public void testChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup() {
52.1405 - doChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup(false);
52.1406 - }
52.1407 - private void doChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup(boolean wrapBySimple) {
52.1408 - final ActionMap am = new ActionMap();
52.1409 -
52.1410 - class Before extends AbstractLookup {
52.1411 - public InstanceContent ic;
52.1412 - public Before() {
52.1413 - this(new InstanceContent());
52.1414 - }
52.1415 -
52.1416 - private Before(InstanceContent ic) {
52.1417 - super(ic);
52.1418 - this.ic = ic;
52.1419 - }
52.1420 -
52.1421 - protected @Override void beforeLookup(Template template) {
52.1422 - if (ic != null) {
52.1423 - ic.add(am);
52.1424 - ic = null;
52.1425 - }
52.1426 - }
52.1427 - }
52.1428 -
52.1429 - Before s = new Before();
52.1430 - doChangeOfNodeDoesNotFireChangeInActionMap(am, s, wrapBySimple, 1);
52.1431 -
52.1432 - assertNull("beforeLookup called once", s.ic);
52.1433 - }
52.1434 -
52.1435 - private void doChangeOfNodeDoesNotFireChangeInActionMap(final ActionMap am, Lookup actionMapLookup, final boolean wrapBySimple, int firstChange) {
52.1436 - Lookup[] lookups = { lookup, actionMapLookup };
52.1437 -
52.1438 - class Provider implements Lookup.Provider {
52.1439 - ProxyLookup delegate;
52.1440 - Lookup query;
52.1441 -
52.1442 - public Provider(Lookup[] arr) {
52.1443 - if (wrapBySimple) {
52.1444 - delegate = new ProxyLookup(arr);
52.1445 - query = Lookups.proxy(this);
52.1446 - } else {
52.1447 - query = delegate = new ProxyLookup(arr);
52.1448 - }
52.1449 - }
52.1450 -
52.1451 - public Lookup getLookup() {
52.1452 - return delegate;
52.1453 - }
52.1454 -
52.1455 - public void setLookups(Lookup... arr) {
52.1456 - if (wrapBySimple) {
52.1457 - delegate = new ProxyLookup(arr);
52.1458 - } else {
52.1459 - delegate.setLookups(arr);
52.1460 - }
52.1461 - }
52.1462 - }
52.1463 -
52.1464 - Provider p = new Provider(lookups);
52.1465 -
52.1466 - Lookup.Result res = p.query.lookup(new Lookup.Template(ActionMap.class));
52.1467 - LL ll = new LL();
52.1468 - res.addLookupListener(ll);
52.1469 -
52.1470 - Collection c = res.allInstances();
52.1471 - assertFalse("Has next", c.isEmpty());
52.1472 -
52.1473 - ActionMap am1 = (ActionMap)c.iterator().next();
52.1474 - assertEquals("Am is there", am, am1);
52.1475 -
52.1476 - assertEquals("Correct # of changes in first get", firstChange, ll.getCount());
52.1477 -
52.1478 - Object m1 = new InputMap();
52.1479 - Object m2 = new InputMap();
52.1480 -
52.1481 - ic.add(m1);
52.1482 - assertEquals("No change in ActionMap 1", 0, ll.getCount());
52.1483 - ic.set(Collections.singletonList(m2), null);
52.1484 - assertEquals("No change in ActionMap 2", 0, ll.getCount());
52.1485 - ic.add(m2);
52.1486 - assertEquals("No change in ActionMap 3", 0, ll.getCount());
52.1487 - p.setLookups(lookup, actionMapLookup, Lookup.EMPTY);
52.1488 - assertEquals("No change in ActionMap 4", 0, ll.getCount());
52.1489 -
52.1490 - ActionMap am2 = p.query.lookup(ActionMap.class);
52.1491 - assertEquals("Still the same action map", am, am2);
52.1492 -
52.1493 -
52.1494 - class Before extends AbstractLookup {
52.1495 - public InstanceContent ic;
52.1496 - public Before() {
52.1497 - this(new InstanceContent());
52.1498 - }
52.1499 -
52.1500 - private Before(InstanceContent ic) {
52.1501 - super(ic);
52.1502 - this.ic = ic;
52.1503 - }
52.1504 -
52.1505 - protected @Override void beforeLookup(Template template) {
52.1506 - if (ic != null) {
52.1507 - ic.add(am);
52.1508 - ic = null;
52.1509 - }
52.1510 - }
52.1511 - }
52.1512 -
52.1513 - Before s = new Before();
52.1514 -
52.1515 - // adding different Before, but returning the same instance
52.1516 - // this happens with metaInfServices lookup often, moreover
52.1517 - // it adds the instance in beforeLookup, which confuses a lot
52.1518 - p.setLookups(new Lookup[]{ lookup, new Before() });
52.1519 - assertEquals("No change in ActionMap 5", 0, ll.getCount());
52.1520 -
52.1521 -
52.1522 - }
52.1523 -
52.1524 - public void testTasklistsCase() throws Exception {
52.1525 - ic.remove(new Object());
52.1526 - }
52.1527 -
52.1528 -
52.1529 -
52.1530 - public void testMultipleListeners() {
52.1531 - Object object = new ImplementationObject();
52.1532 - ic.add(object);
52.1533 -
52.1534 - Listener[] listeners = new Listener[4];
52.1535 - Lookup.Result result = lookup.lookup(new Lookup.Template(LookupObject.class));
52.1536 - for(int i = 0; i < listeners.length; ++i) {
52.1537 - listeners[i] = new Listener();
52.1538 - result.addLookupListener(listeners[i]);
52.1539 - }
52.1540 - // initialize listening
52.1541 - result.allItems();
52.1542 -
52.1543 - ic.remove(object);
52.1544 -
52.1545 - // Apparently, only odd-numbered listeners get called when there are multiple LookupListeners on a result
52.1546 - //for(int i = 0; i < listeners.length; ++i) {
52.1547 - // System.out.println("Listener " + i + ": " + listeners[i].wasCalled());
52.1548 - //}
52.1549 - for(int i = 0; i < listeners.length; ++i) {
52.1550 - assertTrue("Listener " + i + " called", listeners[i].wasCalled());
52.1551 - }
52.1552 - }
52.1553 -
52.1554 - static Object reserialize(Object o) throws Exception {
52.1555 - ByteArrayOutputStream os = new ByteArrayOutputStream();
52.1556 - ObjectOutputStream oos = new ObjectOutputStream(os);
52.1557 - oos.writeObject(o);
52.1558 - oos.close();
52.1559 -
52.1560 - ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
52.1561 - ObjectInputStream ois = new ObjectInputStream(is);
52.1562 - return ois.readObject();
52.1563 - }
52.1564 -
52.1565 - private class Listener implements LookupListener {
52.1566 - private boolean listenerCalled = false;
52.1567 -
52.1568 - public void resultChanged(LookupEvent ev) {
52.1569 - listenerCalled = true;
52.1570 - }
52.1571 -
52.1572 - public boolean wasCalled() {
52.1573 - return listenerCalled;
52.1574 - }
52.1575 -
52.1576 - public void reset() {
52.1577 - listenerCalled = false;
52.1578 - }
52.1579 - }
52.1580 -
52.1581 - private interface LookupObject {}
52.1582 - private class ImplementationObject implements LookupObject {}
52.1583 - private class NullObject implements LookupObject {}
52.1584 -
52.1585 -
52.1586 - public void testReturnSomethingElseThenYouClaimYouWillReturn() {
52.1587 - class Liar extends AbstractLookup.Pair {
52.1588 - public Object obj;
52.1589 -
52.1590 - protected boolean instanceOf(Class c) {
52.1591 - return c.isAssignableFrom(String.class);
52.1592 - }
52.1593 -
52.1594 - protected boolean creatorOf(Object obj) {
52.1595 - return this.obj == obj;
52.1596 - }
52.1597 -
52.1598 - public Object getInstance() {
52.1599 - return this.obj;
52.1600 - }
52.1601 -
52.1602 - public Class getType() {
52.1603 - return String.class;
52.1604 - }
52.1605 -
52.1606 - public String getId() {
52.1607 - return String.class.getName();
52.1608 - }
52.1609 -
52.1610 - public String getDisplayName() {
52.1611 - return getId();
52.1612 - }
52.1613 - }
52.1614 -
52.1615 -
52.1616 - Liar l = new Liar();
52.1617 - l.obj = new Integer(5);
52.1618 -
52.1619 - this.ic.addPair(l);
52.1620 -
52.1621 - Collection c = lookup.lookup(new Lookup.Template(String.class)).allInstances();
52.1622 - assertTrue("It is empty: " + c, c.isEmpty());
52.1623 - }
52.1624 -
52.1625 - public void testCanProxyLookupHaveWrongResults() {
52.1626 - class L implements LookupListener {
52.1627 - ProxyLookup pl;
52.1628 - Lookup.Result<String> original;
52.1629 - Lookup.Result<String> wrapped;
52.1630 - boolean ok;
52.1631 -
52.1632 - public void test() {
52.1633 - pl = new ProxyLookup(lookup);
52.1634 - original = lookup.lookupResult(String.class);
52.1635 -
52.1636 - original.addLookupListener(this);
52.1637 -
52.1638 - wrapped = pl.lookupResult(String.class);
52.1639 -
52.1640 - assertEquals("Original empty", 0, original.allInstances().size());
52.1641 - assertEquals("Wrapped empty", 0, wrapped.allInstances().size());
52.1642 -
52.1643 - ic.add("Hello!");
52.1644 - }
52.1645 -
52.1646 - public void resultChanged(LookupEvent ev) {
52.1647 - ok = true;
52.1648 -
52.1649 - assertEquals("Original has hello", 1, original.allInstances().size());
52.1650 - assertEquals("Wrapped has hello", 1, wrapped.allInstances().size());
52.1651 - }
52.1652 -
52.1653 - }
52.1654 - L listener = new L();
52.1655 - listener.test();
52.1656 - assertTrue("Listener called", listener.ok);
52.1657 - }
52.1658 -
52.1659 - public void testObjectFromInstanceContentConverterDisappearsIfNotReferenced() {
52.1660 - Conv converter = new Conv("foo");
52.1661 - ic.add (converter, converter);
52.1662 - Lookup lkp = instanceLookup;
52.1663 - StringBuilder sb = lookup.lookup (StringBuilder.class);
52.1664 - assertNotNull (sb);
52.1665 - int hash = System.identityHashCode(sb);
52.1666 - assertEquals ("foo", sb.toString());
52.1667 - Reference<StringBuilder> r = new WeakReference<StringBuilder>(sb);
52.1668 - sb = null;
52.1669 - assertGC("Lookup held onto object", r);
52.1670 - sb = lookup.lookup (StringBuilder.class);
52.1671 - assertNotSame(hash, System.identityHashCode(sb));
52.1672 - r = new WeakReference<StringBuilder>(sb);
52.1673 - sb = null;
52.1674 - assertGC("Lookup held onto object", r);
52.1675 - ic.remove (converter, converter);
52.1676 - Reference <InstanceContent.Convertor> cref = new WeakReference<InstanceContent.Convertor>(converter);
52.1677 - converter = null;
52.1678 - assertGC("Converter still referenced", cref);
52.1679 -
52.1680 - sb = lkp.lookup(StringBuilder.class);
52.1681 - assertNull ("Converter removed from lookup, but object it " +
52.1682 - "created still present:'" + sb +"'", sb);
52.1683 - converter = new Conv("bar");
52.1684 - ic.add (converter, converter);
52.1685 - assertNotNull (lkp.lookup(StringBuilder.class));
52.1686 - assertEquals ("bar", lkp.lookup(StringBuilder.class).toString());
52.1687 - }
52.1688 -
52.1689 - private static class Conv implements InstanceContent.Convertor<Conv, StringBuilder> {
52.1690 - private final String str;
52.1691 - private Conv (String str) {
52.1692 - this.str = str;
52.1693 - }
52.1694 -
52.1695 - public StringBuilder convert(Conv obj) {
52.1696 - return new StringBuilder (str);
52.1697 - }
52.1698 -
52.1699 - public Class<? extends StringBuilder> type(Conv obj) {
52.1700 - return StringBuilder.class;
52.1701 - }
52.1702 -
52.1703 - public String id(Conv obj) {
52.1704 - return "Foo";
52.1705 - }
52.1706 -
52.1707 - public String displayName(Conv obj) {
52.1708 - return "Foo";
52.1709 - }
52.1710 - } // end of Conv
52.1711 -
52.1712 - public void testCanGCResults() throws Exception {
52.1713 - class L implements LookupListener {
52.1714 - int cnt;
52.1715 -
52.1716 - public void resultChanged(LookupEvent ev) {
52.1717 - cnt++;
52.1718 - }
52.1719 -
52.1720 - }
52.1721 - L listener1 = new L();
52.1722 - L listener2 = new L();
52.1723 -
52.1724 - Lookup.Result<String> res1 = this.instanceLookup.lookupResult(String.class);
52.1725 - Lookup.Result<String> res2 = this.lookup.lookupResult(String.class);
52.1726 -
52.1727 - assertEquals("Empty1", 0, res1.allItems().size());
52.1728 - assertEquals("Empty2", 0, res2.allItems().size());
52.1729 -
52.1730 - res1.addLookupListener(listener1);
52.1731 - res2.addLookupListener(listener2);
52.1732 -
52.1733 - addInstances(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
52.1734 - this.ic.add("Ahoj");
52.1735 -
52.1736 - assertEquals("Change1", 1, listener1.cnt);
52.1737 - assertEquals("Change2", 1, listener2.cnt);
52.1738 -
52.1739 - assertEquals("Full1", 1, res1.allItems().size());
52.1740 - assertEquals("Full2", 1, res2.allItems().size());
52.1741 -
52.1742 -
52.1743 - Reference<Object> ref2 = new WeakReference<Object>(res2);
52.1744 - res2 = null;
52.1745 - assertGC("Result can disappear", ref2);
52.1746 - }
52.1747 -
52.1748 - void beforeActualTest(String n) {
52.1749 - if (n.equals("testEqualsIsNotCalledTooMuch")) {
52.1750 - CntPair.cnt = 0;
52.1751 - CntPair.hashCnt = 0;
52.1752 - CntPair.instances = 0;
52.1753 - int how = 1000;
52.1754 -
52.1755 - for(int i = 0; i < how; i++) {
52.1756 - this.ic.addPair(new CntPair("x" + i));
52.1757 - }
52.1758 -
52.1759 - assertEquals("No equals called", 0, CntPair.cnt);
52.1760 - assertEquals("1000 instances ", how, CntPair.instances);
52.1761 - }
52.1762 - }
52.1763 -
52.1764 - public void testEqualsIsNotCalledTooMuch() throws Exception {
52.1765 - // most of the work done in beforeActualTest
52.1766 -
52.1767 - // desirable: assertEquals("no comparitions", 0, CntPair.cnt);
52.1768 - // works for InheritanceTree, but not for ArrayStorage, but array
52.1769 - // storages are generally small
52.1770 -
52.1771 - if (CntPair.cnt > 12000) {
52.1772 - fail("Too much comparitions " + CntPair.cnt);
52.1773 - }
52.1774 - if (CntPair.hashCnt > 40000) {
52.1775 - fail("Too much hashes: " + CntPair.hashCnt);
52.1776 - }
52.1777 -
52.1778 - assertEquals("instaces is enough", 1000, CntPair.instances);
52.1779 - }
52.1780 -
52.1781 - /** Adds instances to the instance lookup.
52.1782 - */
52.1783 - private void addInstances (Object... instances) {
52.1784 - for (int i = 0; i < instances.length; i++) {
52.1785 - ic.add(instances[i]);
52.1786 - }
52.1787 - }
52.1788 -
52.1789 - /** Count instances of clazz in an array. */
52.1790 - private int countInstances (Object[] objs, Class clazz) {
52.1791 - int count = 0;
52.1792 - for (int i = 0; i < objs.length; i++) {
52.1793 - if (clazz.isInstance(objs[i])) count++;
52.1794 - }
52.1795 - return count;
52.1796 - }
52.1797 -
52.1798 - /** Counting listener */
52.1799 - protected static class LL implements LookupListener {
52.1800 - private int count = 0;
52.1801 - public Object source;
52.1802 - public Thread changesIn;
52.1803 -
52.1804 - public LL () {
52.1805 - this (null);
52.1806 - }
52.1807 -
52.1808 - public LL (Object source) {
52.1809 - this.source = source;
52.1810 - }
52.1811 -
52.1812 - public void resultChanged(LookupEvent ev) {
52.1813 - if (changesIn != null) {
52.1814 - assertEquals("Changes in the same thread", changesIn, Thread.currentThread());
52.1815 - } else {
52.1816 - changesIn = Thread.currentThread();
52.1817 - }
52.1818 - ++count;
52.1819 - if (source != null) {
52.1820 - assertSame ("Source is the same", source, ev.getSource ());
52.1821 -// assertSame ("Result is the same", source, ev.getResult ());
52.1822 - }
52.1823 - }
52.1824 -
52.1825 - public int getCount() {
52.1826 - int i = count;
52.1827 - count = 0;
52.1828 - return i;
52.1829 - }
52.1830 - };
52.1831 -
52.1832 - /** A set of interfaces for testInterfaceInheritance
52.1833 - */
52.1834 - interface TestInterfaceInheritanceA {}
52.1835 - interface TestInterfaceInheritanceB extends TestInterfaceInheritanceA, java.rmi.Remote {}
52.1836 - interface TestInterfaceInheritanceBB extends TestInterfaceInheritanceB {}
52.1837 - interface TestInterfaceInheritanceC extends TestInterfaceInheritanceA, java.rmi.Remote {}
52.1838 - interface TestInterfaceInheritanceD extends TestInterfaceInheritanceA {}
52.1839 -
52.1840 - /** A special class for garbage test */
52.1841 - public static final class Garbage extends Object implements Serializable {
52.1842 - static final long serialVersionUID = 435340912534L;
52.1843 - }
52.1844 -
52.1845 -
52.1846 - /* A classloader that can load one class in a special way */
52.1847 - private static class CL extends ClassLoader {
52.1848 - public CL () {
52.1849 - super (null);
52.1850 - }
52.1851 -
52.1852 - public @Override Class findClass(String name) throws ClassNotFoundException {
52.1853 - if (name.equals (Garbage.class.getName ())) {
52.1854 - String n = name.replace ('.', '/');
52.1855 - java.io.InputStream is = getClass ().getResourceAsStream ("/" + n + ".class");
52.1856 - byte[] arr = new byte[8096];
52.1857 - try {
52.1858 - int cnt = is.read (arr);
52.1859 - if (cnt == arr.length) {
52.1860 - fail ("Buffer to load the class is not big enough");
52.1861 - }
52.1862 -
52.1863 - return defineClass (name, arr, 0, cnt);
52.1864 - } catch (java.io.IOException ex) {
52.1865 - ex.printStackTrace();
52.1866 - fail ("IO Exception");
52.1867 - return null;
52.1868 - }
52.1869 - } else {
52.1870 - return null;
52.1871 - }
52.1872 - }
52.1873 -
52.1874 - /** Convert obj to other object. There is no need to implement
52.1875 - * cache mechanism. It is provided by AbstractLookup.Item.getInstance().
52.1876 - * Method should be called more than once because Lookup holds
52.1877 - * just weak reference.
52.1878 - */
52.1879 - public Object convert(Object obj) {
52.1880 - return null;
52.1881 - }
52.1882 -
52.1883 - /** Return type of converted object. */
52.1884 - public Class type(Object obj) {
52.1885 - try {
52.1886 - return loadClass (Garbage.class.getName ());
52.1887 - } catch (ClassNotFoundException ex) {
52.1888 - fail ("Class not found");
52.1889 - throw new InternalError ();
52.1890 - }
52.1891 - }
52.1892 - }
52.1893 -
52.1894 - private static final class CntPair extends AbstractLookup.Pair {
52.1895 - private static int instances;
52.1896 - private String txt;
52.1897 -
52.1898 - public CntPair(String txt) {
52.1899 - this.txt = txt;
52.1900 - instances++;
52.1901 - }
52.1902 -
52.1903 - public static int hashCnt;
52.1904 - @Override
52.1905 - public int hashCode() {
52.1906 - hashCnt++;
52.1907 - return txt.hashCode() + 3777;
52.1908 - }
52.1909 -
52.1910 - public static int cnt;
52.1911 - @Override
52.1912 - public boolean equals(Object obj) {
52.1913 - cnt++;
52.1914 -
52.1915 - if (obj == null) {
52.1916 - return false;
52.1917 - }
52.1918 - if (getClass() != obj.getClass()) {
52.1919 - return false;
52.1920 - }
52.1921 - final CntPair other = (CntPair) obj;
52.1922 - if (this.txt != other.txt && (this.txt == null || !this.txt.equals(other.txt))) {
52.1923 - return false;
52.1924 - }
52.1925 - return true;
52.1926 - }
52.1927 -
52.1928 - protected boolean instanceOf(Class c) {
52.1929 - return c.isAssignableFrom(String.class);
52.1930 - }
52.1931 -
52.1932 - protected boolean creatorOf(Object obj) {
52.1933 - return obj == txt;
52.1934 - }
52.1935 -
52.1936 - public Object getInstance() {
52.1937 - return txt;
52.1938 - }
52.1939 -
52.1940 - public Class getType() {
52.1941 - return String.class;
52.1942 - }
52.1943 -
52.1944 - public String getId() {
52.1945 - return txt;
52.1946 - }
52.1947 -
52.1948 - public String getDisplayName() {
52.1949 - return txt;
52.1950 - }
52.1951 -
52.1952 - }
52.1953 -
52.1954 - public static final class SerialPair extends AbstractLookup.Pair
52.1955 - implements java.io.Serializable {
52.1956 - static final long serialVersionUID = 54305834L;
52.1957 - private Object value;
52.1958 - public transient int countInstanceOf;
52.1959 -
52.1960 - public SerialPair (Object value) {
52.1961 - this.value = value;
52.1962 - }
52.1963 -
52.1964 - protected boolean creatorOf(Object obj) {
52.1965 - return obj == value;
52.1966 - }
52.1967 -
52.1968 - public String getDisplayName() {
52.1969 - return getId ();
52.1970 - }
52.1971 -
52.1972 - public String getId() {
52.1973 - return value.toString();
52.1974 - }
52.1975 -
52.1976 - public Object getInstance() {
52.1977 - return value;
52.1978 - }
52.1979 -
52.1980 - public Class getType() {
52.1981 - return value.getClass ();
52.1982 - }
52.1983 -
52.1984 - protected boolean instanceOf(Class c) {
52.1985 - countInstanceOf++;
52.1986 - return c.isInstance(value);
52.1987 - }
52.1988 - } // end of SerialPair
52.1989 -
52.1990 - private static class BrokenPair extends AbstractLookup.Pair {
52.1991 - private transient ThreadLocal IN = new ThreadLocal ();
52.1992 - private boolean checkModify;
52.1993 - private boolean checkQuery;
52.1994 -
52.1995 - public BrokenPair (boolean checkModify, boolean checkQuery) {
52.1996 - this.checkModify = checkModify;
52.1997 - this.checkQuery = checkQuery;
52.1998 - }
52.1999 -
52.2000 - protected boolean creatorOf(Object obj) { return this == obj; }
52.2001 - public String getDisplayName() { return "Broken"; }
52.2002 - public String getId() { return "broken"; }
52.2003 - public Object getInstance() { return this; }
52.2004 - public Class getType() { return getClass (); }
52.2005 - protected boolean instanceOf(Class c) {
52.2006 -
52.2007 - if (checkQuery) {
52.2008 - if (IN.get () == null) {
52.2009 - try {
52.2010 - IN.set (this);
52.2011 - // broken behaviour, tries to modify the lookup
52.2012 - // queries have to survive
52.2013 -
52.2014 - running.lookup.lookup (java.awt.List.class);
52.2015 -
52.2016 - //
52.2017 - // creation of new result has to survive as well
52.2018 - Lookup.Result myQuery = running.lookup.lookup (new Lookup.Template (java.awt.Button.class));
52.2019 - Collection all = myQuery.allItems ();
52.2020 - } finally {
52.2021 - IN.set (null);
52.2022 - }
52.2023 - }
52.2024 - }
52.2025 -
52.2026 -
52.2027 - if (checkModify) {
52.2028 - //
52.2029 - // modifications should fail
52.2030 - //
52.2031 -
52.2032 - try {
52.2033 - running.ic.addPair (new SerialPair (""));
52.2034 - fail ("Modification from a query should be prohibited");
52.2035 - } catch (IllegalStateException ex) {
52.2036 - }
52.2037 -
52.2038 - try {
52.2039 - running.ic.removePair (this);
52.2040 - fail ("This has to throw the exception");
52.2041 - } catch (IllegalStateException ex) {
52.2042 - }
52.2043 - try {
52.2044 - running.ic.setPairs (Collections.EMPTY_SET);
52.2045 - fail ("This has to throw the exception as well");
52.2046 - } catch (IllegalStateException ex) {
52.2047 - }
52.2048 - }
52.2049 -
52.2050 - return c.isAssignableFrom(getType ());
52.2051 - }
52.2052 - } // end of BrokenPair
52.2053 -
52.2054 - private static class Broken2Pair extends AbstractLookup.Pair {
52.2055 - static final long serialVersionUID = 4532587018501L;
52.2056 - public transient ThreadLocal IN;
52.2057 -
52.2058 - public Broken2Pair () {
52.2059 - }
52.2060 -
52.2061 - private void writeObject (java.io.ObjectOutputStream oos) throws java.io.IOException {
52.2062 - }
52.2063 -
52.2064 - private void readObject (java.io.ObjectInputStream ois) throws java.io.IOException, ClassNotFoundException {
52.2065 - IN = new ThreadLocal ();
52.2066 - }
52.2067 -
52.2068 - protected boolean creatorOf(Object obj) { return this == obj; }
52.2069 - public String getDisplayName() { return "Broken"; }
52.2070 - public String getId() { return "broken"; }
52.2071 - public Object getInstance() { return this; }
52.2072 - public Class getType() { return getClass (); }
52.2073 - protected boolean instanceOf(Class c) {
52.2074 -
52.2075 - // behaviour gets broken only after deserialization
52.2076 - if (IN != null && IN.get () == null) {
52.2077 - try {
52.2078 - IN.set (this);
52.2079 -
52.2080 - // creation of new result has to survive as well
52.2081 - Lookup.Result myQuery = running.lookup.lookup (new Lookup.Template (java.awt.List.class));
52.2082 - Collection all = myQuery.allItems ();
52.2083 - } finally {
52.2084 - IN.set (null);
52.2085 - }
52.2086 - }
52.2087 -
52.2088 - return c.isAssignableFrom(getType ());
52.2089 - }
52.2090 - } // end of Broken2Pair
52.2091 -}
53.1 --- a/lookup/src/test/java/org/openide/util/lookup/AbstractLookupExecutorTest.java Wed Jan 27 17:46:23 2010 -0500
53.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
53.3 @@ -1,98 +0,0 @@
53.4 -/*
53.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
53.6 - *
53.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
53.8 - *
53.9 - * The contents of this file are subject to the terms of either the GNU
53.10 - * General Public License Version 2 only ("GPL") or the Common
53.11 - * Development and Distribution License("CDDL") (collectively, the
53.12 - * "License"). You may not use this file except in compliance with the
53.13 - * License. You can obtain a copy of the License at
53.14 - * http://www.netbeans.org/cddl-gplv2.html
53.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
53.16 - * specific language governing permissions and limitations under the
53.17 - * License. When distributing the software, include this License Header
53.18 - * Notice in each file and include the License file at
53.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
53.20 - * particular file as subject to the "Classpath" exception as provided
53.21 - * by Sun in the GPL Version 2 section of the License file that
53.22 - * accompanied this code. If applicable, add the following below the
53.23 - * License Header, with the fields enclosed by brackets [] replaced by
53.24 - * your own identifying information:
53.25 - * "Portions Copyrighted [year] [name of copyright owner]"
53.26 - *
53.27 - * Contributor(s):
53.28 - *
53.29 - * The Original Software is NetBeans. The Initial Developer of the Original
53.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
53.31 - * Microsystems, Inc. All Rights Reserved.
53.32 - *
53.33 - * If you wish your version of this file to be governed by only the CDDL
53.34 - * or only the GPL Version 2, indicate your decision by adding
53.35 - * "[Contributor] elects to include this software in this distribution
53.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
53.37 - * single choice of license, a recipient has the option to distribute
53.38 - * your version of this file under either the CDDL, the GPL Version 2 or
53.39 - * to extend the choice of license to its licensees as provided above.
53.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
53.41 - * Version 2 license, then the option applies only if the new code is
53.42 - * made subject to such option by the copyright holder.
53.43 - */
53.44 -
53.45 -package org.openide.util.lookup;
53.46 -
53.47 -import java.util.concurrent.Executor;
53.48 -import org.openide.util.Lookup;
53.49 -import org.openide.util.LookupEvent;
53.50 -import org.openide.util.LookupListener;
53.51 -
53.52 -public class AbstractLookupExecutorTest extends AbstractLookupBaseHid
53.53 -implements AbstractLookupBaseHid.Impl, Executor, LookupListener {
53.54 - Lookup.Result<?> res;
53.55 -
53.56 -
53.57 - public AbstractLookupExecutorTest(java.lang.String testName) {
53.58 - super(testName, null);
53.59 - }
53.60 -
53.61 - //
53.62 - // Impl of AbstractLookupBaseHid.Impl
53.63 - //
53.64 -
53.65 - /** Creates the initial abstract lookup.
53.66 - */
53.67 - public Lookup createInstancesLookup (InstanceContent ic) {
53.68 - ic.attachExecutor(this);
53.69 - Lookup l = new AbstractLookup (ic, new InheritanceTree ());
53.70 - return l;
53.71 - }
53.72 -
53.73 - /** Creates an lookup for given lookup. This class just returns
53.74 - * the object passed in, but subclasses can be different.
53.75 - * @param lookup in lookup
53.76 - * @return a lookup to use
53.77 - */
53.78 - public Lookup createLookup (Lookup lookup) {
53.79 - res = lookup.lookupResult(Object.class);
53.80 - res.addLookupListener(this);
53.81 - return lookup;
53.82 - }
53.83 -
53.84 - public void clearCaches () {
53.85 - }
53.86 -
53.87 - ThreadLocal<Object> ME = new ThreadLocal<Object>();
53.88 - public void execute(Runnable command) {
53.89 - assertEquals("Not yet set", null, ME.get());
53.90 - ME.set(this);
53.91 - try {
53.92 - command.run();
53.93 - } finally {
53.94 - ME.set(null);
53.95 - }
53.96 - }
53.97 -
53.98 - public void resultChanged(LookupEvent ev) {
53.99 - assertEquals("Changes delivered only from execute method", this, ME.get());
53.100 - }
53.101 -}
54.1 --- a/lookup/src/test/java/org/openide/util/lookup/AbstractLookupMemoryTest.java Wed Jan 27 17:46:23 2010 -0500
54.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
54.3 @@ -1,158 +0,0 @@
54.4 -/*
54.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
54.6 - *
54.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
54.8 - *
54.9 - * The contents of this file are subject to the terms of either the GNU
54.10 - * General Public License Version 2 only ("GPL") or the Common
54.11 - * Development and Distribution License("CDDL") (collectively, the
54.12 - * "License"). You may not use this file except in compliance with the
54.13 - * License. You can obtain a copy of the License at
54.14 - * http://www.netbeans.org/cddl-gplv2.html
54.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
54.16 - * specific language governing permissions and limitations under the
54.17 - * License. When distributing the software, include this License Header
54.18 - * Notice in each file and include the License file at
54.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
54.20 - * particular file as subject to the "Classpath" exception as provided
54.21 - * by Sun in the GPL Version 2 section of the License file that
54.22 - * accompanied this code. If applicable, add the following below the
54.23 - * License Header, with the fields enclosed by brackets [] replaced by
54.24 - * your own identifying information:
54.25 - * "Portions Copyrighted [year] [name of copyright owner]"
54.26 - *
54.27 - * Contributor(s):
54.28 - *
54.29 - * The Original Software is NetBeans. The Initial Developer of the Original
54.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
54.31 - * Microsystems, Inc. All Rights Reserved.
54.32 - *
54.33 - * If you wish your version of this file to be governed by only the CDDL
54.34 - * or only the GPL Version 2, indicate your decision by adding
54.35 - * "[Contributor] elects to include this software in this distribution
54.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
54.37 - * single choice of license, a recipient has the option to distribute
54.38 - * your version of this file under either the CDDL, the GPL Version 2 or
54.39 - * to extend the choice of license to its licensees as provided above.
54.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
54.41 - * Version 2 license, then the option applies only if the new code is
54.42 - * made subject to such option by the copyright holder.
54.43 - */
54.44 -
54.45 -package org.openide.util.lookup;
54.46 -
54.47 -import java.util.*;
54.48 -import org.netbeans.junit.*;
54.49 -import org.netbeans.modules.openide.util.ActiveQueue;
54.50 -import org.openide.util.Lookup;
54.51 -
54.52 -/** Testing memory consumption of various AbstractLookup aspects.
54.53 - */
54.54 -public class AbstractLookupMemoryTest extends NbTestCase {
54.55 - public AbstractLookupMemoryTest(java.lang.String testName) {
54.56 - super(testName);
54.57 - }
54.58 -
54.59 - public static void main(java.lang.String[] args) {
54.60 - junit.textui.TestRunner.run(new NbTestSuite(AbstractLookupMemoryTest.class));
54.61 - }
54.62 -
54.63 - public void testEmptySize () {
54.64 - AbstractLookup instanceLookup = new AbstractLookup ();
54.65 - assertSize ("Empty lookup should be small", 16, instanceLookup);
54.66 -
54.67 - InstanceContent ic = new InstanceContent ();
54.68 - instanceLookup = new AbstractLookup (ic);
54.69 - assertSize ("Lookup with InstanceContent should be small as well", 16, instanceLookup);
54.70 - }
54.71 -
54.72 - public void testPairSize () {
54.73 - AbstractLookup.Pair pair = new EmptyPair ();
54.74 - assertSize ("Pair occupies only 16 bytes", 16, pair);
54.75 - }
54.76 -
54.77 - public void testPairWithOnePointerSize () {
54.78 - AbstractLookup.Pair pair = new OneItemPair ();
54.79 - assertSize ("Pair occupies only 16 bytes", 16, pair);
54.80 - }
54.81 -
54.82 - public void testLookupWithPairs () {
54.83 - Lookup.Template<Object> t = new Lookup.Template<Object>(Object.class);
54.84 - class L implements org.openide.util.LookupListener {
54.85 - public int cnt;
54.86 - public void resultChanged (org.openide.util.LookupEvent ev) {
54.87 - cnt++;
54.88 - }
54.89 - }
54.90 - L listener = new L ();
54.91 - L listener2 = new L ();
54.92 -
54.93 - EmptyPair[] pairs = {
54.94 - new EmptyPair(),
54.95 - new EmptyPair(),
54.96 - new EmptyPair(),
54.97 - new EmptyPair(),
54.98 - };
54.99 - Object[] ignore = {
54.100 - pairs[0],
54.101 - pairs[1],
54.102 - pairs[2],
54.103 - pairs[3],
54.104 - t,
54.105 - ActiveQueue.queue(),
54.106 - listener,
54.107 - listener2,
54.108 - new Integer (11) // trashhold is shared
54.109 - };
54.110 -
54.111 - AbstractLookup.Content c = new AbstractLookup.Content ();
54.112 - AbstractLookup l = new AbstractLookup (c, (Integer)ignore[ignore.length - 1]);
54.113 -
54.114 - c.addPair ((EmptyPair)ignore[0]);
54.115 - assertSize ("Should be really small (not counting the pair sizes)", Collections.singleton (l), 56, ignore);
54.116 -
54.117 - c.addPair ((EmptyPair)ignore[1]);
54.118 - assertSize ("Is bigger I guess (not counting the pair sizes)", Collections.singleton (l), 56, ignore);
54.119 -
54.120 - c.setPairs(Arrays.asList(pairs).subList(0, 3));
54.121 - assertSize ("Even bigger (not counting the pair sizes)", Collections.singleton (l), 64, ignore);
54.122 -
54.123 - c.setPairs(Arrays.asList(pairs).subList(0, 4));
54.124 - assertSize ("Now not that much(not counting the pair sizes)", Collections.singleton (l), 64, ignore);
54.125 -
54.126 - Lookup.Result res = l.lookup (t);
54.127 -
54.128 - assertSize ("After creating a result", Collections.singleton (l), 120, ignore);
54.129 -
54.130 - res.addLookupListener (listener);
54.131 -
54.132 - assertSize ("And attaching one listener", Collections.singleton (l), 120, ignore);
54.133 -
54.134 - res.addLookupListener (listener2);
54.135 - assertSize ("Second listener makes the situation much worse", Collections.singleton (l), 200, ignore);
54.136 - res.removeLookupListener(listener2);
54.137 - assertSize ("But removing it returns us back to original size", Collections.singleton (l), 120, ignore);
54.138 -
54.139 -
54.140 - assertEquals ("Current for pairs are in", res.allItems ().size (), 4); // also activates the listener
54.141 - assertSize ("and making the listener to work", Collections.singleton (l), 120, ignore);
54.142 -
54.143 - c.removePair ((EmptyPair)ignore[0]);
54.144 - assertEquals ("A changes has been delivered", 1, listener.cnt);
54.145 - }
54.146 -
54.147 - /** Simple pair with no data */
54.148 - private static class EmptyPair extends AbstractLookup.Pair {
54.149 - protected boolean creatorOf(Object obj) { return false; }
54.150 - public String getDisplayName() { return ""; }
54.151 - public String getId() { return ""; }
54.152 - public Object getInstance() { return null; }
54.153 - public Class getType() { return Object.class; }
54.154 - protected boolean instanceOf(Class c) { return c == getType (); }
54.155 - } // end of EmptyPair
54.156 -
54.157 - /** Pair with one item (like InstanceContent.Pair) */
54.158 - private static class OneItemPair extends EmptyPair {
54.159 - private Object pointer;
54.160 - }
54.161 -}
55.1 --- a/lookup/src/test/java/org/openide/util/lookup/AbstractLookupTest.java Wed Jan 27 17:46:23 2010 -0500
55.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
55.3 @@ -1,353 +0,0 @@
55.4 -/*
55.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
55.6 - *
55.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
55.8 - *
55.9 - * The contents of this file are subject to the terms of either the GNU
55.10 - * General Public License Version 2 only ("GPL") or the Common
55.11 - * Development and Distribution License("CDDL") (collectively, the
55.12 - * "License"). You may not use this file except in compliance with the
55.13 - * License. You can obtain a copy of the License at
55.14 - * http://www.netbeans.org/cddl-gplv2.html
55.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
55.16 - * specific language governing permissions and limitations under the
55.17 - * License. When distributing the software, include this License Header
55.18 - * Notice in each file and include the License file at
55.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
55.20 - * particular file as subject to the "Classpath" exception as provided
55.21 - * by Sun in the GPL Version 2 section of the License file that
55.22 - * accompanied this code. If applicable, add the following below the
55.23 - * License Header, with the fields enclosed by brackets [] replaced by
55.24 - * your own identifying information:
55.25 - * "Portions Copyrighted [year] [name of copyright owner]"
55.26 - *
55.27 - * Contributor(s):
55.28 - *
55.29 - * The Original Software is NetBeans. The Initial Developer of the Original
55.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
55.31 - * Microsystems, Inc. All Rights Reserved.
55.32 - *
55.33 - * If you wish your version of this file to be governed by only the CDDL
55.34 - * or only the GPL Version 2, indicate your decision by adding
55.35 - * "[Contributor] elects to include this software in this distribution
55.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
55.37 - * single choice of license, a recipient has the option to distribute
55.38 - * your version of this file under either the CDDL, the GPL Version 2 or
55.39 - * to extend the choice of license to its licensees as provided above.
55.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
55.41 - * Version 2 license, then the option applies only if the new code is
55.42 - * made subject to such option by the copyright holder.
55.43 - */
55.44 -
55.45 -package org.openide.util.lookup;
55.46 -
55.47 -import java.util.concurrent.ExecutionException;
55.48 -
55.49 -import java.lang.ref.WeakReference;
55.50 -import java.util.*;
55.51 -import java.util.concurrent.Executors;
55.52 -import java.util.concurrent.TimeUnit;
55.53 -import junit.framework.Test;
55.54 -import org.netbeans.junit.*;
55.55 -import org.openide.util.Lookup;
55.56 -import org.openide.util.lookup.AbstractLookup.Pair;
55.57 -
55.58 -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
55.59 -public class AbstractLookupTest extends AbstractLookupBaseHid implements AbstractLookupBaseHid.Impl {
55.60 - public AbstractLookupTest(java.lang.String testName) {
55.61 - super(testName, null);
55.62 - }
55.63 -
55.64 - //
55.65 - // Impl of AbstractLookupBaseHid.Impl
55.66 - //
55.67 -
55.68 - /** Creates the initial abstract lookup.
55.69 - */
55.70 - public Lookup createInstancesLookup (InstanceContent ic) {
55.71 - return new AbstractLookup (ic, new InheritanceTree ());
55.72 - }
55.73 -
55.74 - /** Creates an lookup for given lookup. This class just returns
55.75 - * the object passed in, but subclasses can be different.
55.76 - * @param lookup in lookup
55.77 - * @return a lookup to use
55.78 - */
55.79 - public Lookup createLookup (Lookup lookup) {
55.80 - return lookup;
55.81 - }
55.82 -
55.83 - public void clearCaches () {
55.84 - }
55.85 -
55.86 - static class LkpResultCanBeGargageCollectedAndClearsTheResult extends AbstractLookup {
55.87 - public int cleared;
55.88 - public int dirty;
55.89 -
55.90 - synchronized @Override boolean cleanUpResult(Template t) {
55.91 - boolean res = super.cleanUpResult (t);
55.92 - if (res) {
55.93 - cleared++;
55.94 - } else {
55.95 - dirty++;
55.96 - }
55.97 -
55.98 - notifyAll ();
55.99 -
55.100 - return res;
55.101 - }
55.102 - }
55.103 - public void testResultCanBeGargageCollectedAndClearsTheResult () throws Exception {
55.104 - LkpResultCanBeGargageCollectedAndClearsTheResult lkp = new LkpResultCanBeGargageCollectedAndClearsTheResult ();
55.105 - assertSize ("24 for AbstractLookup, 8 for two ints", 32, lkp);
55.106 - synchronized (lkp) {
55.107 - Lookup.Result res = lkp.lookup (new Lookup.Template (getClass ()));
55.108 - res.allItems();
55.109 -
55.110 - WeakReference ref = new WeakReference (res);
55.111 - res = null;
55.112 - assertGC ("Reference can get cleared", ref);
55.113 -
55.114 - // wait till we
55.115 - while (lkp.cleared == 0 && lkp.dirty == 0) {
55.116 - lkp.wait ();
55.117 - }
55.118 -
55.119 - assertEquals ("No dirty cleanups", 0, lkp.dirty);
55.120 - assertEquals ("One final cleanup", 1, lkp.cleared);
55.121 - }
55.122 - //assertSize ("Everything has been cleaned to original size", 32, lkp);
55.123 -
55.124 - }
55.125 -
55.126 - public void testPairCannotBeUsedInMoreThanOneLookupAtOnce () throws Exception {
55.127 - /** Simple pair with no data */
55.128 - class EmptyPair extends AbstractLookup.Pair {
55.129 - protected boolean creatorOf(Object obj) { return false; }
55.130 - public String getDisplayName() { return "Empty"; }
55.131 - public String getId() { return "empty"; }
55.132 - public Object getInstance() { return null; }
55.133 - public Class getType() { return Object.class; }
55.134 - protected boolean instanceOf(Class c) { return c == getType (); }
55.135 - } // end of EmptyPair
55.136 -
55.137 - AbstractLookup.Content c1 = new AbstractLookup.Content ();
55.138 - AbstractLookup.Content c2 = new AbstractLookup.Content ();
55.139 - AbstractLookup l1 = new AbstractLookup (c1);
55.140 - AbstractLookup l2 = new AbstractLookup (c2);
55.141 -
55.142 - EmptyPair empty = new EmptyPair ();
55.143 - c1.addPair (empty);
55.144 - Lookup.Result res = l1.lookup (new Lookup.Template (Object.class));
55.145 - assertEquals (
55.146 - "Pair is really found", empty,
55.147 - res.allItems ().iterator().next ()
55.148 - );
55.149 - try {
55.150 - c2.addPair (empty);
55.151 - fail ("It should not be possible to add pair to two lookups");
55.152 - } catch (IllegalStateException ex) {
55.153 - // ok, exception is fine
55.154 - }
55.155 - assertEquals (
55.156 - "L2 is still empty", Collections.EMPTY_LIST,
55.157 - new ArrayList (l2.lookup (new Lookup.Template (Object.class)).allItems ())
55.158 - );
55.159 - }
55.160 -
55.161 - public void testInitializationCanBeDoneFromAnotherThread () {
55.162 - class MyLkp extends AbstractLookup implements Runnable {
55.163 - private InstanceContent ic;
55.164 - private boolean direct;
55.165 -
55.166 - public MyLkp (boolean direct) {
55.167 - this (direct, new InstanceContent ());
55.168 - }
55.169 -
55.170 - private MyLkp (boolean direct, InstanceContent ic) {
55.171 - super (ic);
55.172 - this.direct = direct;
55.173 - this.ic = ic;
55.174 - }
55.175 -
55.176 - protected @Override void initialize() {
55.177 - if (direct) {
55.178 - run ();
55.179 - } else {
55.180 - try {
55.181 - Executors.newSingleThreadScheduledExecutor().schedule(this, 0, TimeUnit.MICROSECONDS).get();
55.182 - } catch (InterruptedException ex) {
55.183 - ex.printStackTrace();
55.184 - } catch (ExecutionException ex) {
55.185 - ex.printStackTrace();
55.186 - }
55.187 - }
55.188 - }
55.189 -
55.190 - public void run () {
55.191 - ic.add (this);
55.192 - ic.remove (this);
55.193 - ic.set (Collections.nCopies(10, this), null);
55.194 - ic.set (Collections.EMPTY_LIST, null);
55.195 - ic.add (AbstractLookupTest.this);
55.196 - }
55.197 - }
55.198 -
55.199 - assertEquals ("The test should be there", this, new MyLkp (true).lookup (Object.class));
55.200 - assertEquals ("and in async mode as well", this, new MyLkp (false).lookup (Object.class));
55.201 - }
55.202 -
55.203 - public void testBeforeLookupIsCalled () {
55.204 - class BeforeL extends AbstractLookup {
55.205 - public ArrayList list = new ArrayList ();
55.206 - public String toAdd;
55.207 - public InstanceContent ic;
55.208 -
55.209 - public BeforeL () {
55.210 - this (new InstanceContent ());
55.211 - }
55.212 -
55.213 - private BeforeL (InstanceContent c) {
55.214 - super (c);
55.215 - this.ic = c;
55.216 - }
55.217 -
55.218 - protected @Override void beforeLookup(Template t) {
55.219 - if (toAdd != null) {
55.220 - list.add (0, new SerialPair (toAdd));
55.221 - setPairs (list);
55.222 - } else {
55.223 - ic.add (new Integer (1));
55.224 - }
55.225 - }
55.226 - }
55.227 -
55.228 - BeforeL lookup = new BeforeL ();
55.229 -
55.230 - lookup.toAdd = "First";
55.231 - assertEquals ("First if found", "First", lookup.lookup (String.class));
55.232 -
55.233 - lookup.toAdd = "2";
55.234 - assertEquals ("2 is not first", "2", lookup.lookup (String.class));
55.235 -
55.236 - Lookup.Result res = lookup.lookup (new Lookup.Template (Object.class));
55.237 - for (int i = 3; i < 20; i++) {
55.238 - lookup.toAdd = String.valueOf (i);
55.239 - assertEquals (i + " items are now there", i, res.allInstances ().size ());
55.240 - }
55.241 - for (int i = 20; i < 35; i++) {
55.242 - lookup.toAdd = String.valueOf (i);
55.243 - assertEquals (i + " items are now there", i, res.allItems ().size ());
55.244 - }
55.245 -
55.246 - assertEquals ("Just strings are there now", 1, res.allClasses ().size ());
55.247 - lookup.toAdd = null; // this will add integer
55.248 - assertEquals ("Two classes now", 2, res.allClasses ().size ());
55.249 - }
55.250 -
55.251 - public void testInconsistentAfterDeserIssue71744() throws Exception {
55.252 - InheritanceTree inhTree = new InheritanceTree();
55.253 -
55.254 - AbstractLookup al = new AbstractLookup(new AbstractLookup.Content(), inhTree);
55.255 - {
55.256 -
55.257 - Collection r = al.lookup(new Lookup.Template(Integer.class)).allInstances();
55.258 - assertEquals("None", 0, r.size());
55.259 - }
55.260 -
55.261 - ICP item = new ICP(new Integer(10));
55.262 - al.addPair(item);
55.263 - al.removePair(item);
55.264 -
55.265 - AbstractLookup newLookup = (AbstractLookup)reserialize(al);
55.266 -
55.267 - newLookup.lookup(Number.class);
55.268 -
55.269 -
55.270 - newLookup.addPair(new ICP(new Long(20)));
55.271 -
55.272 - {
55.273 -
55.274 - Collection r = newLookup.lookup(new Lookup.Template(Number.class)).allInstances();
55.275 - assertEquals("one", 1, r.size());
55.276 -/*
55.277 - Iterator it = r.iterator();
55.278 - assertEquals(new Integer(10), it.next());
55.279 - assertEquals(new Long(20), it.next());*/
55.280 - }
55.281 - }
55.282 -
55.283 - public void testMatchesIssue130673() {
55.284 - class BrokenPairReturningNullID extends Pair<Object> {
55.285 - @Override
55.286 - protected boolean instanceOf(Class<?> c) {
55.287 - return false;
55.288 - }
55.289 -
55.290 - @Override
55.291 - protected boolean creatorOf(Object obj) {
55.292 - return false;
55.293 - }
55.294 -
55.295 - @Override
55.296 - public Object getInstance() {
55.297 - return null;
55.298 - }
55.299 -
55.300 - @Override
55.301 - public Class<? extends Object> getType() {
55.302 - return null;
55.303 - }
55.304 -
55.305 - @Override
55.306 - public String getId() {
55.307 - return null;
55.308 - }
55.309 -
55.310 - @Override
55.311 - public String getDisplayName() {
55.312 - return null;
55.313 - }
55.314 - }
55.315 - BrokenPairReturningNullID broken = new BrokenPairReturningNullID();
55.316 -
55.317 -
55.318 - Lookup.Template<String> t = new Lookup.Template<String>(String.class, "ID", null);
55.319 - boolean not = AbstractLookup.matches(t, broken, true);
55.320 - assertFalse("Does not match the template, but throws no exception", not);
55.321 - }
55.322 -
55.323 - private static final class ICP extends AbstractLookup.Pair {
55.324 - private Number s;
55.325 -
55.326 - public ICP (Number s) {
55.327 - this.s = s;
55.328 - }
55.329 -
55.330 -
55.331 - protected boolean instanceOf(Class c) {
55.332 - return c.isInstance(s);
55.333 - }
55.334 -
55.335 - protected boolean creatorOf(Object obj) {
55.336 - return s == obj;
55.337 - }
55.338 -
55.339 - public Object getInstance() {
55.340 - return s;
55.341 - }
55.342 -
55.343 - public Class getType() {
55.344 - return s.getClass();
55.345 - }
55.346 -
55.347 - public String getId() {
55.348 - return s.toString();
55.349 - }
55.350 -
55.351 - public String getDisplayName() {
55.352 - return getId();
55.353 - }
55.354 -
55.355 - }
55.356 -}
56.1 --- a/lookup/src/test/java/org/openide/util/lookup/ExcludingLookupTest.java Wed Jan 27 17:46:23 2010 -0500
56.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
56.3 @@ -1,228 +0,0 @@
56.4 -/*
56.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
56.6 - *
56.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
56.8 - *
56.9 - * The contents of this file are subject to the terms of either the GNU
56.10 - * General Public License Version 2 only ("GPL") or the Common
56.11 - * Development and Distribution License("CDDL") (collectively, the
56.12 - * "License"). You may not use this file except in compliance with the
56.13 - * License. You can obtain a copy of the License at
56.14 - * http://www.netbeans.org/cddl-gplv2.html
56.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
56.16 - * specific language governing permissions and limitations under the
56.17 - * License. When distributing the software, include this License Header
56.18 - * Notice in each file and include the License file at
56.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
56.20 - * particular file as subject to the "Classpath" exception as provided
56.21 - * by Sun in the GPL Version 2 section of the License file that
56.22 - * accompanied this code. If applicable, add the following below the
56.23 - * License Header, with the fields enclosed by brackets [] replaced by
56.24 - * your own identifying information:
56.25 - * "Portions Copyrighted [year] [name of copyright owner]"
56.26 - *
56.27 - * Contributor(s):
56.28 - *
56.29 - * The Original Software is NetBeans. The Initial Developer of the Original
56.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
56.31 - * Microsystems, Inc. All Rights Reserved.
56.32 - *
56.33 - * If you wish your version of this file to be governed by only the CDDL
56.34 - * or only the GPL Version 2, indicate your decision by adding
56.35 - * "[Contributor] elects to include this software in this distribution
56.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
56.37 - * single choice of license, a recipient has the option to distribute
56.38 - * your version of this file under either the CDDL, the GPL Version 2 or
56.39 - * to extend the choice of license to its licensees as provided above.
56.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
56.41 - * Version 2 license, then the option applies only if the new code is
56.42 - * made subject to such option by the copyright holder.
56.43 - */
56.44 -
56.45 -package org.openide.util.lookup;
56.46 -
56.47 -import java.util.*;
56.48 -import org.openide.util.Lookup;
56.49 -
56.50 -/** Runs all NbLookupTest tests on ProxyLookup and adds few additional.
56.51 - */
56.52 -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
56.53 -public class ExcludingLookupTest extends AbstractLookupBaseHid
56.54 -implements AbstractLookupBaseHid.Impl {
56.55 - public ExcludingLookupTest(java.lang.String testName) {
56.56 - super(testName, null);
56.57 - }
56.58 -
56.59 - public Lookup createLookup (final Lookup lookup) {
56.60 - return Lookups.exclude (lookup, new Class[0]);
56.61 - }
56.62 -
56.63 - public Lookup createInstancesLookup (InstanceContent ic) {
56.64 - return new AbstractLookup (ic);
56.65 - }
56.66 -
56.67 - public void clearCaches () {
56.68 - }
56.69 -
56.70 - public void testWeCanRemoveInteger () throws Exception {
56.71 - doBasicFilteringTest (Integer.class, Integer.class, 0);
56.72 - }
56.73 -
56.74 - public void testWeCanRemoveIntegersEvenByAskingForRemoveOfAllNumbers () throws Exception {
56.75 - doBasicFilteringTest (Number.class, Integer.class, 0);
56.76 - }
56.77 - public void testFunWithInterfaces () throws Exception {
56.78 - doBasicFilteringTest (java.io.Serializable.class, Integer.class, 0);
56.79 - }
56.80 -
56.81 - public void testWeCanGetInstanceOfSerializableEvenItIsExcludedIfWeAskForClassNotExtendingIt () throws Exception {
56.82 - Lookup lookup = Lookups.exclude (this.instanceLookup, new Class[] { java.io.Serializable.class });
56.83 - Lookup.Template t = new Lookup.Template (Object.class);
56.84 - Lookup.Result res = lookup.lookup (t);
56.85 -
56.86 - LL ll = new LL ();
56.87 - res.addLookupListener (ll);
56.88 - assertEquals ("Nothing is there", 0, res.allItems ().size ());
56.89 -
56.90 - Object inst = new Integer (3);
56.91 - ic.add (inst);
56.92 -
56.93 - assertEquals ("Not Filtered out", inst, lookup.lookup (Object.class));
56.94 - assertEquals ("Not Filtered out2", inst, lookup.lookupItem (t).getInstance ());
56.95 - assertEquals ("One is there - 2", 1, res.allItems ().size ());
56.96 - assertEquals ("One is there - 2a", 1, res.allInstances ().size ());
56.97 - assertEquals ("One is there - 2b", 1, res.allClasses ().size ());
56.98 - assertEquals ("Right # of events", 1, ll.getCount ());
56.99 -
56.100 - ic.remove (inst);
56.101 - assertEquals ("Filtered out3", null, lookup.lookupItem (t));
56.102 - assertEquals ("Nothing is there - 3", 0, res.allItems ().size ());
56.103 - assertEquals ("Nothing is there - 3a", 0, res.allInstances ().size ());
56.104 - assertEquals ("Nothing is there - 3b", 0, res.allClasses ().size ());
56.105 - assertEquals ("Of course it is not there", null, lookup.lookup (Object.class));
56.106 - assertEquals ("Right # of events", 1, ll.getCount ());
56.107 - }
56.108 -
56.109 - public void testIntegersQueriedThruObject () throws Exception {
56.110 - doBasicFilteringTest (Number.class, Object.class, 1);
56.111 - }
56.112 -
56.113 - private void doBasicFilteringTest (Class theFilter, Class theQuery, int numberOfExcpectedEventsAfterOneChange) throws Exception {
56.114 - Lookup lookup = Lookups.exclude (this.instanceLookup, new Class[] { theFilter });
56.115 - Lookup.Template t = new Lookup.Template (theQuery);
56.116 - Lookup.Result res = lookup.lookup (t);
56.117 -
56.118 - LL ll = new LL ();
56.119 - res.addLookupListener (ll);
56.120 - assertEquals ("Nothing is there", 0, res.allItems ().size ());
56.121 -
56.122 - Object inst = new Integer (3);
56.123 - ic.add (inst);
56.124 -
56.125 - assertEquals ("Filtered out", null, lookup.lookup (theQuery));
56.126 - assertEquals ("Filtered out2", null, lookup.lookupItem (t));
56.127 - assertEquals ("Nothing is there - 2", 0, res.allItems ().size ());
56.128 - assertEquals ("Nothing is there - 2a", 0, res.allInstances ().size ());
56.129 - assertEquals ("Nothing is there - 2b", 0, res.allClasses ().size ());
56.130 - assertEquals ("Right # of events", numberOfExcpectedEventsAfterOneChange, ll.getCount ());
56.131 -
56.132 - ic.remove (inst);
56.133 - assertEquals ("Filtered out3", null, lookup.lookupItem (t));
56.134 - assertEquals ("Nothing is there - 3", 0, res.allItems ().size ());
56.135 - assertEquals ("Nothing is there - 3a", 0, res.allInstances ().size ());
56.136 - assertEquals ("Nothing is there - 3b", 0, res.allClasses ().size ());
56.137 - assertEquals ("Of course it is not there", null, lookup.lookup (theQuery));
56.138 - assertEquals ("Right # of events", numberOfExcpectedEventsAfterOneChange, ll.getCount ());
56.139 -
56.140 - }
56.141 -
56.142 - public void testSizeOfTheLookup () throws Exception {
56.143 - Class exclude = String.class;
56.144 -
56.145 - Lookup lookup = Lookups.exclude (this.instanceLookup, new Class[] { exclude });
56.146 -
56.147 - assertSize ("Should be pretty lightweight", Collections.singleton (lookup), 16,
56.148 - new Object[] { this.instanceLookup, exclude });
56.149 - }
56.150 - public void testSizeOfTheLookupForMultipleFiltersIsHigher () throws Exception {
56.151 - Class exclude = String.class;
56.152 - Class exclude2 = Integer.class;
56.153 - Class[] arr = new Class[] { exclude, exclude2 };
56.154 -
56.155 - Lookup lookup = Lookups.exclude (this.instanceLookup, arr);
56.156 -
56.157 - assertSize ("Is fatter", Collections.singleton (lookup), 40,
56.158 - new Object[] { this.instanceLookup, exclude, exclude2 });
56.159 - assertSize ("But only due to the array", Collections.singleton (lookup), 16,
56.160 - new Object[] { this.instanceLookup, exclude, exclude2, arr });
56.161 - }
56.162 -
56.163 - public void testFilteringOfSomething () throws Exception {
56.164 - doFilteringOfSomething (Runnable.class, java.io.Serializable.class, 1);
56.165 - }
56.166 -
56.167 - private void doFilteringOfSomething (Class theFilter, Class theQuery, int numberOfExcpectedEventsAfterOneChange) throws Exception {
56.168 - Lookup lookup = Lookups.exclude (this.instanceLookup, new Class[] { theFilter });
56.169 - Lookup.Template t = new Lookup.Template (theQuery);
56.170 - Lookup.Result res = lookup.lookup (t);
56.171 -
56.172 - LL ll = new LL ();
56.173 - res.addLookupListener (ll);
56.174 - assertEquals ("Nothing is there", 0, res.allItems ().size ());
56.175 -
56.176 - Object inst = new Integer (3);
56.177 - ic.add (inst);
56.178 -
56.179 - assertEquals ("Accepted", inst, lookup.lookup (theQuery));
56.180 - assertNotNull ("Accepted too", lookup.lookupItem (t));
56.181 - assertEquals ("One is there - 2", 1, res.allItems ().size ());
56.182 - assertEquals ("One is there - 2a", 1, res.allInstances ().size ());
56.183 - assertEquals ("One is there - 2b", 1, res.allClasses ().size ());
56.184 - assertEquals ("Right # of events", numberOfExcpectedEventsAfterOneChange, ll.getCount ());
56.185 -
56.186 - Object inst2 = new Thread (); // implements Runnable
56.187 - ic.add (inst2);
56.188 - assertEquals ("Accepted - 2", inst, lookup.lookup (theQuery));
56.189 - assertNotNull ("Accepted too -2", lookup.lookupItem (t));
56.190 - assertEquals ("One is there - 3", 1, res.allItems ().size ());
56.191 - assertEquals ("One is there - 3a", 1, res.allInstances ().size ());
56.192 - assertEquals ("One is there - 3b", 1, res.allClasses ().size ());
56.193 - assertEquals ("Right # of events", 0, ll.getCount ());
56.194 -
56.195 -
56.196 - ic.remove (inst);
56.197 - assertEquals ("Filtered out3", null, lookup.lookupItem (t));
56.198 - assertEquals ("Nothing is there - 3", 0, res.allItems ().size ());
56.199 - assertEquals ("Nothing is there - 3a", 0, res.allInstances ().size ());
56.200 - assertEquals ("Nothing is there - 3b", 0, res.allClasses ().size ());
56.201 - assertEquals ("Of course it is not there", null, lookup.lookup (theQuery));
56.202 - assertEquals ("Right # of events", numberOfExcpectedEventsAfterOneChange, ll.getCount ());
56.203 - }
56.204 -
56.205 - public void testTheBehaviourAsRequestedByDavidAndDescribedByJesse () throws Exception {
56.206 - class C implements Runnable, java.io.Serializable {
56.207 - public void run () {}
56.208 - }
56.209 - Object c = new C();
56.210 - Lookup l1 = Lookups.singleton(c);
56.211 - Lookup l2 = Lookups.exclude(l1, new Class[] {Runnable.class});
56.212 - assertNull(l2.lookup(Runnable.class));
56.213 - assertEquals(c, l2.lookup(java.io.Serializable.class));
56.214 - }
56.215 -
56.216 - public void testTheBehaviourAsRequestedByDavidAndDescribedByJesseWithUsageOfResult () throws Exception {
56.217 - class C implements Runnable, java.io.Serializable {
56.218 - public void run () {}
56.219 - }
56.220 - Object c = new C();
56.221 - Lookup l1 = Lookups.singleton(c);
56.222 - Lookup l2 = Lookups.exclude(l1, new Class[] {Runnable.class});
56.223 -
56.224 - Lookup.Result run = l2.lookup (new Lookup.Template (Runnable.class));
56.225 - Lookup.Result ser = l2.lookup (new Lookup.Template (java.io.Serializable.class));
56.226 -
56.227 - assertEquals ("Runnables filtered out", 0, run.allItems ().size ());
56.228 - assertEquals ("One serialiazble", 1, ser.allItems ().size ());
56.229 - assertEquals ("And it is c", c, ser.allInstances ().iterator ().next ());
56.230 - }
56.231 -}
57.1 --- a/lookup/src/test/java/org/openide/util/lookup/InheritanceTreeTest.java Wed Jan 27 17:46:23 2010 -0500
57.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
57.3 @@ -1,77 +0,0 @@
57.4 -/*
57.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
57.6 - *
57.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
57.8 - *
57.9 - * The contents of this file are subject to the terms of either the GNU
57.10 - * General Public License Version 2 only ("GPL") or the Common
57.11 - * Development and Distribution License("CDDL") (collectively, the
57.12 - * "License"). You may not use this file except in compliance with the
57.13 - * License. You can obtain a copy of the License at
57.14 - * http://www.netbeans.org/cddl-gplv2.html
57.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
57.16 - * specific language governing permissions and limitations under the
57.17 - * License. When distributing the software, include this License Header
57.18 - * Notice in each file and include the License file at
57.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
57.20 - * particular file as subject to the "Classpath" exception as provided
57.21 - * by Sun in the GPL Version 2 section of the License file that
57.22 - * accompanied this code. If applicable, add the following below the
57.23 - * License Header, with the fields enclosed by brackets [] replaced by
57.24 - * your own identifying information:
57.25 - * "Portions Copyrighted [year] [name of copyright owner]"
57.26 - *
57.27 - * Contributor(s):
57.28 - *
57.29 - * The Original Software is NetBeans. The Initial Developer of the Original
57.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
57.31 - * Microsystems, Inc. All Rights Reserved.
57.32 - *
57.33 - * If you wish your version of this file to be governed by only the CDDL
57.34 - * or only the GPL Version 2, indicate your decision by adding
57.35 - * "[Contributor] elects to include this software in this distribution
57.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
57.37 - * single choice of license, a recipient has the option to distribute
57.38 - * your version of this file under either the CDDL, the GPL Version 2 or
57.39 - * to extend the choice of license to its licensees as provided above.
57.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
57.41 - * Version 2 license, then the option applies only if the new code is
57.42 - * made subject to such option by the copyright holder.
57.43 - */
57.44 -package org.openide.util.lookup;
57.45 -
57.46 -import junit.framework.TestCase;
57.47 -import junit.framework.*;
57.48 -import org.openide.util.Lookup;
57.49 -import org.openide.util.lookup.AbstractLookup.ReferenceIterator;
57.50 -import org.openide.util.lookup.AbstractLookup.ReferenceToResult;
57.51 -import java.io.*;
57.52 -import java.lang.ref.WeakReference;
57.53 -import java.util.*;
57.54 -
57.55 -/**
57.56 - *
57.57 - * @author Jaroslav Tulach
57.58 - */
57.59 -public class InheritanceTreeTest extends TestCase {
57.60 -
57.61 - public InheritanceTreeTest(String testName) {
57.62 - super(testName);
57.63 - }
57.64 -
57.65 - protected void setUp() throws Exception {
57.66 - }
57.67 -
57.68 - protected void tearDown() throws Exception {
57.69 - }
57.70 -
57.71 - public void testDeserOfNode() {
57.72 - InheritanceTree inh = new InheritanceTree();
57.73 - InheritanceTree.Node n = new InheritanceTree.Node(String.class);
57.74 - n.markDeserialized();
57.75 - n.markDeserialized();
57.76 -
57.77 - n.assignItem(inh, new InstanceContent.SimpleItem("Ahoj"));
57.78 - }
57.79 -
57.80 -}
58.1 --- a/lookup/src/test/java/org/openide/util/lookup/InitializationBug44134Test.java Wed Jan 27 17:46:23 2010 -0500
58.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
58.3 @@ -1,126 +0,0 @@
58.4 -/*
58.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
58.6 - *
58.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
58.8 - *
58.9 - * The contents of this file are subject to the terms of either the GNU
58.10 - * General Public License Version 2 only ("GPL") or the Common
58.11 - * Development and Distribution License("CDDL") (collectively, the
58.12 - * "License"). You may not use this file except in compliance with the
58.13 - * License. You can obtain a copy of the License at
58.14 - * http://www.netbeans.org/cddl-gplv2.html
58.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
58.16 - * specific language governing permissions and limitations under the
58.17 - * License. When distributing the software, include this License Header
58.18 - * Notice in each file and include the License file at
58.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
58.20 - * particular file as subject to the "Classpath" exception as provided
58.21 - * by Sun in the GPL Version 2 section of the License file that
58.22 - * accompanied this code. If applicable, add the following below the
58.23 - * License Header, with the fields enclosed by brackets [] replaced by
58.24 - * your own identifying information:
58.25 - * "Portions Copyrighted [year] [name of copyright owner]"
58.26 - *
58.27 - * Contributor(s):
58.28 - *
58.29 - * The Original Software is NetBeans. The Initial Developer of the Original
58.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
58.31 - * Microsystems, Inc. All Rights Reserved.
58.32 - *
58.33 - * If you wish your version of this file to be governed by only the CDDL
58.34 - * or only the GPL Version 2, indicate your decision by adding
58.35 - * "[Contributor] elects to include this software in this distribution
58.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
58.37 - * single choice of license, a recipient has the option to distribute
58.38 - * your version of this file under either the CDDL, the GPL Version 2 or
58.39 - * to extend the choice of license to its licensees as provided above.
58.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
58.41 - * Version 2 license, then the option applies only if the new code is
58.42 - * made subject to such option by the copyright holder.
58.43 - */
58.44 -
58.45 -package org.openide.util.lookup;
58.46 -
58.47 -import java.util.*;
58.48 -import org.netbeans.junit.*;
58.49 -import org.openide.util.Lookup;
58.50 -
58.51 -public class InitializationBug44134Test extends NbTestCase {
58.52 - public InitializationBug44134Test (java.lang.String testName) {
58.53 - super(testName);
58.54 - }
58.55 -
58.56 - public static void main(java.lang.String[] args) {
58.57 - junit.textui.TestRunner.run(new NbTestSuite(InitializationBug44134Test.class));
58.58 - }
58.59 -
58.60 - public void testThereShouldBe18Integers () throws Exception {
58.61 - FooManifestLookup foo = new FooManifestLookup ();
58.62 -
58.63 - Collection items = foo.lookup (new Lookup.Template (Integer.class)).allItems ();
58.64 -
58.65 - assertEquals ("18 of them", 18, items.size ());
58.66 -
58.67 - Iterator it = items.iterator ();
58.68 - while (it.hasNext()) {
58.69 - Lookup.Item t = (Lookup.Item)it.next ();
58.70 - assertEquals ("Is Integer", Integer.class, t.getInstance ().getClass ());
58.71 - }
58.72 - }
58.73 -
58.74 -
58.75 - public class FooManifestLookup extends AbstractLookup {
58.76 - public FooManifestLookup() {
58.77 - super();
58.78 - }
58.79 -
58.80 - @Override
58.81 - protected void initialize() {
58.82 - for (int i=0; i<18; i++) {
58.83 - try {
58.84 - String id= "__" + i;
58.85 -
58.86 - addPair(new FooLookupItem(new Integer(i),id));
58.87 - }
58.88 - catch (Exception e) {
58.89 - }
58.90 - }
58.91 - }
58.92 -
58.93 - public class FooLookupItem extends AbstractLookup.Pair {
58.94 - public FooLookupItem(Integer data, String id) {
58.95 - super();
58.96 - this.data=data;
58.97 - this.id=id;
58.98 - }
58.99 -
58.100 - protected boolean creatorOf(Object obj) {
58.101 - return obj == data;
58.102 - }
58.103 -
58.104 - public String getDisplayName() {
58.105 - return data.toString();
58.106 - }
58.107 -
58.108 - public Class getType () {
58.109 - return Integer.class;
58.110 - }
58.111 -
58.112 - protected boolean instanceOf (Class c) {
58.113 - return c.isInstance(data);
58.114 - }
58.115 -
58.116 - public Object getInstance() {
58.117 - return data;
58.118 - }
58.119 -
58.120 - public String getId() {
58.121 - return id;
58.122 - }
58.123 -
58.124 - private Integer data;
58.125 - private String id;
58.126 - }
58.127 - }
58.128 -
58.129 -}
59.1 --- a/lookup/src/test/java/org/openide/util/lookup/KomrskaLookupTest.java Wed Jan 27 17:46:23 2010 -0500
59.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
59.3 @@ -1,177 +0,0 @@
59.4 -/*
59.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
59.6 - *
59.7 - * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
59.8 - *
59.9 - * The contents of this file are subject to the terms of either the GNU
59.10 - * General Public License Version 2 only ("GPL") or the Common
59.11 - * Development and Distribution License("CDDL") (collectively, the
59.12 - * "License"). You may not use this file except in compliance with the
59.13 - * License. You can obtain a copy of the License at
59.14 - * http://www.netbeans.org/cddl-gplv2.html
59.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
59.16 - * specific language governing permissions and limitations under the
59.17 - * License. When distributing the software, include this License Header
59.18 - * Notice in each file and include the License file at
59.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
59.20 - * particular file as subject to the "Classpath" exception as provided
59.21 - * by Sun in the GPL Version 2 section of the License file that
59.22 - * accompanied this code. If applicable, add the following below the
59.23 - * License Header, with the fields enclosed by brackets [] replaced by
59.24 - * your own identifying information:
59.25 - * "Portions Copyrighted [year] [name of copyright owner]"
59.26 - *
59.27 - * If you wish your version of this file to be governed by only the CDDL
59.28 - * or only the GPL Version 2, indicate your decision by adding
59.29 - * "[Contributor] elects to include this software in this distribution
59.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
59.31 - * single choice of license, a recipient has the option to distribute
59.32 - * your version of this file under either the CDDL, the GPL Version 2 or
59.33 - * to extend the choice of license to its licensees as provided above.
59.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
59.35 - * Version 2 license, then the option applies only if the new code is
59.36 - * made subject to such option by the copyright holder.
59.37 - *
59.38 - * Contributor(s):
59.39 - *
59.40 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
59.41 - */
59.42 -package org.openide.util.lookup;
59.43 -
59.44 -import org.junit.After;
59.45 -import org.junit.Before;
59.46 -import org.junit.Test;
59.47 -import org.openide.util.Lookup;
59.48 -import org.openide.util.LookupEvent;
59.49 -import org.openide.util.LookupListener;
59.50 -import static org.junit.Assert.*;
59.51 -
59.52 -/**
59.53 - * Test donated by Mr. Komrska. Seems to pass with 6.5.
59.54 - * @author komrska
59.55 - */
59.56 -public final class KomrskaLookupTest {
59.57 - private TestLookupManager lookupManager=null;
59.58 - private StringBuffer result=null;
59.59 -
59.60 - //
59.61 -
59.62 - private void addToLookup(final TestLookupItemA object) {
59.63 - result.append('A');
59.64 - lookupManager.add(object);
59.65 - }
59.66 - private void removeFromLookup(final TestLookupItemA object) {
59.67 - result.append('A');
59.68 - lookupManager.remove(object);
59.69 - }
59.70 -
59.71 - private void addToLookup(final TestLookupItemB object) {
59.72 - result.append('B');
59.73 - lookupManager.add(object);
59.74 - }
59.75 - private void removeFromLookup(final TestLookupItemB object) {
59.76 - result.append('B');
59.77 - lookupManager.remove(object);
59.78 - }
59.79 -
59.80 - public String getResult() {
59.81 - return result.toString();
59.82 - }
59.83 -
59.84 - //
59.85 -
59.86 - @Before
59.87 - public void setUp() {
59.88 - lookupManager=new TestLookupManager();
59.89 - result=new StringBuffer();
59.90 - }
59.91 -
59.92 - @After
59.93 - public void tearDown() {
59.94 - lookupManager=null;
59.95 - result=null;
59.96 - }
59.97 -
59.98 - @Test
59.99 - public void testLookupBug() {
59.100 - TestLookupItemA itemA1=new TestLookupItemA();
59.101 - TestLookupItemB itemB1=new TestLookupItemB();
59.102 - //
59.103 - addToLookup(itemA1);
59.104 - addToLookup(itemB1);
59.105 - removeFromLookup(itemA1);
59.106 - removeFromLookup(itemB1);
59.107 - addToLookup(itemB1);
59.108 - removeFromLookup(itemB1);
59.109 - //
59.110 - addToLookup(itemA1);
59.111 - addToLookup(itemB1);
59.112 - removeFromLookup(itemA1);
59.113 - removeFromLookup(itemB1);
59.114 - addToLookup(itemB1);
59.115 - removeFromLookup(itemB1);
59.116 - //
59.117 - addToLookup(itemA1);
59.118 - addToLookup(itemB1);
59.119 - removeFromLookup(itemA1);
59.120 - removeFromLookup(itemB1);
59.121 - addToLookup(itemB1);
59.122 - removeFromLookup(itemB1);
59.123 - //
59.124 - assertEquals(getResult(),lookupManager.getResult());
59.125 - }
59.126 -
59.127 - public static final class TestLookupItemA {}
59.128 - public static final class TestLookupItemB {}
59.129 - public static final class TestLookupManager {
59.130 - private InstanceContent instanceContent=new InstanceContent();
59.131 - private AbstractLookup abstractLookup=new AbstractLookup(instanceContent);
59.132 -
59.133 - private Lookup.Result<TestLookupItemA> resultA=null;
59.134 - private Lookup.Result<TestLookupItemB> resultB=null;
59.135 -
59.136 - private LookupListener listenerA=new LookupListener() {
59.137 - public void resultChanged(LookupEvent event) {
59.138 - result.append('A');
59.139 - }
59.140 - };
59.141 - private LookupListener listenerB=new LookupListener() {
59.142 - public void resultChanged(LookupEvent event) {
59.143 - result.append('B');
59.144 - }
59.145 - };
59.146 -
59.147 - private StringBuffer result=new StringBuffer();
59.148 -
59.149 - //
59.150 -
59.151 - public TestLookupManager() {
59.152 - Lookup.Template<TestLookupItemA> templateA=
59.153 - new Lookup.Template<TestLookupItemA>(TestLookupItemA.class);
59.154 - resultA=abstractLookup.lookup(templateA);
59.155 - resultA.addLookupListener(listenerA);
59.156 - resultA.allInstances().size();
59.157 - //
59.158 - Lookup.Template<TestLookupItemB> templateB=
59.159 - new Lookup.Template<TestLookupItemB>(TestLookupItemB.class);
59.160 - resultB=abstractLookup.lookup(templateB);
59.161 - resultB.addLookupListener(listenerB);
59.162 - resultB.allInstances().size();
59.163 - // WORKAROUND
59.164 - // instanceContent.add(Boolean.TRUE);
59.165 - }
59.166 -
59.167 - //
59.168 -
59.169 - public void add(Object item) {
59.170 - instanceContent.add(item);
59.171 - }
59.172 - public void remove(Object item) {
59.173 - instanceContent.remove(item);
59.174 - }
59.175 - public String getResult() {
59.176 - return result.toString();
59.177 - }
59.178 - }
59.179 -
59.180 -}
60.1 --- a/lookup/src/test/java/org/openide/util/lookup/LookupBugTest.java Wed Jan 27 17:46:23 2010 -0500
60.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
60.3 @@ -1,79 +0,0 @@
60.4 -package org.openide.util.lookup;
60.5 -
60.6 -import java.util.logging.Logger;
60.7 -import org.junit.Before;
60.8 -import org.junit.Test;
60.9 -import org.openide.util.Lookup;
60.10 -import org.openide.util.LookupEvent;
60.11 -import org.openide.util.LookupListener;
60.12 -import static org.junit.Assert.*;
60.13 -
60.14 -/**
60.15 - * Test of a Lookup bug seen in NetBeans platforms 6.0-6.5M1.
60.16 - * @author rlee
60.17 - */
60.18 -public class LookupBugTest implements LookupListener
60.19 -{
60.20 - private static final int MAX_LOOPS = 1000;
60.21 -
60.22 - private AbstractLookup lookup;
60.23 - private InstanceContent content;
60.24 - private Lookup.Result<String> wordResult;
60.25 - private Lookup.Result<Integer> numberResult;
60.26 - private String word;
60.27 - private Integer number;
60.28 - private Logger LOG;
60.29 -
60.30 - private boolean fired;
60.31 - private int i;
60.32 -
60.33 - @Before
60.34 - public void setUp()
60.35 - {
60.36 - LOG = Logger.getLogger("test.LookupBugTest");
60.37 - content = new InstanceContent();
60.38 - lookup = new AbstractLookup(content);
60.39 - wordResult = lookup.lookupResult(java.lang.String.class);
60.40 - wordResult.addLookupListener(this);
60.41 - numberResult = lookup.lookupResult(java.lang.Integer.class);
60.42 - numberResult.addLookupListener(this);
60.43 -
60.44 - fired = false;
60.45 - }
60.46 -
60.47 - @Test
60.48 - public void lookupTest()
60.49 - {
60.50 - for(i = 0; i < MAX_LOOPS; i++ )
60.51 - {
60.52 - word = String.valueOf(i);
60.53 - number = new Integer(i);
60.54 - content.add(word);
60.55 - assertTrue( "word on loop " + i, checkLookupEventFired() );
60.56 - content.add(number);
60.57 - assertTrue( "number on loop " + i, checkLookupEventFired() );
60.58 - content.remove(word);
60.59 - assertTrue( "remove word on loop " + i, checkLookupEventFired() );
60.60 - content.remove(number);
60.61 - assertTrue( "remove number on loop " + i, checkLookupEventFired() );
60.62 -
60.63 - assertTrue("The lookup still needs to stay simple", AbstractLookup.isSimple(lookup));
60.64 - }
60.65 - }
60.66 -
60.67 - public void resultChanged(LookupEvent ev)
60.68 - {
60.69 - fired = true;
60.70 - }
60.71 -
60.72 - public boolean checkLookupEventFired()
60.73 - {
60.74 - LOG.fine(" round: " + i + " word = " + word + " number = " + number);
60.75 - if( fired )
60.76 - {
60.77 - fired = false;
60.78 - return true;
60.79 - }
60.80 - else return false;
60.81 - }
60.82 -}
61.1 --- a/lookup/src/test/java/org/openide/util/lookup/LookupsProxyTest.java Wed Jan 27 17:46:23 2010 -0500
61.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
61.3 @@ -1,282 +0,0 @@
61.4 -/*
61.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
61.6 - *
61.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
61.8 - *
61.9 - * The contents of this file are subject to the terms of either the GNU
61.10 - * General Public License Version 2 only ("GPL") or the Common
61.11 - * Development and Distribution License("CDDL") (collectively, the
61.12 - * "License"). You may not use this file except in compliance with the
61.13 - * License. You can obtain a copy of the License at
61.14 - * http://www.netbeans.org/cddl-gplv2.html
61.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
61.16 - * specific language governing permissions and limitations under the
61.17 - * License. When distributing the software, include this License Header
61.18 - * Notice in each file and include the License file at
61.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
61.20 - * particular file as subject to the "Classpath" exception as provided
61.21 - * by Sun in the GPL Version 2 section of the License file that
61.22 - * accompanied this code. If applicable, add the following below the
61.23 - * License Header, with the fields enclosed by brackets [] replaced by
61.24 - * your own identifying information:
61.25 - * "Portions Copyrighted [year] [name of copyright owner]"
61.26 - *
61.27 - * Contributor(s):
61.28 - *
61.29 - * The Original Software is NetBeans. The Initial Developer of the Original
61.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
61.31 - * Microsystems, Inc. All Rights Reserved.
61.32 - *
61.33 - * If you wish your version of this file to be governed by only the CDDL
61.34 - * or only the GPL Version 2, indicate your decision by adding
61.35 - * "[Contributor] elects to include this software in this distribution
61.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
61.37 - * single choice of license, a recipient has the option to distribute
61.38 - * your version of this file under either the CDDL, the GPL Version 2 or
61.39 - * to extend the choice of license to its licensees as provided above.
61.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
61.41 - * Version 2 license, then the option applies only if the new code is
61.42 - * made subject to such option by the copyright holder.
61.43 - */
61.44 -
61.45 -package org.openide.util.lookup;
61.46 -
61.47 -import java.io.Serializable;
61.48 -
61.49 -import java.util.*;
61.50 -import org.netbeans.junit.*;
61.51 -import org.openide.util.Lookup;
61.52 -import org.openide.util.LookupEvent;
61.53 -import org.openide.util.LookupListener;
61.54 -
61.55 -/** Runs all NbLookupTest tests on ProxyLookup and adds few additional.
61.56 - */
61.57 -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
61.58 -public class LookupsProxyTest extends AbstractLookupBaseHid
61.59 -implements AbstractLookupBaseHid.Impl {
61.60 - public LookupsProxyTest(java.lang.String testName) {
61.61 - super(testName, null);
61.62 - }
61.63 -
61.64 - public static void main(java.lang.String[] args) {
61.65 - junit.textui.TestRunner.run(new NbTestSuite (LookupsProxyTest.class));
61.66 - }
61.67 -
61.68 - /** Creates an lookup for given lookup. This class just returns
61.69 - * the object passed in, but subclasses can be different.
61.70 - * @param lookup in lookup
61.71 - * @return a lookup to use
61.72 - */
61.73 - public Lookup createLookup (final Lookup lookup) {
61.74 - return org.openide.util.lookup.Lookups.proxy (
61.75 - new Lookup.Provider () {
61.76 - public Lookup getLookup () {
61.77 - return lookup;
61.78 - }
61.79 - }
61.80 - );
61.81 - }
61.82 -
61.83 - public Lookup createInstancesLookup (InstanceContent ic) {
61.84 - return new AbstractLookup (ic);
61.85 - }
61.86 -
61.87 - public void clearCaches () {
61.88 - }
61.89 -
61.90 -
61.91 -
61.92 - /** Check whether setLookups method does not fire when there is no
61.93 - * change in the lookups.
61.94 - */
61.95 - public void testProxyListener () {
61.96 - Changer ch = new Changer (Lookup.EMPTY);
61.97 -
61.98 - Lookup lookup = Lookups.proxy(ch);
61.99 - Lookup.Result res = lookup.lookup (new Lookup.Template (Object.class));
61.100 -
61.101 - LL ll = new LL ();
61.102 - res.addLookupListener (ll);
61.103 - Collection allRes = res.allInstances ();
61.104 -
61.105 - ch.setLookup (new AbstractLookup (new InstanceContent ())); // another empty lookup
61.106 - lookup.lookup (Object.class); // does the refresh
61.107 -
61.108 - assertEquals("Replacing an empty by empty does not generate an event", 0, ll.getCount());
61.109 -
61.110 - InstanceContent content = new InstanceContent ();
61.111 - AbstractLookup del = new AbstractLookup (content);
61.112 - content.add (this);
61.113 - ch.setLookup (del);
61.114 - lookup.lookup (Object.class);
61.115 -
61.116 - if (ll.getCount () != 1) {
61.117 - fail ("Changing lookups with different content generates an event");
61.118 - }
61.119 -
61.120 - ch.setLookup (del);
61.121 - lookup.lookup (Object.class);
61.122 -
61.123 - if (ll.getCount () != 0) {
61.124 - fail ("Not changing the lookups does not generate any event");
61.125 - }
61.126 - }
61.127 -
61.128 -
61.129 - public void testListeningAndQueryingByTwoListenersInstancesSetLookups() {
61.130 - doListeningAndQueryingByTwoListenersSetLookups(0, 1, false);
61.131 - }
61.132 - public void testListeningAndQueryingByTwoListenersClassesSetLookups() {
61.133 - doListeningAndQueryingByTwoListenersSetLookups(1, 1, false);
61.134 - }
61.135 - public void testListeningAndQueryingByTwoListenersItemsSetLookups() {
61.136 - doListeningAndQueryingByTwoListenersSetLookups(2, 1, false);
61.137 - }
61.138 -
61.139 - public void testListeningAndQueryingByTwoListenersInstancesSetLookups2() {
61.140 - doListeningAndQueryingByTwoListenersSetLookups(0, 2, false);
61.141 - }
61.142 - public void testListeningAndQueryingByTwoListenersClassesSetLookups2() {
61.143 - doListeningAndQueryingByTwoListenersSetLookups(1, 2, false);
61.144 - }
61.145 - public void testListeningAndQueryingByTwoListenersItemsSetLookups2() {
61.146 - doListeningAndQueryingByTwoListenersSetLookups(2, 2, false);
61.147 - }
61.148 -
61.149 - public void testListeningAndQueryingByTwoListenersInstancesSetLookupsWithProxy() {
61.150 - doListeningAndQueryingByTwoListenersSetLookups(0, 1, true);
61.151 - }
61.152 - public void testListeningAndQueryingByTwoListenersClassesSetLookupsWithProxy() {
61.153 - doListeningAndQueryingByTwoListenersSetLookups(1, 1, true);
61.154 - }
61.155 - public void testListeningAndQueryingByTwoListenersItemsSetLookupsWithProxy() {
61.156 - doListeningAndQueryingByTwoListenersSetLookups(2, 1, true);
61.157 - }
61.158 -
61.159 - public void testListeningAndQueryingByTwoListenersInstancesSetLookups2WithProxy() {
61.160 - doListeningAndQueryingByTwoListenersSetLookups(0, 2, true);
61.161 - }
61.162 - public void testListeningAndQueryingByTwoListenersClassesSetLookups2WithProxy() {
61.163 - doListeningAndQueryingByTwoListenersSetLookups(1, 2, true);
61.164 - }
61.165 - public void testListeningAndQueryingByTwoListenersItemsSetLookups2WithProxy() {
61.166 - doListeningAndQueryingByTwoListenersSetLookups(2, 2, true);
61.167 - }
61.168 -
61.169 - /* XXX: these are pretty slow, seems there is a performance problem 2^22
61.170 - public void testListeningAndQueryingByTwoListenersInstancesSetLookups22() {
61.171 - doListeningAndQueryingByTwoListenersSetLookups(0, 22);
61.172 - }
61.173 - public void testListeningAndQueryingByTwoListenersClassesSetLookups22() {
61.174 - doListeningAndQueryingByTwoListenersSetLookups(1, 22);
61.175 - }
61.176 - public void testListeningAndQueryingByTwoListenersItemsSetLookups22() {
61.177 - doListeningAndQueryingByTwoListenersSetLookups(2, 22);
61.178 - }
61.179 - */
61.180 -
61.181 - private void doListeningAndQueryingByTwoListenersSetLookups(final int type, int depth, boolean cacheOnTop) {
61.182 - Changer orig = new Changer(Lookup.EMPTY);
61.183 - Lookup on = Lookups.proxy(orig);
61.184 - Lookup first = on;
61.185 -
61.186 - while (--depth > 0) {
61.187 - Changer next = new Changer(on);
61.188 - on = Lookups.proxy(next);
61.189 - }
61.190 -
61.191 -
61.192 - final Lookup lookup = cacheOnTop ? new ProxyLookup(new Lookup[] { on }) : on;
61.193 -
61.194 - class L implements LookupListener {
61.195 - Lookup.Result integer = lookup.lookup(new Lookup.Template(Integer.class));
61.196 - Lookup.Result number = lookup.lookup(new Lookup.Template(Number.class));
61.197 - Lookup.Result serial = lookup.lookup(new Lookup.Template(Serializable.class));
61.198 -
61.199 - {
61.200 - integer.addLookupListener(this);
61.201 - number.addLookupListener(this);
61.202 - serial.addLookupListener(this);
61.203 - }
61.204 -
61.205 - int round;
61.206 -
61.207 - public void resultChanged(LookupEvent ev) {
61.208 - Collection c1 = get(type, integer);
61.209 - Collection c2 = get(type, number);
61.210 - Collection c3 = get(type, serial);
61.211 -
61.212 - assertEquals("round " + round + " c1 vs. c2", c1, c2);
61.213 - assertEquals("round " + round + " c1 vs. c3", c1, c3);
61.214 - assertEquals("round " + round + " c2 vs. c3", c2, c3);
61.215 -
61.216 - round++;
61.217 - }
61.218 -
61.219 - private Collection get(int type, Lookup.Result res) {
61.220 - Collection c;
61.221 - switch(type) {
61.222 - case 0: c = res.allInstances(); break;
61.223 - case 1: c = res.allClasses(); break;
61.224 - case 2: c = res.allItems(); break;
61.225 - default: c = null; fail("Type: " + type); break;
61.226 - }
61.227 -
61.228 - assertNotNull(c);
61.229 - return new ArrayList(c);
61.230 - }
61.231 - }
61.232 -
61.233 - L listener = new L();
61.234 - listener.resultChanged(null);
61.235 - ArrayList arr = new ArrayList();
61.236 - for(int i = 0; i < 100; i++) {
61.237 - arr.add(new Integer(i));
61.238 -
61.239 - orig.lookup = Lookups.fixed(arr.toArray());
61.240 - // do the refresh
61.241 - first.lookup((Class)null);
61.242 - }
61.243 -
61.244 - assertEquals("3x100+1 checks", 301, listener.round);
61.245 - }
61.246 -
61.247 -
61.248 - public void testRefreshWithoutAllInstances103300 () {
61.249 - Changer ch = new Changer (Lookup.EMPTY);
61.250 -
61.251 - Lookup lookup = Lookups.proxy(ch);
61.252 -
61.253 - ch.setLookup (new AbstractLookup (new InstanceContent ())); // another empty lookup
61.254 - assertNull("Nothing there", lookup.lookup (Object.class)); // does the refresh
61.255 -
61.256 - InstanceContent content = new InstanceContent ();
61.257 - AbstractLookup del = new AbstractLookup (content);
61.258 - content.add (this);
61.259 - ch.setLookup (del);
61.260 - assertEquals("Can see me", this, lookup.lookup (Object.class));
61.261 -
61.262 - ch.setLookup (del);
61.263 - assertEquals("Still can see me", this, lookup.lookup (Object.class));
61.264 -
61.265 - assertEquals("I am visible", this, lookup.lookup(LookupsProxyTest.class));
61.266 - }
61.267 -
61.268 -
61.269 - private static final class Changer implements Lookup.Provider {
61.270 - private Lookup lookup;
61.271 -
61.272 - public Changer (Lookup lookup) {
61.273 - setLookup (lookup);
61.274 - }
61.275 -
61.276 - public void setLookup (Lookup lookup) {
61.277 - this.lookup = lookup;
61.278 - }
61.279 -
61.280 - public Lookup getLookup() {
61.281 - return lookup;
61.282 - }
61.283 - }
61.284 -
61.285 -}
62.1 --- a/lookup/src/test/java/org/openide/util/lookup/MetaInfServicesLookupTest.java Wed Jan 27 17:46:23 2010 -0500
62.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
62.3 @@ -1,552 +0,0 @@
62.4 -/*
62.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
62.6 - *
62.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
62.8 - *
62.9 - * The contents of this file are subject to the terms of either the GNU
62.10 - * General Public License Version 2 only ("GPL") or the Common
62.11 - * Development and Distribution License("CDDL") (collectively, the
62.12 - * "License"). You may not use this file except in compliance with the
62.13 - * License. You can obtain a copy of the License at
62.14 - * http://www.netbeans.org/cddl-gplv2.html
62.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
62.16 - * specific language governing permissions and limitations under the
62.17 - * License. When distributing the software, include this License Header
62.18 - * Notice in each file and include the License file at
62.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
62.20 - * particular file as subject to the "Classpath" exception as provided
62.21 - * by Sun in the GPL Version 2 section of the License file that
62.22 - * accompanied this code. If applicable, add the following below the
62.23 - * License Header, with the fields enclosed by brackets [] replaced by
62.24 - * your own identifying information:
62.25 - * "Portions Copyrighted [year] [name of copyright owner]"
62.26 - *
62.27 - * Contributor(s):
62.28 - *
62.29 - * The Original Software is NetBeans. The Initial Developer of the Original
62.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
62.31 - * Microsystems, Inc. All Rights Reserved.
62.32 - *
62.33 - * If you wish your version of this file to be governed by only the CDDL
62.34 - * or only the GPL Version 2, indicate your decision by adding
62.35 - * "[Contributor] elects to include this software in this distribution
62.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
62.37 - * single choice of license, a recipient has the option to distribute
62.38 - * your version of this file under either the CDDL, the GPL Version 2 or
62.39 - * to extend the choice of license to its licensees as provided above.
62.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
62.41 - * Version 2 license, then the option applies only if the new code is
62.42 - * made subject to such option by the copyright holder.
62.43 - */
62.44 -
62.45 -package org.openide.util.lookup;
62.46 -
62.47 -import java.io.ByteArrayInputStream;
62.48 -import java.io.File;
62.49 -import java.io.FileOutputStream;
62.50 -import java.io.IOException;
62.51 -import java.io.InputStream;
62.52 -import java.io.InputStreamReader;
62.53 -import java.lang.ref.Reference;
62.54 -import java.lang.ref.WeakReference;
62.55 -import java.net.URL;
62.56 -import java.net.URLClassLoader;
62.57 -import java.net.URLConnection;
62.58 -import java.net.URLStreamHandler;
62.59 -import java.util.ArrayList;
62.60 -import java.util.Collection;
62.61 -import java.util.Collections;
62.62 -import java.util.Comparator;
62.63 -import java.util.Enumeration;
62.64 -import java.util.HashSet;
62.65 -import java.util.Iterator;
62.66 -import java.util.List;
62.67 -import java.util.Map;
62.68 -import java.util.Set;
62.69 -import java.util.TreeSet;
62.70 -import java.util.WeakHashMap;
62.71 -import java.util.concurrent.atomic.AtomicBoolean;
62.72 -import java.util.jar.JarEntry;
62.73 -import java.util.jar.JarOutputStream;
62.74 -import java.util.logging.Level;
62.75 -import java.util.logging.Logger;
62.76 -import java.util.regex.Matcher;
62.77 -import java.util.regex.Pattern;
62.78 -import org.bar.Comparator2;
62.79 -import org.netbeans.junit.MockServices;
62.80 -import org.netbeans.junit.NbTestCase;
62.81 -import org.openide.util.Lookup;
62.82 -import org.openide.util.LookupEvent;
62.83 -import org.openide.util.LookupListener;
62.84 -import org.openide.util.test.MockLookup;
62.85 -
62.86 -/** Test finding services from manifest.
62.87 - * @author Jesse Glick
62.88 - */
62.89 -public class MetaInfServicesLookupTest extends NbTestCase {
62.90 - private Logger LOG;
62.91 - private Map<ClassLoader,Lookup> lookups = new WeakHashMap<ClassLoader,Lookup>();
62.92 -
62.93 - public MetaInfServicesLookupTest(String name) {
62.94 - super(name);
62.95 - LOG = Logger.getLogger("Test." + name);
62.96 - }
62.97 -
62.98 - protected String prefix() {
62.99 - return "META-INF/services/";
62.100 - }
62.101 -
62.102 - protected Lookup createLookup(ClassLoader c) {
62.103 - return Lookups.metaInfServices(c);
62.104 - }
62.105 -
62.106 - @Override
62.107 - protected Level logLevel() {
62.108 - return Level.INFO;
62.109 - }
62.110 -
62.111 - private Lookup getTestedLookup(ClassLoader c) {
62.112 - MockServices.setServices();
62.113 - Lookup l = lookups.get(c);
62.114 - if (l == null) {
62.115 - l = createLookup(c);
62.116 - lookups.put(c, l);
62.117 - }
62.118 - return l;
62.119 - }
62.120 -
62.121 - private URL findJar(String n) throws IOException {
62.122 - LOG.info("Looking for " + n);
62.123 - File jarDir = new File(getWorkDir(), "jars");
62.124 - jarDir.mkdirs();
62.125 - File jar = new File(jarDir, n);
62.126 - if (jar.exists()) {
62.127 - return jar.toURI().toURL();
62.128 - }
62.129 -
62.130 - LOG.info("generating " + jar);
62.131 -
62.132 - URL data = MetaInfServicesLookupTest.class.getResource(n.replaceAll("\\.jar", "\\.txt"));
62.133 - assertNotNull("Data found", data);
62.134 - StringBuffer sb = new StringBuffer();
62.135 - InputStreamReader r = new InputStreamReader(data.openStream());
62.136 - for(;;) {
62.137 - int ch = r.read();
62.138 - if (ch == -1) {
62.139 - break;
62.140 - }
62.141 - sb.append((char)ch);
62.142 - }
62.143 -
62.144 - JarOutputStream os = new JarOutputStream(new FileOutputStream(jar));
62.145 -
62.146 - Pattern p = Pattern.compile(":([^:]+):([^:]*)", Pattern.MULTILINE | Pattern.DOTALL);
62.147 - Matcher m = p.matcher(sb);
62.148 - Pattern foobar = Pattern.compile("^(org\\.(foo|bar)\\..*)$", Pattern.MULTILINE);
62.149 - Set<String> names = new TreeSet<String>();
62.150 - while (m.find()) {
62.151 - assert m.groupCount() == 2;
62.152 - String entryName = prefix() + m.group(1);
62.153 - LOG.info("putting there entry: " + entryName);
62.154 - os.putNextEntry(new JarEntry(entryName));
62.155 - os.write(m.group(2).getBytes());
62.156 - os.closeEntry();
62.157 -
62.158 - Matcher fb = foobar.matcher(m.group(2));
62.159 - while (fb.find()) {
62.160 - String clazz = fb.group(1).replace('.', '/') + ".class";
62.161 - LOG.info("will copy " + clazz);
62.162 - names.add(clazz);
62.163 - }
62.164 - }
62.165 -
62.166 - for (String copy : names) {
62.167 - os.putNextEntry(new JarEntry(copy));
62.168 - LOG.info("copying " + copy);
62.169 - InputStream from = MetaInfServicesLookupTest.class.getResourceAsStream("/" + copy);
62.170 - assertNotNull(copy, from);
62.171 - for (;;) {
62.172 - int ch = from.read();
62.173 - if (ch == -1) {
62.174 - break;
62.175 - }
62.176 - os.write(ch);
62.177 - }
62.178 - from.close();
62.179 - os.closeEntry();
62.180 - }
62.181 - os.close();
62.182 - LOG.info("done " + jar);
62.183 - return jar.toURI().toURL();
62.184 - }
62.185 -
62.186 - ClassLoader c1, c2, c2a, c3, c4;
62.187 -
62.188 - @Override
62.189 - protected void setUp() throws Exception {
62.190 - clearWorkDir();
62.191 - ClassLoader app = getClass().getClassLoader().getParent();
62.192 - ClassLoader c0 = app;
62.193 -
62.194 - c1 = new URLClassLoader(new URL[] {
62.195 - findJar("services-jar-1.jar"),
62.196 - }, c0);
62.197 - c2 = new URLClassLoader(new URL[] {
62.198 - findJar("services-jar-2.jar"),
62.199 - }, c1);
62.200 - c2a = new URLClassLoader(new URL[] {
62.201 - findJar("services-jar-2.jar"),
62.202 - }, c1);
62.203 - c3 = new URLClassLoader(new URL[] { findJar("services-jar-2.jar") },
62.204 - c0
62.205 - );
62.206 - c4 = new URLClassLoader(new URL[] {
62.207 - findJar("services-jar-1.jar"),
62.208 - findJar("services-jar-2.jar"),
62.209 - }, c0);
62.210 - }
62.211 -
62.212 - @Override
62.213 - protected void tearDown() throws Exception {
62.214 - Set<Reference<Lookup>> weak = new HashSet<Reference<Lookup>>();
62.215 - for (Lookup l : lookups.values()) {
62.216 - weak.add(new WeakReference<Lookup>(l));
62.217 - }
62.218 -
62.219 - lookups = null;
62.220 -
62.221 - for(Reference<Lookup> ref : weak) {
62.222 - assertGC("Lookup can disappear", ref);
62.223 - }
62.224 - }
62.225 -
62.226 - public void testBasicUsage() throws Exception {
62.227 - Lookup l = getTestedLookup(c2);
62.228 - Class<?> xface = c1.loadClass("org.foo.Interface");
62.229 - List<?> results = new ArrayList<Object>(l.lookupAll(xface));
62.230 - assertEquals("Two items in result: " + results, 2, results.size());
62.231 - // Note that they have to be in order:
62.232 - assertEquals("org.foo.impl.Implementation1", results.get(0).getClass().getName());
62.233 - assertEquals("org.bar.Implementation2", results.get(1).getClass().getName());
62.234 - // Make sure it does not gratuitously replace items:
62.235 - List<?> results2 = new ArrayList<Object>(l.lookupAll(xface));
62.236 - assertEquals(results, results2);
62.237 - }
62.238 -
62.239 - public void testLoaderSkew() throws Exception {
62.240 - Class<?> xface1 = c1.loadClass("org.foo.Interface");
62.241 - Lookup l3 = getTestedLookup(c3);
62.242 - // If we cannot load Interface, there should be no impls of course... quietly!
62.243 - assertEquals(Collections.emptyList(),
62.244 - new ArrayList<Object>(l3.lookupAll(xface1)));
62.245 - Lookup l4 = getTestedLookup(c4);
62.246 - // If we can load Interface but it is the wrong one, ignore it.
62.247 - assertEquals(Collections.emptyList(),
62.248 - new ArrayList<Object>(l4.lookupAll(xface1)));
62.249 - // Make sure l4 is really OK - it can load from its own JARs.
62.250 - Class<?> xface4 = c4.loadClass("org.foo.Interface");
62.251 - assertEquals(2, l4.lookupAll(xface4).size());
62.252 - }
62.253 -
62.254 - public void testStability() throws Exception {
62.255 - Lookup l = getTestedLookup(c2);
62.256 - Class<?> xface = c1.loadClass("org.foo.Interface");
62.257 - Object first = l.lookup(xface);
62.258 - assertEquals(first, l.lookupAll(xface).iterator().next());
62.259 - l = getTestedLookup(c2a);
62.260 - Object second = l.lookup(xface);
62.261 - assertEquals(first, second);
62.262 - }
62.263 -
62.264 - public void testMaskingOfResources() throws Exception {
62.265 - Lookup l1 = getTestedLookup(c1);
62.266 - Lookup l2 = getTestedLookup(c2);
62.267 - Lookup l4 = getTestedLookup(c4);
62.268 -
62.269 - assertNotNull("services1.jar defines a class that implements runnable", l1.lookup(Runnable.class));
62.270 - assertNull("services2.jar does not defines a class that implements runnable", l2.lookup(Runnable.class));
62.271 - assertNull("services1.jar defines Runnable, but services2.jar masks it out", l4.lookup(Runnable.class));
62.272 - }
62.273 -
62.274 - public void testOrdering() throws Exception {
62.275 - Lookup l = getTestedLookup(c1);
62.276 - Class<?> xface = c1.loadClass("java.util.Comparator");
62.277 - List<?> results = new ArrayList<Object>(l.lookupAll(xface));
62.278 - assertEquals(1, results.size());
62.279 -
62.280 - l = getTestedLookup(c2);
62.281 - xface = c2.loadClass("java.util.Comparator");
62.282 - results = new ArrayList<Object>(l.lookupAll(xface));
62.283 - assertEquals(2, results.size());
62.284 - // Test order:
62.285 - assertEquals("org.bar.Comparator2", results.get(0).getClass().getName());
62.286 - assertEquals("org.foo.impl.Comparator1", results.get(1).getClass().getName());
62.287 -
62.288 - // test that items without position are always at the end
62.289 - l = getTestedLookup(c2);
62.290 - xface = c2.loadClass("java.util.Iterator");
62.291 - results = new ArrayList<Object>(l.lookupAll(xface));
62.292 - assertEquals(2, results.size());
62.293 - // Test order:
62.294 - assertEquals("org.bar.Iterator2", results.get(0).getClass().getName());
62.295 - assertEquals("org.foo.impl.Iterator1", results.get(1).getClass().getName());
62.296 - }
62.297 -
62.298 - public void testNoCallToGetResourceForObjectIssue65124() throws Exception {
62.299 - class Loader extends ClassLoader {
62.300 - private int counter;
62.301 -
62.302 - @Override
62.303 - protected URL findResource(String name) {
62.304 - if (name.equals(prefix() + "java.lang.Object")) {
62.305 - counter++;
62.306 - }
62.307 -
62.308 - URL retValue;
62.309 -
62.310 - retValue = super.findResource(name);
62.311 - return retValue;
62.312 - }
62.313 -
62.314 - @Override
62.315 - protected Enumeration<URL> findResources(String name) throws IOException {
62.316 - if (name.equals(prefix() + "java.lang.Object")) {
62.317 - counter++;
62.318 - }
62.319 - return super.findResources(name);
62.320 - }
62.321 - }
62.322 - Loader loader = new Loader();
62.323 - Lookup l = getTestedLookup(loader);
62.324 -
62.325 - Object no = l.lookup(String.class);
62.326 - assertNull("Not found of course", no);
62.327 - assertEquals("No lookup of Object", 0, loader.counter);
62.328 - }
62.329 -
62.330 - public void testCanGarbageCollectClasses() throws Exception {
62.331 - class Loader extends ClassLoader {
62.332 - public Loader() {
62.333 - super(Loader.class.getClassLoader().getParent());
62.334 - }
62.335 -
62.336 - @Override
62.337 - protected URL findResource(String name) {
62.338 - if (name.equals(prefix() + "java.lang.Runnable")) {
62.339 - return Loader.class.getResource("MetaInfServicesLookupTestRunnable.txt");
62.340 - }
62.341 -
62.342 - URL retValue;
62.343 -
62.344 - retValue = super.findResource(name);
62.345 - return retValue;
62.346 - }
62.347 -
62.348 - @Override
62.349 - protected Class<?> findClass(String name) throws ClassNotFoundException {
62.350 - if (name.equals("org.openide.util.lookup.MetaInfServicesLookupTestRunnable")) {
62.351 - try {
62.352 - InputStream is = getClass().getResourceAsStream("MetaInfServicesLookupTestRunnable.class");
62.353 - byte[] arr = new byte[is.available()];
62.354 - int read = is.read(arr);
62.355 - assertEquals("Fully read", arr.length, read);
62.356 - return defineClass(name, arr, 0, arr.length);
62.357 - } catch (IOException ex) {
62.358 - throw new ClassNotFoundException("Cannot load", ex);
62.359 - }
62.360 - }
62.361 - throw new ClassNotFoundException();
62.362 - }
62.363 -
62.364 -
62.365 -
62.366 - @Override
62.367 - protected Enumeration<URL> findResources(String name) throws IOException {
62.368 - if (name.equals(prefix() + "java.lang.Runnable")) {
62.369 - return Collections.enumeration(Collections.singleton(findResource(name)));
62.370 - }
62.371 - return super.findResources(name);
62.372 - }
62.373 - }
62.374 - Loader loader = new Loader();
62.375 - Lookup l = getTestedLookup(loader);
62.376 -
62.377 -
62.378 - Object no = l.lookup(Runnable.class);
62.379 - assertNotNull("Found of course", no);
62.380 - assertEquals("The right name", "MetaInfServicesLookupTestRunnable", no.getClass().getSimpleName());
62.381 - if (no.getClass().getClassLoader() != loader) {
62.382 - fail("Wrong classloader: " + no.getClass().getClassLoader());
62.383 - }
62.384 -
62.385 - WeakReference<Object> ref = new WeakReference<Object>(no.getClass());
62.386 - loader = null;
62.387 - no = null;
62.388 - l = null;
62.389 - lookups.clear();
62.390 - MockLookup.setInstances();
62.391 - Thread.currentThread().setContextClassLoader(null);
62.392 - assertGC("Class can be garbage collected", ref);
62.393 - }
62.394 -
62.395 - public void testSuperTypes() throws Exception {
62.396 - doTestSuperTypes(createLookup(c2));
62.397 - doTestSuperTypes(new ProxyLookup(createLookup(c2)));
62.398 - }
62.399 - private void doTestSuperTypes(Lookup l) throws Exception {
62.400 - final Class<?> xface = c1.loadClass("org.foo.Interface");
62.401 - final Lookup.Result<Object> res = l.lookupResult(Object.class);
62.402 - assertEquals("Nothing yet", 0, res.allInstances().size());
62.403 - final AtomicBoolean event = new AtomicBoolean();
62.404 - final Thread here = Thread.currentThread();
62.405 - res.addLookupListener(new LookupListener() {
62.406 - public void resultChanged(LookupEvent ev) {
62.407 - if (Thread.currentThread() == here) {
62.408 - event.set(true);
62.409 - }
62.410 - }
62.411 - });
62.412 - assertNotNull("Interface found", l.lookup(xface));
62.413 - assertFalse(event.get());
62.414 - class W implements Runnable {
62.415 - boolean ok;
62.416 - public synchronized void run() {
62.417 - ok = true;
62.418 - notifyAll();
62.419 - }
62.420 -
62.421 - public synchronized void await() throws Exception {
62.422 - while (!ok) {
62.423 - wait();
62.424 - }
62.425 - }
62.426 - }
62.427 - W w = new W();
62.428 - MetaInfServicesLookup.RP.execute(w);
62.429 - w.await();
62.430 - assertEquals("Now two", 2, res.allInstances().size());
62.431 - }
62.432 -
62.433 - public void testWrongOrderAsInIssue100320() throws Exception {
62.434 - ClassLoader app = getClass().getClassLoader().getParent();
62.435 - ClassLoader c0 = app;
62.436 - ClassLoader ctmp = new URLClassLoader(new URL[] {
62.437 - findJar("problem100320.jar"),
62.438 - }, c0);
62.439 - Lookup lookup = Lookups.metaInfServices(ctmp, prefix());
62.440 -
62.441 - Collection<?> colAWT = lookup.lookupAll(IOException.class);
62.442 - assertEquals("There is enough objects to switch to InheritanceTree", 12, colAWT.size());
62.443 -
62.444 -
62.445 - List<?> col1 = new ArrayList<Object>(lookup.lookupAll(Comparator.class));
62.446 - assertEquals("Two", 2, col1.size());
62.447 - Collection<?> col2 = lookup.lookupAll(ctmp.loadClass(Comparator2.class.getName()));
62.448 - assertEquals("One", 1, col2.size());
62.449 - List<?> col3 = new ArrayList<Object>(lookup.lookupAll(Comparator.class));
62.450 - assertEquals("Two2", 2, col3.size());
62.451 -
62.452 - Iterator<?> it1 = col1.iterator();
62.453 - Iterator<?> it3 = col3.iterator();
62.454 - if (
62.455 - it1.next() != it3.next() ||
62.456 - it1.next() != it3.next()
62.457 - ) {
62.458 - fail("Collections are different:\nFirst: " + col1 + "\nLast: " + col3);
62.459 - }
62.460 - }
62.461 -
62.462 - public void testContentionWhenLoadingMetainfServices() throws Exception {
62.463 - class My extends ClassLoader implements Runnable {
62.464 - Lookup query;
62.465 - Integer value;
62.466 -
62.467 - public void run() {
62.468 - value = query.lookup(Integer.class);
62.469 - }
62.470 -
62.471 -
62.472 - @Override
62.473 - protected URL findResource(String name) {
62.474 - waitForTask(name);
62.475 - return super.findResource(name);
62.476 - }
62.477 -
62.478 - @Override
62.479 - protected Enumeration<URL> findResources(String name) throws IOException {
62.480 - waitForTask(name);
62.481 - return super.findResources(name);
62.482 - }
62.483 -
62.484 - private synchronized void waitForTask(String name) {
62.485 - if (name.startsWith(prefix()) && Thread.currentThread().getName().contains("block")) {
62.486 - try {
62.487 - wait();
62.488 - } catch (InterruptedException ex) {
62.489 - Logger.getLogger("global").log(Level.WARNING, "", ex);
62.490 - }
62.491 - }
62.492 - }
62.493 - }
62.494 -
62.495 - My loader = new My();
62.496 - loader.query = createLookup(loader);
62.497 - Thread t = new Thread(loader, "block when querying");
62.498 - t.start();
62.499 - t.join(1000);
62.500 -
62.501 - // this blocks waiting for the waitForTask to finish
62.502 - // right now
62.503 - Float f = loader.query.lookup(Float.class);
62.504 - assertNull("Nothing found", f);
62.505 -
62.506 - synchronized (loader) {
62.507 - loader.notifyAll();
62.508 - }
62.509 - t.join();
62.510 -
62.511 - assertNull("Nothing found", loader.value);
62.512 - }
62.513 -
62.514 - public void testInitializerRobustness() throws Exception { // #174055
62.515 - check(Broken1.class.getName());
62.516 - check(Broken2.class.getName());
62.517 - }
62.518 - private void check(final String n) {
62.519 - assertNull(Lookups.metaInfServices(new ClassLoader() {
62.520 - protected @Override Enumeration<URL> findResources(String name) throws IOException {
62.521 - if (name.equals("META-INF/services/java.lang.Object")) {
62.522 - return singleton(new URL(null, "dummy:stuff", new URLStreamHandler() {
62.523 - protected URLConnection openConnection(URL u) throws IOException {
62.524 - return new URLConnection(u) {
62.525 - public void connect() throws IOException {}
62.526 - public @Override InputStream getInputStream() throws IOException {
62.527 - return new ByteArrayInputStream(n.getBytes("UTF-8"));
62.528 - }
62.529 - };
62.530 - }
62.531 - }));
62.532 - } else {
62.533 - return Collections.enumeration(Collections.<URL>emptyList());
62.534 - }
62.535 - }
62.536 -
62.537 - }).lookup(Object.class));
62.538 - }
62.539 - public static class Broken1 {
62.540 - public Broken1() {
62.541 - throw new NullPointerException("broken1");
62.542 - }
62.543 - }
62.544 - public static class Broken2 {
62.545 - static {
62.546 - if (true) { // otherwise javac complains
62.547 - throw new NullPointerException("broken2");
62.548 - }
62.549 - }
62.550 - }
62.551 -
62.552 - static <T> Enumeration<T> singleton(T t) {
62.553 - return Collections.enumeration(Collections.singleton(t));
62.554 - }
62.555 -}
63.1 --- a/lookup/src/test/java/org/openide/util/lookup/MetaInfServicesLookupTestRunnable.java Wed Jan 27 17:46:23 2010 -0500
63.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
63.3 @@ -1,50 +0,0 @@
63.4 -/*
63.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
63.6 - *
63.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
63.8 - *
63.9 - * The contents of this file are subject to the terms of either the GNU
63.10 - * General Public License Version 2 only ("GPL") or the Common
63.11 - * Development and Distribution License("CDDL") (collectively, the
63.12 - * "License"). You may not use this file except in compliance with the
63.13 - * License. You can obtain a copy of the License at
63.14 - * http://www.netbeans.org/cddl-gplv2.html
63.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
63.16 - * specific language governing permissions and limitations under the
63.17 - * License. When distributing the software, include this License Header
63.18 - * Notice in each file and include the License file at
63.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
63.20 - * particular file as subject to the "Classpath" exception as provided
63.21 - * by Sun in the GPL Version 2 section of the License file that
63.22 - * accompanied this code. If applicable, add the following below the
63.23 - * License Header, with the fields enclosed by brackets [] replaced by
63.24 - * your own identifying information:
63.25 - * "Portions Copyrighted [year] [name of copyright owner]"
63.26 - *
63.27 - * Contributor(s):
63.28 - *
63.29 - * The Original Software is NetBeans. The Initial Developer of the Original
63.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
63.31 - * Microsystems, Inc. All Rights Reserved.
63.32 - *
63.33 - * If you wish your version of this file to be governed by only the CDDL
63.34 - * or only the GPL Version 2, indicate your decision by adding
63.35 - * "[Contributor] elects to include this software in this distribution
63.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
63.37 - * single choice of license, a recipient has the option to distribute
63.38 - * your version of this file under either the CDDL, the GPL Version 2 or
63.39 - * to extend the choice of license to its licensees as provided above.
63.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
63.41 - * Version 2 license, then the option applies only if the new code is
63.42 - * made subject to such option by the copyright holder.
63.43 - */
63.44 -
63.45 -package org.openide.util.lookup;
63.46 -
63.47 -
63.48 -/**
63.49 - */
63.50 -public final class MetaInfServicesLookupTestRunnable implements Runnable {
63.51 - public void run() {
63.52 - }
63.53 -}
64.1 --- a/lookup/src/test/java/org/openide/util/lookup/NamedServicesLookupTest.java Wed Jan 27 17:46:23 2010 -0500
64.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
64.3 @@ -1,85 +0,0 @@
64.4 -/*
64.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
64.6 - *
64.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
64.8 - *
64.9 - * The contents of this file are subject to the terms of either the GNU
64.10 - * General Public License Version 2 only ("GPL") or the Common
64.11 - * Development and Distribution License("CDDL") (collectively, the
64.12 - * "License"). You may not use this file except in compliance with the
64.13 - * License. You can obtain a copy of the License at
64.14 - * http://www.netbeans.org/cddl-gplv2.html
64.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
64.16 - * specific language governing permissions and limitations under the
64.17 - * License. When distributing the software, include this License Header
64.18 - * Notice in each file and include the License file at
64.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
64.20 - * particular file as subject to the "Classpath" exception as provided
64.21 - * by Sun in the GPL Version 2 section of the License file that
64.22 - * accompanied this code. If applicable, add the following below the
64.23 - * License Header, with the fields enclosed by brackets [] replaced by
64.24 - * your own identifying information:
64.25 - * "Portions Copyrighted [year] [name of copyright owner]"
64.26 - *
64.27 - * Contributor(s):
64.28 - *
64.29 - * The Original Software is NetBeans. The Initial Developer of the Original
64.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
64.31 - * Microsystems, Inc. All Rights Reserved.
64.32 - *
64.33 - * If you wish your version of this file to be governed by only the CDDL
64.34 - * or only the GPL Version 2, indicate your decision by adding
64.35 - * "[Contributor] elects to include this software in this distribution
64.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
64.37 - * single choice of license, a recipient has the option to distribute
64.38 - * your version of this file under either the CDDL, the GPL Version 2 or
64.39 - * to extend the choice of license to its licensees as provided above.
64.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
64.41 - * Version 2 license, then the option applies only if the new code is
64.42 - * made subject to such option by the copyright holder.
64.43 - */
64.44 -
64.45 -package org.openide.util.lookup;
64.46 -
64.47 -import org.openide.util.Lookup;
64.48 -import org.openide.util.test.MockLookup;
64.49 -
64.50 -
64.51 -/** Test finding services from manifest.
64.52 - * @author Jaroslav Tulach
64.53 - */
64.54 -public class NamedServicesLookupTest extends MetaInfServicesLookupTest {
64.55 - static {
64.56 - MockLookup.init();
64.57 - }
64.58 - public NamedServicesLookupTest(String name) {
64.59 - super(name);
64.60 - }
64.61 -
64.62 - @Override
64.63 - protected String prefix() {
64.64 - return "META-INF/namedservices/sub/path/";
64.65 - }
64.66 -
64.67 - @Override
64.68 - protected Lookup createLookup(ClassLoader c) {
64.69 - MockLookup.setInstances(c);
64.70 - Thread.currentThread().setContextClassLoader(c);
64.71 - Lookup l = Lookups.forPath("sub/path");
64.72 - return l;
64.73 - }
64.74 -
64.75 - //
64.76 - // this is not much inheriting test, as we mask most of the tested methods
64.77 - // anyway, but the infrastructure to generate the JAR files is useful
64.78 - //
64.79 -
64.80 - public @Override void testLoaderSkew() {}
64.81 - public @Override void testStability() throws Exception {}
64.82 - public @Override void testMaskingOfResources() throws Exception {}
64.83 - public @Override void testOrdering() throws Exception {}
64.84 - public @Override void testNoCallToGetResourceForObjectIssue65124() throws Exception {}
64.85 - public @Override void testSuperTypes() throws Exception {}
64.86 - public @Override void testWrongOrderAsInIssue100320() throws Exception {}
64.87 -
64.88 -}
65.1 --- a/lookup/src/test/java/org/openide/util/lookup/PathInLookupTest.java Wed Jan 27 17:46:23 2010 -0500
65.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
65.3 @@ -1,112 +0,0 @@
65.4 -/*
65.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
65.6 - *
65.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
65.8 - *
65.9 - * The contents of this file are subject to the terms of either the GNU
65.10 - * General Public License Version 2 only ("GPL") or the Common
65.11 - * Development and Distribution License("CDDL") (collectively, the
65.12 - * "License"). You may not use this file except in compliance with the
65.13 - * License. You can obtain a copy of the License at
65.14 - * http://www.netbeans.org/cddl-gplv2.html
65.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
65.16 - * specific language governing permissions and limitations under the
65.17 - * License. When distributing the software, include this License Header
65.18 - * Notice in each file and include the License file at
65.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
65.20 - * particular file as subject to the "Classpath" exception as provided
65.21 - * by Sun in the GPL Version 2 section of the License file that
65.22 - * accompanied this code. If applicable, add the following below the
65.23 - * License Header, with the fields enclosed by brackets [] replaced by
65.24 - * your own identifying information:
65.25 - * "Portions Copyrighted [year] [name of copyright owner]"
65.26 - *
65.27 - * Contributor(s):
65.28 - *
65.29 - * The Original Software is NetBeans. The Initial Developer of the Original
65.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
65.31 - * Microsystems, Inc. All Rights Reserved.
65.32 - *
65.33 - * If you wish your version of this file to be governed by only the CDDL
65.34 - * or only the GPL Version 2, indicate your decision by adding
65.35 - * "[Contributor] elects to include this software in this distribution
65.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
65.37 - * single choice of license, a recipient has the option to distribute
65.38 - * your version of this file under either the CDDL, the GPL Version 2 or
65.39 - * to extend the choice of license to its licensees as provided above.
65.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
65.41 - * Version 2 license, then the option applies only if the new code is
65.42 - * made subject to such option by the copyright holder.
65.43 - */
65.44 -
65.45 -package org.openide.util.lookup;
65.46 -
65.47 -import java.util.logging.Level;
65.48 -import org.netbeans.junit.MockServices;
65.49 -import org.netbeans.junit.NbTestCase;
65.50 -import org.netbeans.modules.openide.util.NamedServicesProvider;
65.51 -import org.openide.util.Lookup;
65.52 -
65.53 -/**
65.54 - * @author Jaroslav Tulach
65.55 - */
65.56 -public class PathInLookupTest extends NbTestCase {
65.57 - static {
65.58 - System.setProperty("org.openide.util.Lookup.paths", "MyServices:YourServices");
65.59 - MockServices.setServices(P.class);
65.60 - Lookup.getDefault();
65.61 - }
65.62 -
65.63 - public PathInLookupTest(String name) {
65.64 - super(name);
65.65 - }
65.66 -
65.67 - @Override
65.68 - protected Level logLevel() {
65.69 - return Level.FINE;
65.70 - }
65.71 -
65.72 - public void testInterfaceFoundInMyServices() throws Exception {
65.73 - assertNull("not found", Lookup.getDefault().lookup(Shared.class));
65.74 - Shared v = new Shared();
65.75 - P.ic1.add(v);
65.76 - assertNotNull("found", Lookup.getDefault().lookup(Shared.class));
65.77 - P.ic1.remove(v);
65.78 - assertNull("not found again", Lookup.getDefault().lookup(Shared.class));
65.79 - }
65.80 - public void testInterfaceFoundInMyServices2() throws Exception {
65.81 - assertNull("not found", Lookup.getDefault().lookup(Shared.class));
65.82 - Shared v = new Shared();
65.83 - P.ic2.add(v);
65.84 - assertNotNull("found", Lookup.getDefault().lookup(Shared.class));
65.85 - P.ic2.remove(v);
65.86 - assertNull("not found again", Lookup.getDefault().lookup(Shared.class));
65.87 - }
65.88 -
65.89 - static final class Shared extends Object {}
65.90 -
65.91 - public static final class P extends NamedServicesProvider {
65.92 - static InstanceContent ic1 = new InstanceContent();
65.93 - static InstanceContent ic2 = new InstanceContent();
65.94 - static AbstractLookup[] arr = {
65.95 - new AbstractLookup(ic1), new AbstractLookup(ic2)
65.96 - };
65.97 -
65.98 -
65.99 - @Override
65.100 - public Lookup create(String path) {
65.101 - int indx = -1;
65.102 - if (path.equals("MyServices/")) {
65.103 - indx = 0;
65.104 - }
65.105 - if (path.equals("YourServices/")) {
65.106 - indx = 1;
65.107 - }
65.108 - if (indx == -1) {
65.109 - fail("Unexpected lookup query: " + path);
65.110 - }
65.111 - return arr[indx];
65.112 - }
65.113 - }
65.114 -
65.115 -}
66.1 --- a/lookup/src/test/java/org/openide/util/lookup/PrefixServicesLookupTest.java Wed Jan 27 17:46:23 2010 -0500
66.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
66.3 @@ -1,63 +0,0 @@
66.4 -/*
66.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
66.6 - *
66.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
66.8 - *
66.9 - * The contents of this file are subject to the terms of either the GNU
66.10 - * General Public License Version 2 only ("GPL") or the Common
66.11 - * Development and Distribution License("CDDL") (collectively, the
66.12 - * "License"). You may not use this file except in compliance with the
66.13 - * License. You can obtain a copy of the License at
66.14 - * http://www.netbeans.org/cddl-gplv2.html
66.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
66.16 - * specific language governing permissions and limitations under the
66.17 - * License. When distributing the software, include this License Header
66.18 - * Notice in each file and include the License file at
66.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
66.20 - * particular file as subject to the "Classpath" exception as provided
66.21 - * by Sun in the GPL Version 2 section of the License file that
66.22 - * accompanied this code. If applicable, add the following below the
66.23 - * License Header, with the fields enclosed by brackets [] replaced by
66.24 - * your own identifying information:
66.25 - * "Portions Copyrighted [year] [name of copyright owner]"
66.26 - *
66.27 - * Contributor(s):
66.28 - *
66.29 - * The Original Software is NetBeans. The Initial Developer of the Original
66.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
66.31 - * Microsystems, Inc. All Rights Reserved.
66.32 - *
66.33 - * If you wish your version of this file to be governed by only the CDDL
66.34 - * or only the GPL Version 2, indicate your decision by adding
66.35 - * "[Contributor] elects to include this software in this distribution
66.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
66.37 - * single choice of license, a recipient has the option to distribute
66.38 - * your version of this file under either the CDDL, the GPL Version 2 or
66.39 - * to extend the choice of license to its licensees as provided above.
66.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
66.41 - * Version 2 license, then the option applies only if the new code is
66.42 - * made subject to such option by the copyright holder.
66.43 - */
66.44 -
66.45 -package org.openide.util.lookup;
66.46 -
66.47 -import org.openide.util.Lookup;
66.48 -
66.49 -
66.50 -/** Test finding services from manifest.
66.51 - * @author Jaroslav Tulach
66.52 - */
66.53 -public class PrefixServicesLookupTest extends MetaInfServicesLookupTest {
66.54 - public PrefixServicesLookupTest(String name) {
66.55 - super(name);
66.56 - }
66.57 -
66.58 - protected String prefix() {
66.59 - return "META-INF/netbeans/prefix/services/test/";
66.60 - }
66.61 -
66.62 - protected Lookup createLookup(ClassLoader c) {
66.63 - return Lookups.metaInfServices(c, prefix());
66.64 - }
66.65 -
66.66 -}
67.1 --- a/lookup/src/test/java/org/openide/util/lookup/ProxyLookup173975Test.java Wed Jan 27 17:46:23 2010 -0500
67.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
67.3 @@ -1,108 +0,0 @@
67.4 -/*
67.5 - * To change this template, choose Tools | Templates
67.6 - * and open the template in the editor.
67.7 - */
67.8 -package org.openide.util.lookup;
67.9 -
67.10 -import java.util.Collection;
67.11 -import java.util.Collections;
67.12 -import org.junit.Assert;
67.13 -import org.junit.Test;
67.14 -import org.openide.util.Lookup;
67.15 -import org.openide.util.LookupEvent;
67.16 -import org.openide.util.LookupListener;
67.17 -import org.openide.util.lookup.AbstractLookup.Storage;
67.18 -
67.19 -public class ProxyLookup173975Test {
67.20 -
67.21 - public ProxyLookup173975Test() {
67.22 - }
67.23 -
67.24 - boolean called = false;
67.25 -
67.26 - @Test
67.27 - public void testAbstractLookupWithoutAllInstances() {
67.28 - registerLookupListenerAndAddSomething(false, false, false);
67.29 - }
67.30 -
67.31 - @Test
67.32 - public void testAbstractLookupWithAllInstances() {
67.33 - registerLookupListenerAndAddSomething(false, true, false);
67.34 - }
67.35 -
67.36 - @Test
67.37 - public void testAbstractLookupInheritanceTreeWithoutAllInstances() {
67.38 - registerLookupListenerAndAddSomething(false, false, true);
67.39 - }
67.40 -
67.41 - @Test
67.42 - public void testAbstractLookupInheritanceTreeWithAllInstances() {
67.43 - registerLookupListenerAndAddSomething(false, true, true);
67.44 - }
67.45 -
67.46 - @Test
67.47 - public void testProxyLookupWithoutAllInstances() {
67.48 - registerLookupListenerAndAddSomething(true, false, false);
67.49 - }
67.50 -
67.51 - @Test
67.52 - public void testProxyLookupWithAllInstances() {
67.53 - registerLookupListenerAndAddSomething(true, true, false);
67.54 - }
67.55 -
67.56 - @Test
67.57 - public void testProxyLookupInheritanceTreeWithoutAllInstances() {
67.58 - registerLookupListenerAndAddSomething(true, false, true);
67.59 - }
67.60 -
67.61 - @Test
67.62 - public void testProxyLookupInheritanceTreeWithAllInstances() {
67.63 - registerLookupListenerAndAddSomething(true, true, true);
67.64 - }
67.65 -
67.66 - private void registerLookupListenerAndAddSomething(boolean useProxy, boolean callAllInstances, boolean inheritanceTree) {
67.67 - called = false;
67.68 - InstanceContent aInstanceContent = new InstanceContent();
67.69 - Storage<?> s = inheritanceTree ? new InheritanceTree() : new ArrayStorage();
67.70 - Lookup aLookup = new AbstractLookup(aInstanceContent, s);
67.71 - if (useProxy) {
67.72 - aLookup = new ProxyLookup(aLookup);
67.73 - }
67.74 - Lookup.Result<ObjectInLookup> result = aLookup.lookupResult(ObjectInLookup.class);
67.75 - if (callAllInstances) {
67.76 - result.allInstances(); // TO GET SUCCESS
67.77 - }
67.78 - result.addLookupListener(new LookupListener() {
67.79 -
67.80 - public void resultChanged(LookupEvent ev) {
67.81 - Lookup.Result aResult = (Lookup.Result) ev.getSource();
67.82 - Collection c = aResult.allInstances();
67.83 - if (!c.isEmpty()) {
67.84 - called = true;
67.85 - }
67.86 - }
67.87 - });
67.88 -
67.89 - aInstanceContent.set(Collections.singleton(
67.90 - new ObjectInLookup("Set Object in Lookup)")), null);
67.91 - Assert.assertTrue("Listener was notified", called);
67.92 - }
67.93 -
67.94 - public class ObjectInLookup {
67.95 -
67.96 - private final String name;
67.97 -
67.98 - public ObjectInLookup(String name) {
67.99 - this.name = name;
67.100 - }
67.101 -
67.102 - public String getName() {
67.103 - return this.name;
67.104 - }
67.105 -
67.106 - @Override
67.107 - public String toString() {
67.108 - return "objectinlookup:" + getName();
67.109 - }
67.110 - }
67.111 -}
68.1 --- a/lookup/src/test/java/org/openide/util/lookup/ProxyLookupEventIssue136866Test.java Wed Jan 27 17:46:23 2010 -0500
68.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
68.3 @@ -1,56 +0,0 @@
68.4 -package org.openide.util.lookup;
68.5 -
68.6 -import junit.framework.TestCase;
68.7 -import org.openide.util.Lookup;
68.8 -import org.openide.util.LookupEvent;
68.9 -import org.openide.util.LookupListener;
68.10 -
68.11 -/**
68.12 - * Test case which demonstrates that ProxyLookup does not fire
68.13 - * an event when it should.
68.14 - */
68.15 -public class ProxyLookupEventIssue136866Test extends TestCase {
68.16 -
68.17 - public ProxyLookupEventIssue136866Test(String testName) {
68.18 - super(testName);
68.19 - }
68.20 -
68.21 - public void testAbstractLookupFiresEventWhenContentChanged() {
68.22 - InstanceContent ic = new InstanceContent();
68.23 - AbstractLookup al = new AbstractLookup(ic);
68.24 -
68.25 - final int[] counts = {0}; // Number of items observed upon a LookupEvent
68.26 - final Lookup.Result<String> result = al.lookupResult(String.class);
68.27 -
68.28 - result.addLookupListener(new LookupListener() {
68.29 - public void resultChanged(LookupEvent ev) {
68.30 - // this gets called as expected
68.31 - assertSame(result, ev.getSource());
68.32 - counts[0] = result.allInstances().size();
68.33 - }
68.34 - });
68.35 -
68.36 - ic.add("hello1");
68.37 - assertEquals(1, counts[0]);
68.38 - }
68.39 -
68.40 - public void testProxyLookupFailsToFireEventWhenProxiedLookupChanged() {
68.41 - InstanceContent ic = new InstanceContent();
68.42 -// AbstractLookup al = new AbstractLookup(ic);
68.43 - Lookup proxy = new AbstractLookup(ic);
68.44 -
68.45 - final int[] counts = {0}; // Number of items observed upon a LookupEvent
68.46 - final Lookup.Result<String> result = proxy.lookupResult(String.class);
68.47 -
68.48 - result.addLookupListener(new LookupListener() {
68.49 - public void resultChanged(LookupEvent ev) {
68.50 - // this should be called but never is
68.51 - assertSame(result, ev.getSource());
68.52 - counts[0] = result.allInstances().size();
68.53 - }
68.54 - });
68.55 -
68.56 - ic.add("hello1");
68.57 - assertEquals(1, counts[0]);
68.58 - }
68.59 -}
69.1 --- a/lookup/src/test/java/org/openide/util/lookup/ProxyLookupTest.java Wed Jan 27 17:46:23 2010 -0500
69.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
69.3 @@ -1,655 +0,0 @@
69.4 -/*
69.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
69.6 - *
69.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
69.8 - *
69.9 - * The contents of this file are subject to the terms of either the GNU
69.10 - * General Public License Version 2 only ("GPL") or the Common
69.11 - * Development and Distribution License("CDDL") (collectively, the
69.12 - * "License"). You may not use this file except in compliance with the
69.13 - * License. You can obtain a copy of the License at
69.14 - * http://www.netbeans.org/cddl-gplv2.html
69.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
69.16 - * specific language governing permissions and limitations under the
69.17 - * License. When distributing the software, include this License Header
69.18 - * Notice in each file and include the License file at
69.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
69.20 - * particular file as subject to the "Classpath" exception as provided
69.21 - * by Sun in the GPL Version 2 section of the License file that
69.22 - * accompanied this code. If applicable, add the following below the
69.23 - * License Header, with the fields enclosed by brackets [] replaced by
69.24 - * your own identifying information:
69.25 - * "Portions Copyrighted [year] [name of copyright owner]"
69.26 - *
69.27 - * Contributor(s):
69.28 - *
69.29 - * The Original Software is NetBeans. The Initial Developer of the Original
69.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
69.31 - * Microsystems, Inc. All Rights Reserved.
69.32 - *
69.33 - * If you wish your version of this file to be governed by only the CDDL
69.34 - * or only the GPL Version 2, indicate your decision by adding
69.35 - * "[Contributor] elects to include this software in this distribution
69.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
69.37 - * single choice of license, a recipient has the option to distribute
69.38 - * your version of this file under either the CDDL, the GPL Version 2 or
69.39 - * to extend the choice of license to its licensees as provided above.
69.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
69.41 - * Version 2 license, then the option applies only if the new code is
69.42 - * made subject to such option by the copyright holder.
69.43 - */
69.44 -
69.45 -package org.openide.util.lookup;
69.46 -
69.47 -import java.io.Serializable;
69.48 -
69.49 -import java.lang.ref.Reference;
69.50 -import java.lang.ref.WeakReference;
69.51 -import java.util.*;
69.52 -import java.util.concurrent.Executor;
69.53 -import junit.framework.*;
69.54 -import org.netbeans.junit.*;
69.55 -import org.netbeans.modules.openide.util.ActiveQueue;
69.56 -import org.openide.util.Lookup;
69.57 -import org.openide.util.Lookup.Result;
69.58 -import org.openide.util.LookupEvent;
69.59 -import org.openide.util.LookupListener;
69.60 -
69.61 -/** Runs all NbLookupTest tests on ProxyLookup and adds few additional.
69.62 - */
69.63 -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
69.64 -public class ProxyLookupTest extends AbstractLookupBaseHid
69.65 -implements AbstractLookupBaseHid.Impl {
69.66 - public ProxyLookupTest(java.lang.String testName) {
69.67 - super(testName, null);
69.68 - }
69.69 -
69.70 - public static Test suite() {
69.71 - return new NbTestSuite (ProxyLookupTest.class);
69.72 -// return new ProxyLookupTest("testDuplicatedLookupArrayIndexWithSetLookupAsInIssue123679");
69.73 - }
69.74 -
69.75 - /** Creates an lookup for given lookup. This class just returns
69.76 - * the object passed in, but subclasses can be different.
69.77 - * @param lookup in lookup
69.78 - * @return a lookup to use
69.79 - */
69.80 - public Lookup createLookup (Lookup lookup) {
69.81 - return new ProxyLookup (new Lookup[] { lookup });
69.82 - }
69.83 -
69.84 - public Lookup createInstancesLookup (InstanceContent ic) {
69.85 - return new AbstractLookup (ic);
69.86 - }
69.87 -
69.88 -
69.89 - public void clearCaches () {
69.90 - }
69.91 -
69.92 -
69.93 - /** Check whether setLookups method does not fire when there is no
69.94 - * change in the lookups.
69.95 - */
69.96 - public void testProxyListener () {
69.97 - ProxyLookup lookup = new ProxyLookup (new Lookup[0]);
69.98 -
69.99 - final Lookup.Template<Object> template = new Lookup.Template<Object>(Object.class);
69.100 - final Object[] IGNORE = {
69.101 - ProxyLookup.ImmutableInternalData.EMPTY,
69.102 - ProxyLookup.ImmutableInternalData.EMPTY_ARR,
69.103 - ActiveQueue.queue(),
69.104 - Collections.emptyMap(),
69.105 - Collections.emptyList(),
69.106 - Collections.emptySet()
69.107 - };
69.108 -
69.109 - assertSize("Pretty small", Collections.singleton(lookup), 16, IGNORE);
69.110 -
69.111 - Lookup.Result<Object> res = lookup.lookup (template);
69.112 -
69.113 - assertSize("Bigger", Collections.singleton(lookup), 216, IGNORE);
69.114 -
69.115 - LL ll = new LL ();
69.116 - res.addLookupListener (ll);
69.117 - Collection allRes = res.allInstances ();
69.118 -
69.119 - lookup.setLookups (new Lookup[0]);
69.120 -
69.121 - if (ll.getCount () != 0) {
69.122 - fail ("Calling setLookups (emptyarray) fired a change");
69.123 - }
69.124 -
69.125 - InstanceContent t = new InstanceContent();
69.126 - Lookup del = new AbstractLookup (t);
69.127 - t.add("Ahoj");
69.128 - lookup.setLookups (new Lookup[] { del });
69.129 -
69.130 - if (ll.getCount () != 1) {
69.131 - fail ("Changing lookups did not generate an event");
69.132 - }
69.133 -
69.134 - lookup.setLookups (new Lookup[] { del });
69.135 -
69.136 - if (ll.getCount () != 0) {
69.137 - fail ("Calling setLookups (thesamearray) fired a change");
69.138 - }
69.139 - }
69.140 -
69.141 - public void testNoListenersProxyListener () {
69.142 - ProxyLookup lookup = new ProxyLookup (new Lookup[0]);
69.143 - class E implements Executor {
69.144 - Runnable r;
69.145 - public void execute(Runnable command) {
69.146 - assertNull("NO previous", r);
69.147 - r = command;
69.148 - }
69.149 - public void perform() {
69.150 - assertNotNull("We shall have a runnable", r);
69.151 - r.run();
69.152 - r = null;
69.153 - }
69.154 - }
69.155 - E executor = new E();
69.156 -
69.157 -
69.158 - final Lookup.Template<Object> template = new Lookup.Template<Object>(Object.class);
69.159 - final Object[] IGNORE = {
69.160 - ProxyLookup.ImmutableInternalData.EMPTY,
69.161 - ProxyLookup.ImmutableInternalData.EMPTY_ARR,
69.162 - ActiveQueue.queue(),
69.163 - Collections.emptyMap(),
69.164 - Collections.emptyList(),
69.165 - Collections.emptySet()
69.166 - };
69.167 -
69.168 - assertSize("Pretty small", Collections.singleton(lookup), 16, IGNORE);
69.169 -
69.170 - Lookup.Result<Object> res = lookup.lookup (template);
69.171 -
69.172 - assertSize("Bigger", Collections.singleton(lookup), 216, IGNORE);
69.173 -
69.174 - LL ll = new LL ();
69.175 - res.addLookupListener (ll);
69.176 - Collection allRes = res.allInstances ();
69.177 -
69.178 - lookup.setLookups (executor, new Lookup[0]);
69.179 - if (ll.getCount () != 0) {
69.180 - fail ("Calling setLookups (emptyarray) fired a change");
69.181 - }
69.182 -
69.183 - InstanceContent t = new InstanceContent();
69.184 - Lookup del = new AbstractLookup (t);
69.185 - t.add("Ahoj");
69.186 - lookup.setLookups (executor, new Lookup[] { del });
69.187 - assertEquals("No change yet", 0, ll.getCount());
69.188 - executor.perform();
69.189 - if (ll.getCount () != 1) {
69.190 - fail ("Changing lookups did not generate an event");
69.191 - }
69.192 -
69.193 - lookup.setLookups (executor, new Lookup[] { del });
69.194 - if (ll.getCount () != 0) {
69.195 - fail ("Calling setLookups (thesamearray) fired a change");
69.196 - }
69.197 - }
69.198 -
69.199 - public void testSetLookups () throws Exception {
69.200 - AbstractLookup a1 = new AbstractLookup (new InstanceContent ());
69.201 - AbstractLookup a2 = new AbstractLookup (new InstanceContent ());
69.202 -
69.203 - InstanceContent i3 = new InstanceContent ();
69.204 - i3.add (i3);
69.205 - AbstractLookup a3 = new AbstractLookup (i3);
69.206 -
69.207 - final ProxyLookup p = new ProxyLookup (new Lookup[] { a1, a2 });
69.208 - final Lookup.Result res1 = p.lookup (new Lookup.Template (Object.class));
69.209 - Collection c1 = res1.allInstances();
69.210 -
69.211 - Lookup.Result res2 = p.lookup (new Lookup.Template (String.class));
69.212 - Collection c2 = res2.allInstances ();
69.213 -
69.214 -
69.215 - assertTrue ("We need two results", res1 != res2);
69.216 -
69.217 - final Object blocked = new Object ();
69.218 -
69.219 - class L extends Object implements LookupListener {
69.220 - public void resultChanged (LookupEvent ev) {
69.221 - try {
69.222 - res1.removeLookupListener(this);
69.223 -
69.224 - // waiting for second thread to start #111#
69.225 - blocked.wait ();
69.226 -
69.227 - } catch (Exception ex) {
69.228 - ex.printStackTrace();
69.229 - fail ("An exception occured ");
69.230 - }
69.231 - }
69.232 - }
69.233 -
69.234 - final L listener1 = new L ();
69.235 - res1.addLookupListener (listener1);
69.236 -
69.237 -
69.238 - Runnable newLookupSetter = new Runnable() {
69.239 - public void run () {
69.240 - synchronized (blocked) {
69.241 - try {
69.242 - p.setLookups (new Lookup[0]);
69.243 - } catch (Exception ex) {
69.244 - ex.printStackTrace();
69.245 - fail ("setLookups failed.");
69.246 - } finally {
69.247 - // starts the main thread #111#
69.248 - blocked.notify ();
69.249 - }
69.250 - }
69.251 - }
69.252 - };
69.253 -
69.254 - synchronized (blocked) {
69.255 - new Thread (newLookupSetter).start ();
69.256 -
69.257 - p.setLookups (new Lookup[] { a1, a2, a3 });
69.258 - }
69.259 - }
69.260 -
69.261 - public void testProxyLookupTemplateCaching(){
69.262 - Lookup lookups[] = new Lookup[1];
69.263 - doProxyLookupTemplateCaching(lookups, false);
69.264 - }
69.265 -
69.266 - public void testProxyLookupTemplateCachingOnSizeTwoArray() {
69.267 - Lookup lookups[] = new Lookup[2];
69.268 - lookups[1] = Lookup.EMPTY;
69.269 - doProxyLookupTemplateCaching(lookups, false);
69.270 - }
69.271 - public void testProxyLookupShallNotAllowModificationOfGetLookups(){
69.272 - Lookup lookups[] = new Lookup[1];
69.273 - doProxyLookupTemplateCaching(lookups, true);
69.274 - }
69.275 -
69.276 - public void testProxyLookupShallNotAllowModificationOfGetLookupsOnSizeTwoArray() {
69.277 - Lookup lookups[] = new Lookup[2];
69.278 - lookups[1] = Lookup.EMPTY;
69.279 - doProxyLookupTemplateCaching(lookups, true);
69.280 - }
69.281 -
69.282 - /** Index 0 of lookups will be modified, the rest is up to the
69.283 - * setup code.
69.284 - */
69.285 - private void doProxyLookupTemplateCaching(Lookup[] lookups, boolean reget) {
69.286 - // Create MyProxyLookup with one lookup containing the String object
69.287 - InstanceContent inst = new InstanceContent();
69.288 - inst.add(new String("Hello World")); //NOI18N
69.289 - lookups[0] = new AbstractLookup(inst);
69.290 - ProxyLookup proxy = new ProxyLookup(lookups);
69.291 - if (reget) {
69.292 - lookups = proxy.getLookups();
69.293 - }
69.294 -
69.295 - // Performing template lookup for String object
69.296 - Lookup.Result result = proxy.lookup(new Lookup.Template(String.class, null, null));
69.297 - int stringTemplateResultSize = result.allInstances().size();
69.298 - assertEquals ("Ensure, there is only one instance of String.class in proxyLookup:", //NOI18N
69.299 - 1, stringTemplateResultSize);
69.300 -
69.301 - // Changing lookup in proxy lookup, now it will contain
69.302 - // StringBuffer Object instead of String
69.303 - InstanceContent ic2 = new InstanceContent();
69.304 - ic2.add(new Integer(1234567890));
69.305 - lookups[0] = new AbstractLookup(ic2);
69.306 - proxy.setLookups(lookups);
69.307 -
69.308 - assertEquals ("the old result is updated", 0, result.allInstances().size());
69.309 -
69.310 - // Instance of String.class should not appear in proxyLookup
69.311 - Lookup.Result r2 = proxy.lookup(new Lookup.Template(String.class, null, null));
69.312 - assertEquals ("Instance of String.class should not appear in proxyLookup:", //NOI18N
69.313 - 0, r2.allInstances().size());
69.314 -
69.315 - Lookup.Result r3 = proxy.lookup(new Lookup.Template(Integer.class, null, null));
69.316 - assertEquals ("There is only one instance of Integer.class in proxyLookup:", //NOI18N
69.317 - 1, r3.allInstances().size());
69.318 - }
69.319 -
69.320 - public void testListeningAndQueryingByTwoListenersInstancesSetLookups() {
69.321 - doListeningAndQueryingByTwoListenersSetLookups(0, 1);
69.322 - }
69.323 - public void testListeningAndQueryingByTwoListenersClassesSetLookups() {
69.324 - doListeningAndQueryingByTwoListenersSetLookups(1, 1);
69.325 - }
69.326 - public void testListeningAndQueryingByTwoListenersItemsSetLookups() {
69.327 - doListeningAndQueryingByTwoListenersSetLookups(2, 1);
69.328 - }
69.329 -
69.330 - public void testListeningAndQueryingByTwoListenersInstancesSetLookups2() {
69.331 - doListeningAndQueryingByTwoListenersSetLookups(0, 2);
69.332 - }
69.333 - public void testListeningAndQueryingByTwoListenersClassesSetLookups2() {
69.334 - doListeningAndQueryingByTwoListenersSetLookups(1, 2);
69.335 - }
69.336 - public void testListeningAndQueryingByTwoListenersItemsSetLookups2() {
69.337 - doListeningAndQueryingByTwoListenersSetLookups(2, 2);
69.338 - }
69.339 - public void testListeningAndQueryingByTwoListenersInstancesSetLookups22() {
69.340 - doListeningAndQueryingByTwoListenersSetLookups(0, 22);
69.341 - }
69.342 - public void testListeningAndQueryingByTwoListenersClassesSetLookups22() {
69.343 - doListeningAndQueryingByTwoListenersSetLookups(1, 22);
69.344 - }
69.345 - public void testListeningAndQueryingByTwoListenersItemsSetLookups22() {
69.346 - doListeningAndQueryingByTwoListenersSetLookups(2, 22);
69.347 - }
69.348 -
69.349 - private void doListeningAndQueryingByTwoListenersSetLookups(final int type, int depth) {
69.350 - ProxyLookup orig = new ProxyLookup();
69.351 - ProxyLookup on = orig;
69.352 -
69.353 - while (--depth > 0) {
69.354 - on = new ProxyLookup(new Lookup[] { on });
69.355 - }
69.356 -
69.357 -
69.358 - final ProxyLookup lookup = on;
69.359 -
69.360 - class L implements LookupListener {
69.361 - Lookup.Result integer = lookup.lookup(new Lookup.Template(Integer.class));
69.362 - Lookup.Result number = lookup.lookup(new Lookup.Template(Number.class));
69.363 - Lookup.Result serial = lookup.lookup(new Lookup.Template(Serializable.class));
69.364 -
69.365 - {
69.366 - integer.addLookupListener(this);
69.367 - number.addLookupListener(this);
69.368 - serial.addLookupListener(this);
69.369 - }
69.370 -
69.371 - int round;
69.372 -
69.373 - public void resultChanged(LookupEvent ev) {
69.374 - Collection c1 = get(type, integer);
69.375 - Collection c2 = get(type, number);
69.376 - Collection c3 = get(type, serial);
69.377 -
69.378 - assertEquals("round " + round + " c1 vs. c2", c1, c2);
69.379 - assertEquals("round " + round + " c1 vs. c3", c1, c3);
69.380 - assertEquals("round " + round + " c2 vs. c3", c2, c3);
69.381 -
69.382 - round++;
69.383 - }
69.384 -
69.385 - private Collection get(int type, Lookup.Result res) {
69.386 - Collection c;
69.387 - switch(type) {
69.388 - case 0: c = res.allInstances(); break;
69.389 - case 1: c = res.allClasses(); break;
69.390 - case 2: c = res.allItems(); break;
69.391 - default: c = null; fail("Type: " + type); break;
69.392 - }
69.393 -
69.394 - assertNotNull(c);
69.395 - return new ArrayList(c);
69.396 - }
69.397 - }
69.398 -
69.399 - L listener = new L();
69.400 - listener.resultChanged(null);
69.401 - ArrayList arr = new ArrayList();
69.402 - for(int i = 0; i < 100; i++) {
69.403 - arr.add(new Integer(i));
69.404 -
69.405 - orig.setLookups(new Lookup[] { Lookups.fixed(arr.toArray()) });
69.406 - }
69.407 -
69.408 - assertEquals("3x100+1 checks", 301, listener.round);
69.409 - }
69.410 -
69.411 - static Object holder;
69.412 -
69.413 - public void testProxyWithLiveResultCanBeCollected() {
69.414 - Lookup layer0 = Lookups.singleton("Hello");
69.415 - Lookup layer1 = new ProxyLookup(new Lookup[] { layer0 });
69.416 - Lookup layer2 = new ProxyLookup(new Lookup[] { layer1 });
69.417 - Lookup.Result result1 = layer1.lookup(new Lookup.Template(String.class));
69.418 -
69.419 - assertEquals("One instance", 1, result1.allInstances().size());
69.420 -
69.421 - // this will create ProxyLookup$R which listens on origResult
69.422 - Lookup.Result result2 = layer2.lookup(new Lookup.Template(String.class));
69.423 -
69.424 - // this line is necessary. W/o actually querying the result,
69.425 - // it will nether compute it nor attach the listener.
69.426 - assertEquals("One instance", 1, result2.allInstances().size());
69.427 -
69.428 - result2.addLookupListener(new LookupListener() {
69.429 - public void resultChanged(LookupEvent ev) {}
69.430 - });
69.431 -
69.432 - Reference ref = new WeakReference(layer2);
69.433 - layer2 = null;
69.434 - result2 = null;
69.435 - try {
69.436 - holder = result1;
69.437 - assertGC ("The proxy lookup not been garbage collected!", ref);
69.438 - } finally {
69.439 - holder = null;
69.440 - }
69.441 - }
69.442 -
69.443 - public void testArrayIndexAsInIssue119292() throws Exception {
69.444 - final ProxyLookup pl = new ProxyLookup();
69.445 - final int[] cnt = { 0 };
69.446 -
69.447 - class L extends Lookup {
69.448 - L[] set;
69.449 - Lookup l;
69.450 -
69.451 - public L(String s) {
69.452 - l = Lookups.singleton(s);
69.453 - }
69.454 -
69.455 - @Override
69.456 - public <T> T lookup(Class<T> clazz) {
69.457 - return l.lookup(clazz);
69.458 - }
69.459 -
69.460 - @Override
69.461 - public <T> Result<T> lookup(Template<T> template) {
69.462 - return l.lookup(template);
69.463 - }
69.464 -
69.465 - @Override
69.466 - @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
69.467 - public boolean equals(Object obj) {
69.468 - if (set != null) {
69.469 - cnt[0]++;
69.470 - pl.setLookups(set);
69.471 - }
69.472 - return super.equals(obj);
69.473 - }
69.474 -
69.475 - @Override
69.476 - public int hashCode() {
69.477 - int hash = 3;
69.478 - return hash;
69.479 - }
69.480 - }
69.481 -
69.482 - Result<String> res = pl.lookupResult(String.class);
69.483 - assertEquals(Collections.EMPTY_LIST, res.allItems());
69.484 -
69.485 - L[] old = { new L("A"), new L("B") };
69.486 - L[] now = { new L("C") };
69.487 -
69.488 - pl.setLookups(old);
69.489 - cnt[0] = 0;
69.490 -
69.491 - old[0].set = new L[0];
69.492 - pl.setLookups(now);
69.493 -
69.494 - assertEquals("No call to equals", 0, cnt[0]);
69.495 -
69.496 - assertEquals("Still assigned to C", Collections.singletonList("C"), res.allInstances());
69.497 - }
69.498 -
69.499 - public void testArrayIndexWithAddRemoveListenerAsInIssue119292() throws Exception {
69.500 - final ProxyLookup pl = new ProxyLookup();
69.501 - final int[] cnt = { 0 };
69.502 -
69.503 - class L extends Lookup {
69.504 - L[] set;
69.505 - Lookup l;
69.506 -
69.507 - public L(String s) {
69.508 - l = Lookups.singleton(s);
69.509 - }
69.510 -
69.511 - @Override
69.512 - public <T> T lookup(Class<T> clazz) {
69.513 - return l.lookup(clazz);
69.514 - }
69.515 -
69.516 - @Override
69.517 - public <T> Result<T> lookup(Template<T> template) {
69.518 - Result<T> r = l.lookup(template);
69.519 - return new R<T>(r);
69.520 - }
69.521 -
69.522 - final class R<T> extends Result<T> {
69.523 - private Result<T> delegate;
69.524 -
69.525 - public R(Result<T> delegate) {
69.526 - this.delegate = delegate;
69.527 - }
69.528 -
69.529 - @Override
69.530 - public void addLookupListener(LookupListener l) {
69.531 - cnt[0]++;
69.532 - if (set != null) {
69.533 - pl.setLookups(set);
69.534 - }
69.535 - delegate.addLookupListener(l);
69.536 - }
69.537 -
69.538 - @Override
69.539 - public void removeLookupListener(LookupListener l) {
69.540 - cnt[0]++;
69.541 - if (set != null) {
69.542 - pl.setLookups(set);
69.543 - }
69.544 - delegate.removeLookupListener(l);
69.545 - }
69.546 -
69.547 - @Override
69.548 - public Collection<? extends T> allInstances() {
69.549 - return delegate.allInstances();
69.550 - }
69.551 - }
69.552 - }
69.553 -
69.554 - Result<String> res = pl.lookupResult(String.class);
69.555 - assertEquals(Collections.EMPTY_LIST, res.allItems());
69.556 -
69.557 - L[] old = { new L("A"), new L("B") };
69.558 - L[] now = { new L("C") };
69.559 -
69.560 - pl.setLookups(old);
69.561 - cnt[0] = 0;
69.562 -
69.563 - old[0].set = new L[0];
69.564 - pl.setLookups(now);
69.565 -
69.566 - if (cnt[0] == 0) {
69.567 - fail("There should be calls to listeners");
69.568 - }
69.569 -
69.570 - assertEquals("C is overriden from removeLookupListener", Collections.emptyList(), res.allInstances());
69.571 - }
69.572 -
69.573 -
69.574 - public void testArrayIndexWithSetLookupAsInIssue123679() throws Exception {
69.575 - final ProxyLookup pl = new ProxyLookup();
69.576 - final int[] cnt = { 0 };
69.577 -
69.578 - class L extends Lookup {
69.579 - L[] set;
69.580 - Lookup l;
69.581 - Collection<? extends Serializable> res;
69.582 -
69.583 - public L(String s) {
69.584 - l = Lookups.singleton(s);
69.585 - }
69.586 -
69.587 - @Override
69.588 - public <T> T lookup(Class<T> clazz) {
69.589 - return l.lookup(clazz);
69.590 - }
69.591 -
69.592 - @Override
69.593 - public <T> Result<T> lookup(Template<T> template) {
69.594 - cnt[0]++;
69.595 - if (set != null) {
69.596 - pl.setLookups(set);
69.597 - res = pl.lookupAll(Serializable.class);
69.598 - }
69.599 - Result<T> r = l.lookup(template);
69.600 - return r;
69.601 - }
69.602 - }
69.603 -
69.604 - L[] now = { new L("A"), new L("B") };
69.605 - L[] old = { new L("C") };
69.606 - pl.setLookups(old);
69.607 - old[0].set = now;
69.608 -
69.609 - Result<String> res = pl.lookupResult(String.class);
69.610 - assertEquals("New items visible", 2, res.allItems().size());
69.611 -
69.612 -
69.613 - pl.setLookups(new L("X"), new L("Y"), new L("Z"));
69.614 - }
69.615 -
69.616 - public void testDuplicatedLookupArrayIndexWithSetLookupAsInIssue123679() throws Exception {
69.617 - final ProxyLookup pl = new ProxyLookup();
69.618 - final int[] cnt = { 0 };
69.619 -
69.620 - class L extends Lookup {
69.621 - L[] set;
69.622 - Lookup l;
69.623 - Collection<? extends Serializable> res;
69.624 -
69.625 - public L(String s) {
69.626 - l = Lookups.singleton(s);
69.627 - }
69.628 -
69.629 - @Override
69.630 - public <T> T lookup(Class<T> clazz) {
69.631 - return l.lookup(clazz);
69.632 - }
69.633 -
69.634 - @Override
69.635 - public <T> Result<T> lookup(Template<T> template) {
69.636 - cnt[0]++;
69.637 - if (set != null) {
69.638 - pl.setLookups(set);
69.639 - res = pl.lookupAll(Serializable.class);
69.640 - }
69.641 - Result<T> r = l.lookup(template);
69.642 - return r;
69.643 - }
69.644 - }
69.645 -
69.646 - L dupl = new L("A");
69.647 - L[] now = { dupl };
69.648 - L[] old = { new L("C") };
69.649 - pl.setLookups(old);
69.650 - old[0].set = now;
69.651 -
69.652 - Result<String> res = pl.lookupResult(String.class);
69.653 - assertEquals("New items visible", 1, res.allItems().size());
69.654 -
69.655 -
69.656 - pl.setLookups(old);
69.657 - }
69.658 -}
70.1 --- a/lookup/src/test/java/org/openide/util/lookup/SimpleLookupTest.java Wed Jan 27 17:46:23 2010 -0500
70.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
70.3 @@ -1,351 +0,0 @@
70.4 -/*
70.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
70.6 - *
70.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
70.8 - *
70.9 - * The contents of this file are subject to the terms of either the GNU
70.10 - * General Public License Version 2 only ("GPL") or the Common
70.11 - * Development and Distribution License("CDDL") (collectively, the
70.12 - * "License"). You may not use this file except in compliance with the
70.13 - * License. You can obtain a copy of the License at
70.14 - * http://www.netbeans.org/cddl-gplv2.html
70.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
70.16 - * specific language governing permissions and limitations under the
70.17 - * License. When distributing the software, include this License Header
70.18 - * Notice in each file and include the License file at
70.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
70.20 - * particular file as subject to the "Classpath" exception as provided
70.21 - * by Sun in the GPL Version 2 section of the License file that
70.22 - * accompanied this code. If applicable, add the following below the
70.23 - * License Header, with the fields enclosed by brackets [] replaced by
70.24 - * your own identifying information:
70.25 - * "Portions Copyrighted [year] [name of copyright owner]"
70.26 - *
70.27 - * Contributor(s):
70.28 - *
70.29 - * The Original Software is NetBeans. The Initial Developer of the Original
70.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2009 Sun
70.31 - * Microsystems, Inc. All Rights Reserved.
70.32 - *
70.33 - * If you wish your version of this file to be governed by only the CDDL
70.34 - * or only the GPL Version 2, indicate your decision by adding
70.35 - * "[Contributor] elects to include this software in this distribution
70.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
70.37 - * single choice of license, a recipient has the option to distribute
70.38 - * your version of this file under either the CDDL, the GPL Version 2 or
70.39 - * to extend the choice of license to its licensees as provided above.
70.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
70.41 - * Version 2 license, then the option applies only if the new code is
70.42 - * made subject to such option by the copyright holder.
70.43 - */
70.44 -
70.45 -package org.openide.util.lookup;
70.46 -
70.47 -import java.util.ArrayList;
70.48 -import java.util.Arrays;
70.49 -import java.util.Collection;
70.50 -import java.util.List;
70.51 -import java.util.Set;
70.52 -import org.netbeans.junit.NbTestCase;
70.53 -import org.openide.util.Lookup;
70.54 -
70.55 -/**
70.56 - * Tests for class SimpleLookup.
70.57 - * @author David Strupl
70.58 - */
70.59 -public class SimpleLookupTest extends NbTestCase {
70.60 -
70.61 - public SimpleLookupTest(String testName) {
70.62 - super(testName);
70.63 - }
70.64 -
70.65 - public void testEmptyLookup() {
70.66 - assertSize("Lookup.EMPTY should be small", 8, Lookup.EMPTY);
70.67 - }
70.68 -
70.69 - /**
70.70 - * Simple tests testing singleton lookup.
70.71 - */
70.72 - public void testSingleton() {
70.73 - //
70.74 - Object orig = new Object();
70.75 - Lookup p1 = Lookups.singleton(orig);
70.76 - Object obj = p1.lookup(Object.class);
70.77 - assertTrue(obj == orig);
70.78 - assertNull(p1.lookup(String.class));
70.79 - assertTrue(orig == p1.lookup(Object.class)); // 2nd time, still the same?
70.80 - //
70.81 - Lookup p2 = Lookups.singleton("test");
70.82 - assertNotNull(p2.lookup(Object.class));
70.83 - assertNotNull(p2.lookup(String.class));
70.84 - assertNotNull(p2.lookup(java.io.Serializable.class));
70.85 - }
70.86 -
70.87 - public void testEmptyFixed() {
70.88 - Lookup l = Lookups.fixed();
70.89 - assertSize("Lookups.fixed() for empty list of items should be small", 8, l);
70.90 - assertSame(Lookup.EMPTY, l);
70.91 - }
70.92 -
70.93 - public void testSingleItemFixed() {
70.94 - Object o = new Object();
70.95 - Lookup l = Lookups.fixed(o);
70.96 - assertSize("Lookups.fixed(o) for a single item should be small", 24, l);
70.97 - }
70.98 -
70.99 - /**
70.100 - * Simple tests testing fixed lookup.
70.101 - */
70.102 - public void testFixed() {
70.103 - //
70.104 - Object[] orig = new Object[] { new Object(), new Object() };
70.105 - Lookup p1 = Lookups.fixed(orig);
70.106 - Object obj = p1.lookup(Object.class);
70.107 - assertTrue(obj == orig[0] || obj == orig[1]);
70.108 - assertNull(p1.lookup(String.class));
70.109 - //
70.110 - String[] s = new String[] { "test1", "test2" };
70.111 - Lookup p2 = Lookups.fixed((Object[]) s);
70.112 - Object obj2 = p2.lookup(Object.class);
70.113 - assertNotNull(obj2);
70.114 - if (obj2 != s[0] && obj2 != s[1]) {
70.115 - fail("Returned objects are not the originals");
70.116 - }
70.117 - assertNotNull(p2.lookup(String.class));
70.118 - assertNotNull(p2.lookup(java.io.Serializable.class));
70.119 - Lookup.Template<String> t = new Lookup.Template<String>(String.class);
70.120 - Lookup.Result<String> r = p2.lookup(t);
70.121 - Collection<? extends String> all = r.allInstances();
70.122 - assertTrue(all.size() == 2);
70.123 - for (String o : all) {
70.124 - assertTrue("allInstances contains wrong objects", o.equals(s[0]) || o.equals(s[1]));
70.125 - }
70.126 -
70.127 - try {
70.128 - Lookups.fixed(new Object[] {null});
70.129 - fail("No nulls are allowed");
70.130 - } catch (NullPointerException ex) {
70.131 - // ok, NPE is what we want
70.132 - }
70.133 - }
70.134 -
70.135 - public void testFixedSubtypes() {
70.136 - class A {}
70.137 - class B extends A {}
70.138 - Lookup l = Lookups.fixed(new A(), new B());
70.139 - assertEquals(1, l.lookupAll(B.class).size());
70.140 - assertEquals(2, l.lookupAll(A.class).size());
70.141 - }
70.142 -
70.143 - /**
70.144 - * Simple tests testing converting lookup.
70.145 - */
70.146 - public void testConverting() {
70.147 - //
70.148 - String[] orig = new String[] { TestConvertor.TEST1, TestConvertor.TEST2 };
70.149 - TestConvertor convertor = new TestConvertor();
70.150 - Lookup p1 = Lookups.fixed(orig, convertor);
70.151 - assertNull("Converting from String to Integer - it should not find String in result", p1.lookup(String.class));
70.152 - assertNotNull(p1.lookup(Integer.class));
70.153 - assertNotNull(p1.lookup(Integer.class));
70.154 - assertTrue("Convertor should be called only once.", convertor.getNumberOfConvertCalls() == 1);
70.155 - Lookup.Template<Integer> t = new Lookup.Template<Integer>(Integer.class);
70.156 - Lookup.Result<Integer> r = p1.lookup(t);
70.157 - Collection<? extends Integer> all = r.allInstances();
70.158 - assertTrue(all.size() == 2);
70.159 - for (int i : all) {
70.160 - assertTrue("allInstances contains wrong objects", i == TestConvertor.t1 || i == TestConvertor.t2);
70.161 - }
70.162 - }
70.163 -
70.164 - private static class TestConvertor implements InstanceContent.Convertor<String,Integer> {
70.165 - static final String TEST1 = "test1";
70.166 - static final int t1 = 1;
70.167 - static final String TEST2 = "test2";
70.168 - static final int t2 = 2;
70.169 -
70.170 - private int numberOfConvertCalls = 0;
70.171 -
70.172 - public Integer convert(String obj) {
70.173 - numberOfConvertCalls++;
70.174 - if (obj.equals(TEST1)) {
70.175 - return t1;
70.176 - }
70.177 - if (obj.equals(TEST2)) {
70.178 - return t2;
70.179 - }
70.180 - throw new IllegalArgumentException();
70.181 - }
70.182 -
70.183 - public String displayName(String obj) {
70.184 - return obj;
70.185 - }
70.186 -
70.187 - public String id(String obj) {
70.188 - if (obj.equals(TEST1)) {
70.189 - return TEST1;
70.190 - }
70.191 - if (obj.equals(TEST2)) {
70.192 - return TEST2;
70.193 - }
70.194 - return null;
70.195 - }
70.196 -
70.197 - public Class<? extends Integer> type(String obj) {
70.198 - return Integer.class;
70.199 - }
70.200 -
70.201 - int getNumberOfConvertCalls() {
70.202 - return numberOfConvertCalls;
70.203 - }
70.204 - }
70.205 -
70.206 - public void testLookupItem() {
70.207 - SomeInst inst = new SomeInst();
70.208 - Lookup.Item item = Lookups.lookupItem(inst, "XYZ");
70.209 -
70.210 - assertTrue("Wrong instance", item.getInstance() == inst);
70.211 - assertTrue("Wrong instance class", item.getType() == inst.getClass());
70.212 - assertEquals("Wrong id", "XYZ", item.getId());
70.213 -
70.214 - item = Lookups.lookupItem(inst, null);
70.215 - assertNotNull("Id must never be null", item.getId());
70.216 - }
70.217 -
70.218 - public void testLookupItemEquals() {
70.219 - SomeInst instA = new SomeInst();
70.220 - SomeInst instB = new SomeInst();
70.221 - Lookup.Item itemA = Lookups.lookupItem(instA, null);
70.222 - Lookup.Item itemB = Lookups.lookupItem(instB, null);
70.223 -
70.224 - assertTrue("Lookup items shouldn't be equal", !itemA.equals(itemB) && !itemB.equals(itemA));
70.225 -
70.226 - itemA = Lookups.lookupItem(instA, null);
70.227 - itemB = Lookups.lookupItem(instA, null); // same instance
70.228 -
70.229 - assertTrue("Lookup items should be equal", itemA.equals(itemB) && itemB.equals(itemA));
70.230 - assertTrue("Lookup items hashcode should be same", itemA.hashCode() == itemB.hashCode());
70.231 -
70.232 - itemA = Lookups.lookupItem(new String("VOKURKA"), null);
70.233 - itemB = Lookups.lookupItem(new String("VOKURKA"), null);
70.234 -
70.235 - assertTrue("Lookup items shouldn't be equal (2)", !itemA.equals(itemB) && !itemB.equals(itemA));
70.236 - }
70.237 -
70.238 - public void testAllClassesIssue42399 () throws Exception {
70.239 - Object[] arr = { "Ahoj", new Object () };
70.240 -
70.241 - Lookup l = Lookups.fixed (arr);
70.242 -
70.243 - Set<Class<? extends Object>> s = l.lookup(new Lookup.Template<Object>(Object.class)).allClasses();
70.244 -
70.245 - assertEquals ("Two there", 2, s.size ());
70.246 - assertTrue ("Contains Object.class", s.contains (Object.class));
70.247 - assertTrue ("Contains string", s.contains (String.class));
70.248 -
70.249 - }
70.250 -
70.251 - public void testLookupItemEarlyInitializationProblem() {
70.252 - InstanceContent ic = new InstanceContent();
70.253 - AbstractLookup al = new AbstractLookup(ic);
70.254 - LI item = new LI();
70.255 - List<AbstractLookup.Pair> pairs1 = new ArrayList<AbstractLookup.Pair>();
70.256 - List<AbstractLookup.Pair> pairs2 = new ArrayList<AbstractLookup.Pair>();
70.257 -
70.258 - assertEquals("Item's instance shouldn't be requested", 0, item.cnt);
70.259 -
70.260 - pairs1.add(new ItemPair<Object>(Lookups.<Object>lookupItem(new SomeInst(), null)));
70.261 - pairs1.add(new ItemPair<Object>(item));
70.262 - pairs1.add(new ItemPair<Object>(Lookups.lookupItem(new Object(), null)));
70.263 -
70.264 - pairs2.add(new ItemPair<Object>(item));
70.265 - pairs2.add(new ItemPair<Object>(Lookups.lookupItem(new Object(), null)));
70.266 -
70.267 - ic.setPairs(pairs1);
70.268 - ic.setPairs(pairs2);
70.269 -
70.270 - assertEquals("Item's instance shouldn't be requested when added to lookup", 0, item.cnt);
70.271 -
70.272 - LI item2 = al.lookup(LI.class);
70.273 - assertEquals("Item's instance should be requested", 1, item.cnt);
70.274 - }
70.275 -
70.276 - public void testConvenienceMethods() throws Exception {
70.277 - // Just check signatures and basic behavior of #73848.
70.278 - Lookup l = Lookups.fixed(new Object[] {1, "hello", 2, "goodbye"});
70.279 - Collection<? extends Integer> ints = l.lookupAll(Integer.class);
70.280 - assertEquals(Arrays.asList(new Integer[] {1, 2}), new ArrayList<Integer>(ints));
70.281 - Lookup.Result<Integer> r = l.lookupResult(Integer.class);
70.282 - ints = r.allInstances();
70.283 - assertEquals(Arrays.asList(new Integer[] {1, 2}), new ArrayList<Integer>(ints));
70.284 - }
70.285 -
70.286 - private static class SomeInst { }
70.287 -
70.288 - private static class LI extends Lookup.Item<Object> {
70.289 -
70.290 - public long cnt = 0;
70.291 -
70.292 - public String getDisplayName() {
70.293 - return getId();
70.294 - }
70.295 -
70.296 - public String getId() {
70.297 - return getClass() + "@" + hashCode();
70.298 - }
70.299 -
70.300 - public Object getInstance() {
70.301 - cnt++;
70.302 - return this;
70.303 - }
70.304 -
70.305 - public Class<? extends Object> getType() {
70.306 - return getClass();
70.307 - }
70.308 - } // End of LI class
70.309 -
70.310 - private static class ItemPair<T> extends AbstractLookup.Pair<T> {
70.311 -
70.312 - private AbstractLookup.Item<T> item;
70.313 -
70.314 - public ItemPair(Lookup.Item<T> i) {
70.315 - this.item = i;
70.316 - }
70.317 -
70.318 - protected boolean creatorOf(Object obj) {
70.319 - return item.getInstance() == obj;
70.320 - }
70.321 -
70.322 - public String getDisplayName() {
70.323 - return item.getDisplayName ();
70.324 - }
70.325 -
70.326 - public String getId() {
70.327 - return item.getId ();
70.328 - }
70.329 -
70.330 - public T getInstance() {
70.331 - return item.getInstance ();
70.332 - }
70.333 -
70.334 - public Class<? extends T> getType() {
70.335 - return item.getType ();
70.336 - }
70.337 -
70.338 - protected boolean instanceOf(Class<?> c) {
70.339 - return c.isAssignableFrom(getType());
70.340 - }
70.341 -
70.342 - public @Override boolean equals(Object o) {
70.343 - if (o instanceof ItemPair) {
70.344 - ItemPair p = (ItemPair)o;
70.345 - return item.equals (p.item);
70.346 - }
70.347 - return false;
70.348 - }
70.349 -
70.350 - public @Override int hashCode() {
70.351 - return item.hashCode ();
70.352 - }
70.353 - } // end of ItemPair
70.354 -}
71.1 --- a/lookup/src/test/java/org/openide/util/lookup/SimpleProxyLookupIssue42244Test.java Wed Jan 27 17:46:23 2010 -0500
71.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
71.3 @@ -1,120 +0,0 @@
71.4 -/*
71.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
71.6 - *
71.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
71.8 - *
71.9 - * The contents of this file are subject to the terms of either the GNU
71.10 - * General Public License Version 2 only ("GPL") or the Common
71.11 - * Development and Distribution License("CDDL") (collectively, the
71.12 - * "License"). You may not use this file except in compliance with the
71.13 - * License. You can obtain a copy of the License at
71.14 - * http://www.netbeans.org/cddl-gplv2.html
71.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
71.16 - * specific language governing permissions and limitations under the
71.17 - * License. When distributing the software, include this License Header
71.18 - * Notice in each file and include the License file at
71.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
71.20 - * particular file as subject to the "Classpath" exception as provided
71.21 - * by Sun in the GPL Version 2 section of the License file that
71.22 - * accompanied this code. If applicable, add the following below the
71.23 - * License Header, with the fields enclosed by brackets [] replaced by
71.24 - * your own identifying information:
71.25 - * "Portions Copyrighted [year] [name of copyright owner]"
71.26 - *
71.27 - * Contributor(s):
71.28 - *
71.29 - * The Original Software is NetBeans. The Initial Developer of the Original
71.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
71.31 - * Microsystems, Inc. All Rights Reserved.
71.32 - *
71.33 - * If you wish your version of this file to be governed by only the CDDL
71.34 - * or only the GPL Version 2, indicate your decision by adding
71.35 - * "[Contributor] elects to include this software in this distribution
71.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
71.37 - * single choice of license, a recipient has the option to distribute
71.38 - * your version of this file under either the CDDL, the GPL Version 2 or
71.39 - * to extend the choice of license to its licensees as provided above.
71.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
71.41 - * Version 2 license, then the option applies only if the new code is
71.42 - * made subject to such option by the copyright holder.
71.43 - */
71.44 -
71.45 -package org.openide.util.lookup;
71.46 -
71.47 -import java.lang.ref.WeakReference;
71.48 -import java.util.*;
71.49 -import junit.framework.*;
71.50 -import org.netbeans.junit.*;
71.51 -import org.openide.util.Lookup;
71.52 -
71.53 -/** To simulate issue 42244.
71.54 - */
71.55 -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
71.56 -public class SimpleProxyLookupIssue42244Test extends AbstractLookupBaseHid implements AbstractLookupBaseHid.Impl {
71.57 - public SimpleProxyLookupIssue42244Test (java.lang.String testName) {
71.58 - super(testName, null);
71.59 - }
71.60 -
71.61 - public static Test suite() {
71.62 - // return new SimpleProxyLookupIssue42244Test("testGarbageCollect");
71.63 - return new NbTestSuite(SimpleProxyLookupIssue42244Test.class);
71.64 - }
71.65 -
71.66 - /** Creates an lookup for given lookup. This class just returns
71.67 - * the object passed in, but subclasses can be different.
71.68 - * @param lookup in lookup
71.69 - * @return a lookup to use
71.70 - */
71.71 - public Lookup createLookup (final Lookup lookup) {
71.72 - class C implements Lookup.Provider {
71.73 - public Lookup getLookup () {
71.74 - return lookup;
71.75 - }
71.76 - }
71.77 - return Lookups.proxy (new C ());
71.78 - }
71.79 -
71.80 - public Lookup createInstancesLookup (InstanceContent ic) {
71.81 - return new KeepResultsProxyLookup (new AbstractLookup (ic));
71.82 - }
71.83 -
71.84 - public void clearCaches () {
71.85 - KeepResultsProxyLookup k = (KeepResultsProxyLookup)this.instanceLookup;
71.86 -
71.87 - ArrayList toGC = new ArrayList ();
71.88 - Iterator it = k.allQueries.iterator ();
71.89 - while (it.hasNext ()) {
71.90 - Lookup.Result r = (Lookup.Result)it.next ();
71.91 - toGC.add (new WeakReference (r));
71.92 - }
71.93 -
71.94 - k.allQueries = null;
71.95 -
71.96 - it = toGC.iterator ();
71.97 - while (it.hasNext ()) {
71.98 - WeakReference r = (WeakReference)it.next ();
71.99 - assertGC ("Trying to release all results from memory", r);
71.100 - }
71.101 - }
71.102 -
71.103 - class KeepResultsProxyLookup extends ProxyLookup {
71.104 - private ArrayList allQueries = new ArrayList ();
71.105 - private ThreadLocal in = new ThreadLocal ();
71.106 -
71.107 - public KeepResultsProxyLookup (Lookup delegate) {
71.108 - super (new Lookup[] { delegate });
71.109 - }
71.110 -
71.111 - @Override
71.112 - protected void beforeLookup (org.openide.util.Lookup.Template template) {
71.113 - super.beforeLookup (template);
71.114 - if (allQueries != null && in.get () == null) {
71.115 - in.set (this);
71.116 - Lookup.Result res = lookup (template);
71.117 - allQueries.add (res);
71.118 - in.set (null);
71.119 - }
71.120 - }
71.121 -
71.122 - }
71.123 -}
72.1 --- a/lookup/src/test/java/org/openide/util/lookup/SimpleProxyLookupSpeedIssue42244Test.java Wed Jan 27 17:46:23 2010 -0500
72.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
72.3 @@ -1,118 +0,0 @@
72.4 -/*
72.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
72.6 - *
72.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
72.8 - *
72.9 - * The contents of this file are subject to the terms of either the GNU
72.10 - * General Public License Version 2 only ("GPL") or the Common
72.11 - * Development and Distribution License("CDDL") (collectively, the
72.12 - * "License"). You may not use this file except in compliance with the
72.13 - * License. You can obtain a copy of the License at
72.14 - * http://www.netbeans.org/cddl-gplv2.html
72.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
72.16 - * specific language governing permissions and limitations under the
72.17 - * License. When distributing the software, include this License Header
72.18 - * Notice in each file and include the License file at
72.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
72.20 - * particular file as subject to the "Classpath" exception as provided
72.21 - * by Sun in the GPL Version 2 section of the License file that
72.22 - * accompanied this code. If applicable, add the following below the
72.23 - * License Header, with the fields enclosed by brackets [] replaced by
72.24 - * your own identifying information:
72.25 - * "Portions Copyrighted [year] [name of copyright owner]"
72.26 - *
72.27 - * Contributor(s):
72.28 - *
72.29 - * The Original Software is NetBeans. The Initial Developer of the Original
72.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
72.31 - * Microsystems, Inc. All Rights Reserved.
72.32 - *
72.33 - * If you wish your version of this file to be governed by only the CDDL
72.34 - * or only the GPL Version 2, indicate your decision by adding
72.35 - * "[Contributor] elects to include this software in this distribution
72.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
72.37 - * single choice of license, a recipient has the option to distribute
72.38 - * your version of this file under either the CDDL, the GPL Version 2 or
72.39 - * to extend the choice of license to its licensees as provided above.
72.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
72.41 - * Version 2 license, then the option applies only if the new code is
72.42 - * made subject to such option by the copyright holder.
72.43 - */
72.44 -
72.45 -package org.openide.util.lookup;
72.46 -
72.47 -import java.util.HashSet;
72.48 -import java.util.Set;
72.49 -import org.netbeans.junit.NbTestCase;
72.50 -
72.51 -import org.netbeans.junit.RandomlyFails;
72.52 -import org.openide.util.Lookup;
72.53 -
72.54 -/**
72.55 - * @author Petr Nejedly, adapted to test by Jaroslav Tulach
72.56 - */
72.57 -@RandomlyFails // NB-Core-Build #1847
72.58 -public class SimpleProxyLookupSpeedIssue42244Test extends NbTestCase {
72.59 -
72.60 - public SimpleProxyLookupSpeedIssue42244Test (String name) {
72.61 - super (name);
72.62 - }
72.63 -
72.64 - public void testCompareTheSpeed () {
72.65 - String content1 = "String1";
72.66 - String content2 = "String2";
72.67 -
72.68 - Lookup fixed1 = Lookups.singleton(content1);
72.69 - Lookup fixed2 = Lookups.singleton(content2);
72.70 -
72.71 - MyProvider provider = new MyProvider();
72.72 - provider.setLookup(fixed1);
72.73 -
72.74 - Lookup top = Lookups.proxy(provider);
72.75 -
72.76 - Lookup.Result<String> r0 = top.lookupResult(String.class);
72.77 - r0.allInstances();
72.78 -
72.79 - long time = System.currentTimeMillis();
72.80 - top.lookupAll(String.class);
72.81 - long withOneResult = System.currentTimeMillis() - time;
72.82 -
72.83 -
72.84 - Set<Object> results = new HashSet<Object>();
72.85 - for (int i=0; i<10000; i++) {
72.86 - Lookup.Result<String> res = top.lookupResult(String.class);
72.87 - results.add (res);
72.88 - res.allInstances();
72.89 - }
72.90 -
72.91 - provider.setLookup(fixed2);
72.92 -
72.93 - time = System.currentTimeMillis();
72.94 - top.lookupAll(String.class);
72.95 - long withManyResults = System.currentTimeMillis() - time;
72.96 -
72.97 - // if the measurement takes less then 10ms, pretend 10ms
72.98 - if (withManyResults < 10) {
72.99 - withManyResults = 10;
72.100 - }
72.101 - if (withOneResult < 10) {
72.102 - withOneResult = 10;
72.103 - }
72.104 -
72.105 - if (withManyResults >= 10 * withOneResult) {
72.106 - fail ("With many results the test runs too long.\n With many: " + withManyResults + "\n With one : " + withOneResult);
72.107 - }
72.108 - }
72.109 -
72.110 - private static class MyProvider implements Lookup.Provider {
72.111 - private Lookup lookup;
72.112 - public Lookup getLookup() {
72.113 - return lookup;
72.114 - }
72.115 -
72.116 - void setLookup(Lookup lookup) {
72.117 - this.lookup = lookup;
72.118 - }
72.119 - }
72.120 -
72.121 -}
73.1 --- a/lookup/src/test/java/org/openide/util/lookup/SimpleProxyLookupTest.java Wed Jan 27 17:46:23 2010 -0500
73.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
73.3 @@ -1,73 +0,0 @@
73.4 -/*
73.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
73.6 - *
73.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
73.8 - *
73.9 - * The contents of this file are subject to the terms of either the GNU
73.10 - * General Public License Version 2 only ("GPL") or the Common
73.11 - * Development and Distribution License("CDDL") (collectively, the
73.12 - * "License"). You may not use this file except in compliance with the
73.13 - * License. You can obtain a copy of the License at
73.14 - * http://www.netbeans.org/cddl-gplv2.html
73.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
73.16 - * specific language governing permissions and limitations under the
73.17 - * License. When distributing the software, include this License Header
73.18 - * Notice in each file and include the License file at
73.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
73.20 - * particular file as subject to the "Classpath" exception as provided
73.21 - * by Sun in the GPL Version 2 section of the License file that
73.22 - * accompanied this code. If applicable, add the following below the
73.23 - * License Header, with the fields enclosed by brackets [] replaced by
73.24 - * your own identifying information:
73.25 - * "Portions Copyrighted [year] [name of copyright owner]"
73.26 - *
73.27 - * Contributor(s):
73.28 - *
73.29 - * The Original Software is NetBeans. The Initial Developer of the Original
73.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
73.31 - * Microsystems, Inc. All Rights Reserved.
73.32 - *
73.33 - * If you wish your version of this file to be governed by only the CDDL
73.34 - * or only the GPL Version 2, indicate your decision by adding
73.35 - * "[Contributor] elects to include this software in this distribution
73.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
73.37 - * single choice of license, a recipient has the option to distribute
73.38 - * your version of this file under either the CDDL, the GPL Version 2 or
73.39 - * to extend the choice of license to its licensees as provided above.
73.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
73.41 - * Version 2 license, then the option applies only if the new code is
73.42 - * made subject to such option by the copyright holder.
73.43 - */
73.44 -
73.45 -package org.openide.util.lookup;
73.46 -
73.47 -import java.lang.ref.WeakReference;
73.48 -import org.netbeans.junit.NbTestCase;
73.49 -import org.openide.util.Lookup;
73.50 -import org.openide.util.Lookup.Provider;
73.51 -
73.52 -/**
73.53 - *
73.54 - * @author Jan Lahoda
73.55 - */
73.56 -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
73.57 -public class SimpleProxyLookupTest extends NbTestCase {
73.58 -
73.59 - public SimpleProxyLookupTest(String testName) {
73.60 - super(testName);
73.61 - }
73.62 -
73.63 - public void test69810() throws Exception {
73.64 - Lookup.Template t = new Lookup.Template(String.class);
73.65 - SimpleProxyLookup spl = new SimpleProxyLookup(new Provider() {
73.66 - public Lookup getLookup() {
73.67 - return Lookups.fixed(new Object[] {"test1", "test2"});
73.68 - }
73.69 - });
73.70 -
73.71 - assertGC("", new WeakReference(spl.lookup(t)));
73.72 -
73.73 - spl.lookup(new Lookup.Template(Object.class)).allInstances();
73.74 - }
73.75 -
73.76 -}
74.1 --- a/lookup/src/test/java/org/openide/util/lookup/SingletonLookupTest.java Wed Jan 27 17:46:23 2010 -0500
74.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
74.3 @@ -1,113 +0,0 @@
74.4 -/*
74.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
74.6 - *
74.7 - * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
74.8 - *
74.9 - * The contents of this file are subject to the terms of either the GNU
74.10 - * General Public License Version 2 only ("GPL") or the Common
74.11 - * Development and Distribution License("CDDL") (collectively, the
74.12 - * "License"). You may not use this file except in compliance with the
74.13 - * License. You can obtain a copy of the License at
74.14 - * http://www.netbeans.org/cddl-gplv2.html
74.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
74.16 - * specific language governing permissions and limitations under the
74.17 - * License. When distributing the software, include this License Header
74.18 - * Notice in each file and include the License file at
74.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
74.20 - * particular file as subject to the "Classpath" exception as provided
74.21 - * by Sun in the GPL Version 2 section of the License file that
74.22 - * accompanied this code. If applicable, add the following below the
74.23 - * License Header, with the fields enclosed by brackets [] replaced by
74.24 - * your own identifying information:
74.25 - * "Portions Copyrighted [year] [name of copyright owner]"
74.26 - *
74.27 - * If you wish your version of this file to be governed by only the CDDL
74.28 - * or only the GPL Version 2, indicate your decision by adding
74.29 - * "[Contributor] elects to include this software in this distribution
74.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
74.31 - * single choice of license, a recipient has the option to distribute
74.32 - * your version of this file under either the CDDL, the GPL Version 2 or
74.33 - * to extend the choice of license to its licensees as provided above.
74.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
74.35 - * Version 2 license, then the option applies only if the new code is
74.36 - * made subject to such option by the copyright holder.
74.37 - *
74.38 - * Contributor(s):
74.39 - *
74.40 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
74.41 - */
74.42 -
74.43 -package org.openide.util.lookup;
74.44 -
74.45 -import java.util.Collection;
74.46 -import org.netbeans.junit.NbTestCase;
74.47 -import org.openide.util.Lookup;
74.48 -
74.49 -/**
74.50 - * Contains tests of class {@code SingletonLookup}.
74.51 - *
74.52 - * @author Marian Petras
74.53 - */
74.54 -public class SingletonLookupTest extends NbTestCase {
74.55 -
74.56 - public SingletonLookupTest(String testName) {
74.57 - super(testName);
74.58 - }
74.59 -
74.60 - public void testBasics() {
74.61 - Object orig = new Object();
74.62 - Lookup p1 = new SingletonLookup(orig);
74.63 - Object obj = p1.lookup(Object.class);
74.64 - assertTrue(obj == orig);
74.65 - assertNull(p1.lookup(String.class));
74.66 - assertTrue(orig == p1.lookup(Object.class)); // 2nd time, still the same?
74.67 - //
74.68 - Lookup p2 = new SingletonLookup("test");
74.69 - assertNotNull(p2.lookup(Object.class));
74.70 - assertNotNull(p2.lookup(String.class));
74.71 - assertNotNull(p2.lookup(java.io.Serializable.class));
74.72 - }
74.73 -
74.74 - public void testId() {
74.75 - Object orig = new Object();
74.76 - Collection allInstances;
74.77 -
74.78 - Lookup l = new SingletonLookup(orig, "id");
74.79 -
74.80 - allInstances = l.lookup(new Lookup.Template<Object>(Object.class, null, null)).allInstances();
74.81 - assertNotNull(allInstances);
74.82 - assertFalse(allInstances.isEmpty());
74.83 - assertEquals(1, allInstances.size());
74.84 - assertTrue(allInstances.iterator().next() == orig);
74.85 -
74.86 - allInstances = l.lookup(new Lookup.Template<Object>(Object.class, "id", null)).allInstances();
74.87 - assertNotNull(allInstances);
74.88 - assertFalse(allInstances.isEmpty());
74.89 - assertEquals(1, allInstances.size());
74.90 - assertTrue(allInstances.iterator().next() == orig);
74.91 -
74.92 - allInstances = l.lookup(new Lookup.Template<Object>(Object.class, "not", null)).allInstances();
74.93 - assertNotNull(allInstances);
74.94 - assertTrue(allInstances.isEmpty());
74.95 -
74.96 - allInstances = l.lookup(new Lookup.Template<String>(String.class, null, null)).allInstances();
74.97 - assertNotNull(allInstances);
74.98 - assertTrue(allInstances.isEmpty());
74.99 -
74.100 - allInstances = l.lookup(new Lookup.Template<String>(String.class, "id", null)).allInstances();
74.101 - assertNotNull(allInstances);
74.102 - assertTrue(allInstances.isEmpty());
74.103 -
74.104 - allInstances = l.lookup(new Lookup.Template<String>(String.class, "not", null)).allInstances();
74.105 - assertNotNull(allInstances);
74.106 - assertTrue(allInstances.isEmpty());
74.107 - }
74.108 -
74.109 - public void testSize() {
74.110 - final Object obj = new Object();
74.111 - assertSize("The singleton lookup instance should be small",
74.112 - 24,
74.113 - new SingletonLookup(obj));
74.114 - }
74.115 -
74.116 -}
75.1 --- a/lookup/src/test/java/org/openide/util/test/AnnotationProcessorTestUtils.java Wed Jan 27 17:46:23 2010 -0500
75.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
75.3 @@ -1,139 +0,0 @@
75.4 -/*
75.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
75.6 - *
75.7 - * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
75.8 - *
75.9 - * The contents of this file are subject to the terms of either the GNU
75.10 - * General Public License Version 2 only ("GPL") or the Common
75.11 - * Development and Distribution License("CDDL") (collectively, the
75.12 - * "License"). You may not use this file except in compliance with the
75.13 - * License. You can obtain a copy of the License at
75.14 - * http://www.netbeans.org/cddl-gplv2.html
75.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
75.16 - * specific language governing permissions and limitations under the
75.17 - * License. When distributing the software, include this License Header
75.18 - * Notice in each file and include the License file at
75.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
75.20 - * particular file as subject to the "Classpath" exception as provided
75.21 - * by Sun in the GPL Version 2 section of the License file that
75.22 - * accompanied this code. If applicable, add the following below the
75.23 - * License Header, with the fields enclosed by brackets [] replaced by
75.24 - * your own identifying information:
75.25 - * "Portions Copyrighted [year] [name of copyright owner]"
75.26 - *
75.27 - * If you wish your version of this file to be governed by only the CDDL
75.28 - * or only the GPL Version 2, indicate your decision by adding
75.29 - * "[Contributor] elects to include this software in this distribution
75.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
75.31 - * single choice of license, a recipient has the option to distribute
75.32 - * your version of this file under either the CDDL, the GPL Version 2 or
75.33 - * to extend the choice of license to its licensees as provided above.
75.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
75.35 - * Version 2 license, then the option applies only if the new code is
75.36 - * made subject to such option by the copyright holder.
75.37 - *
75.38 - * Contributor(s):
75.39 - *
75.40 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
75.41 - */
75.42 -
75.43 -package org.openide.util.test;
75.44 -
75.45 -import java.io.File;
75.46 -import java.io.FileWriter;
75.47 -import java.io.IOException;
75.48 -import java.io.OutputStream;
75.49 -import java.io.PrintWriter;
75.50 -import java.io.Writer;
75.51 -import java.util.ArrayList;
75.52 -import java.util.List;
75.53 -import java.util.regex.Pattern;
75.54 -import javax.tools.JavaCompiler;
75.55 -import javax.tools.ToolProvider;
75.56 -import junit.framework.Assert;
75.57 -
75.58 -/**
75.59 - * Utilities useful to those testing JSR 269 annotation processors.
75.60 - * <p>If you just want to test that the output of the processor is correct,
75.61 - * you do not need to do anything special:
75.62 - * just use the annotation on some sample classes nested inside your unit test.
75.63 - * They will be processed, and you check that your SPI loads them correctly.
75.64 - * These utilities are useful mainly in case you want to check that the processor
75.65 - * rejects erroneous sources, and that any messages it prints are reasonable;
75.66 - * that it behaves correctly on incremental compilations; etc.
75.67 - */
75.68 -public class AnnotationProcessorTestUtils {
75.69 -
75.70 - private AnnotationProcessorTestUtils() {}
75.71 -
75.72 - /**
75.73 - * Create a source file.
75.74 - * @param dir source root
75.75 - * @param clazz a fully-qualified class name
75.76 - * @param content lines of text (skip package decl)
75.77 - */
75.78 - public static void makeSource(File dir, String clazz, String... content) throws IOException {
75.79 - File f = new File(dir, clazz.replace('.', File.separatorChar) + ".java");
75.80 - f.getParentFile().mkdirs();
75.81 - Writer w = new FileWriter(f);
75.82 - try {
75.83 - PrintWriter pw = new PrintWriter(w);
75.84 - String pkg = clazz.replaceFirst("\\.[^.]+$", "");
75.85 - if (!pkg.equals(clazz)) {
75.86 - pw.println("package " + pkg + ";");
75.87 - }
75.88 - for (String line : content) {
75.89 - pw.println(line);
75.90 - }
75.91 - pw.flush();
75.92 - } finally {
75.93 - w.close();
75.94 - }
75.95 - }
75.96 -
75.97 - /**
75.98 - * Run the Java compiler.
75.99 - * (A JSR 199 implementation must be available.)
75.100 - * @param src a source root (runs javac on all *.java it finds matching {@code srcIncludes})
75.101 - * @param srcIncludes a pattern of source files names without path to compile (useful for testing incremental compiles), or null for all
75.102 - * @param dest a dest dir to compile classes to
75.103 - * @param cp classpath entries; if null, use Java classpath of test
75.104 - * @param stderr output stream to print messages to, or null for test console (i.e. do not capture)
75.105 - * @return true if compilation succeeded, false if it failed
75.106 - */
75.107 - public static boolean runJavac(File src, String srcIncludes, File dest, File[] cp, OutputStream stderr) {
75.108 - List<String> args = new ArrayList<String>();
75.109 - args.add("-classpath");
75.110 - if (cp != null) {
75.111 - StringBuffer b = new StringBuffer();
75.112 - for (File entry : cp) {
75.113 - b.append(File.pathSeparatorChar);
75.114 - b.append(entry.getAbsolutePath());
75.115 - }
75.116 - args.add(b.toString());
75.117 - } else {
75.118 - args.add(System.getProperty("java.class.path"));
75.119 - }
75.120 - args.add("-d");
75.121 - args.add(dest.getAbsolutePath());
75.122 - args.add("-sourcepath");
75.123 - args.add(src.getAbsolutePath());
75.124 - dest.mkdirs();
75.125 - scan(args, src, srcIncludes);
75.126 - JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
75.127 - Assert.assertNotNull("no JSR 199 compiler impl found; try e.g.: " +
75.128 - "test.unit.run.cp.extra=${nb_all}/apisupport.harness/external/openjdk-javac-6-b12.jar", compiler);
75.129 - //System.err.println("running javac with args: " + args);
75.130 - return compiler.run(null, null, stderr, args.toArray(new String[args.size()])) == 0;
75.131 - }
75.132 - private static void scan(List<String> names, File f, String includes) {
75.133 - if (f.isDirectory()) {
75.134 - for (File kid : f.listFiles()) {
75.135 - scan(names, kid, includes);
75.136 - }
75.137 - } else if (f.getName().endsWith(".java") && (includes == null || Pattern.compile(includes).matcher(f.getName()).find())) {
75.138 - names.add(f.getAbsolutePath());
75.139 - }
75.140 - }
75.141 -
75.142 -}
76.1 --- a/lookup/src/test/java/org/openide/util/test/MockLookup.java Wed Jan 27 17:46:23 2010 -0500
76.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
76.3 @@ -1,135 +0,0 @@
76.4 -/*
76.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
76.6 - *
76.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
76.8 - *
76.9 - * The contents of this file are subject to the terms of either the GNU
76.10 - * General Public License Version 2 only ("GPL") or the Common
76.11 - * Development and Distribution License("CDDL") (collectively, the
76.12 - * "License"). You may not use this file except in compliance with the
76.13 - * License. You can obtain a copy of the License at
76.14 - * http://www.netbeans.org/cddl-gplv2.html
76.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
76.16 - * specific language governing permissions and limitations under the
76.17 - * License. When distributing the software, include this License Header
76.18 - * Notice in each file and include the License file at
76.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
76.20 - * particular file as subject to the "Classpath" exception as provided
76.21 - * by Sun in the GPL Version 2 section of the License file that
76.22 - * accompanied this code. If applicable, add the following below the
76.23 - * License Header, with the fields enclosed by brackets [] replaced by
76.24 - * your own identifying information:
76.25 - * "Portions Copyrighted [year] [name of copyright owner]"
76.26 - *
76.27 - * Contributor(s):
76.28 - *
76.29 - * The Original Software is NetBeans. The Initial Developer of the Original
76.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
76.31 - * Microsystems, Inc. All Rights Reserved.
76.32 - *
76.33 - * If you wish your version of this file to be governed by only the CDDL
76.34 - * or only the GPL Version 2, indicate your decision by adding
76.35 - * "[Contributor] elects to include this software in this distribution
76.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
76.37 - * single choice of license, a recipient has the option to distribute
76.38 - * your version of this file under either the CDDL, the GPL Version 2 or
76.39 - * to extend the choice of license to its licensees as provided above.
76.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
76.41 - * Version 2 license, then the option applies only if the new code is
76.42 - * made subject to such option by the copyright holder.
76.43 - */
76.44 -
76.45 -package org.openide.util.test;
76.46 -
76.47 -import java.lang.reflect.Field;
76.48 -import java.util.Collection;
76.49 -import static junit.framework.Assert.*;
76.50 -import org.openide.util.Lookup;
76.51 -import org.openide.util.lookup.Lookups;
76.52 -import org.openide.util.lookup.ProxyLookup;
76.53 -
76.54 -/**
76.55 - * Mock implementation of system default lookup suitable for use in unit tests.
76.56 - * The initial value just contains classpath services.
76.57 - */
76.58 -public class MockLookup extends ProxyLookup {
76.59 -
76.60 - private static MockLookup DEFAULT;
76.61 - private static boolean making = false;
76.62 - private static volatile boolean ready;
76.63 -
76.64 - static {
76.65 - making = true;
76.66 - try {
76.67 - System.setProperty("org.openide.util.Lookup", MockLookup.class.getName());
76.68 - if (Lookup.getDefault().getClass() != MockLookup.class) {
76.69 - // Someone else initialized lookup first. Try to force our way.
76.70 - Field defaultLookup = Lookup.class.getDeclaredField("defaultLookup");
76.71 - defaultLookup.setAccessible(true);
76.72 - defaultLookup.set(null, null);
76.73 - }
76.74 - assertEquals(MockLookup.class, Lookup.getDefault().getClass());
76.75 - } catch (Exception x) {
76.76 - throw new ExceptionInInitializerError(x);
76.77 - } finally {
76.78 - making = false;
76.79 - }
76.80 - }
76.81 -
76.82 - /** Do not call this directly! */
76.83 - public MockLookup() {
76.84 - assertTrue(making);
76.85 - assertNull(DEFAULT);
76.86 - DEFAULT = this;
76.87 - }
76.88 -
76.89 - /**
76.90 - * Just ensures that this lookup is default lookup, but does not actually change its content.
76.91 - * Useful mainly if you have some test utility method which calls foreign code which might use default lookup,
76.92 - * and you want to ensure that any users of mock lookup will see the correct default lookup right away,
76.93 - * even if they have not yet called {@link #setLookup} or {@link #setInstances}.
76.94 - */
76.95 - public static void init() {
76.96 - if (!ready) {
76.97 - setInstances();
76.98 - }
76.99 - }
76.100 -
76.101 - /**
76.102 - * Sets the global default lookup with zero or more delegate lookups.
76.103 - * Caution: if you don't include Lookups.metaInfServices, you may have trouble,
76.104 - * e.g. {@link #makeScratchDir} will not work.
76.105 - * Most of the time you should use {@link #setInstances} instead.
76.106 - */
76.107 - public static void setLookup(Lookup... lookups) {
76.108 - ready = true;
76.109 - DEFAULT.setLookups(lookups);
76.110 - }
76.111 -
76.112 - /**
76.113 - * Sets the global default lookup with some fixed instances.
76.114 - * Will also include (at a lower priority) a {@link ClassLoader},
76.115 - * and services found from <code>META-INF/services/*</code> in the classpath.
76.116 - */
76.117 - public static void setInstances(Object... instances) {
76.118 - ClassLoader l = MockLookup.class.getClassLoader();
76.119 - setLookup(Lookups.fixed(instances), Lookups.metaInfServices(l), Lookups.singleton(l));
76.120 - }
76.121 - /**
76.122 - * Sets the global default lookup with some fixed instances and
76.123 - * content read from Services folder from system file system.
76.124 - * Will also include (at a lower priority) a {@link ClassLoader},
76.125 - * and services found from <code>META-INF/services/*</code> in the classpath.
76.126 - */
76.127 - public static void setLayersAndInstances(Object... instances) {
76.128 - ClassLoader l = MockLookup.class.getClassLoader();
76.129 - if (l != Lookup.getDefault().lookup(ClassLoader.class)) {
76.130 - setLookup(Lookups.fixed(instances), Lookups.metaInfServices(l), Lookups.singleton(l));
76.131 - }
76.132 - Lookup projects = Lookups.forPath("Services");
76.133 - Collection<?> initialize = projects.lookupAll(Object.class);
76.134 - //System.err.println("all: " + initialize);
76.135 - setLookup(Lookups.fixed(instances), Lookups.metaInfServices(l), Lookups.singleton(l), projects);
76.136 - }
76.137 -
76.138 -}
77.1 --- a/lookup/src/test/java/org/openide/util/test/MockLookupTest.java Wed Jan 27 17:46:23 2010 -0500
77.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
77.3 @@ -1,66 +0,0 @@
77.4 -/*
77.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
77.6 - *
77.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
77.8 - *
77.9 - * The contents of this file are subject to the terms of either the GNU
77.10 - * General Public License Version 2 only ("GPL") or the Common
77.11 - * Development and Distribution License("CDDL") (collectively, the
77.12 - * "License"). You may not use this file except in compliance with the
77.13 - * License. You can obtain a copy of the License at
77.14 - * http://www.netbeans.org/cddl-gplv2.html
77.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
77.16 - * specific language governing permissions and limitations under the
77.17 - * License. When distributing the software, include this License Header
77.18 - * Notice in each file and include the License file at
77.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
77.20 - * particular file as subject to the "Classpath" exception as provided
77.21 - * by Sun in the GPL Version 2 section of the License file that
77.22 - * accompanied this code. If applicable, add the following below the
77.23 - * License Header, with the fields enclosed by brackets [] replaced by
77.24 - * your own identifying information:
77.25 - * "Portions Copyrighted [year] [name of copyright owner]"
77.26 - *
77.27 - * Contributor(s):
77.28 - *
77.29 - * The Original Software is NetBeans. The Initial Developer of the Original
77.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
77.31 - * Microsystems, Inc. All Rights Reserved.
77.32 - *
77.33 - * If you wish your version of this file to be governed by only the CDDL
77.34 - * or only the GPL Version 2, indicate your decision by adding
77.35 - * "[Contributor] elects to include this software in this distribution
77.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
77.37 - * single choice of license, a recipient has the option to distribute
77.38 - * your version of this file under either the CDDL, the GPL Version 2 or
77.39 - * to extend the choice of license to its licensees as provided above.
77.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
77.41 - * Version 2 license, then the option applies only if the new code is
77.42 - * made subject to such option by the copyright holder.
77.43 - */
77.44 -
77.45 -package org.openide.util.test;
77.46 -
77.47 -import junit.framework.TestCase;
77.48 -import org.openide.util.Lookup;
77.49 -
77.50 -public class MockLookupTest extends TestCase {
77.51 -
77.52 - // XXX test:
77.53 - // setLookup with one or more lookup args does not use M-I/s
77.54 - // still works if another Lookup.getDefault was set before
77.55 -
77.56 - public MockLookupTest(String n) {
77.57 - super(n);
77.58 - }
77.59 -
77.60 - public void testSetLookup() throws Exception {
77.61 - MockLookup.setInstances("hello");
77.62 - assertEquals("initial lookup works", "hello", Lookup.getDefault().lookup(String.class));
77.63 - MockLookup.setInstances("goodbye");
77.64 - assertEquals("modified lookup works", "goodbye", Lookup.getDefault().lookup(String.class));
77.65 - MockLookup.setInstances();
77.66 - assertEquals("cleared lookup works", null, Lookup.getDefault().lookup(String.class));
77.67 - }
77.68 -
77.69 -}
78.1 --- a/lookup/src/test/resources/org/openide/util/lookup/MetaInfServicesLookupTestRunnable.txt Wed Jan 27 17:46:23 2010 -0500
78.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
78.3 @@ -1,1 +0,0 @@
78.4 -org.openide.util.lookup.MetaInfServicesLookupTestRunnable
79.1 --- a/lookup/src/test/resources/org/openide/util/lookup/problem100320.txt Wed Jan 27 17:46:23 2010 -0500
79.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
79.3 @@ -1,17 +0,0 @@
79.4 -:java.io.IOException:
79.5 -java.nio.charset.CharacterCodingException
79.6 -java.io.EOFException
79.7 -java.io.FileNotFoundException
79.8 -java.io.InterruptedIOException
79.9 -java.net.MalformedURLException
79.10 -java.io.IOException
79.11 -java.io.UnsupportedEncodingException
79.12 -java.io.NotActiveException
79.13 -java.io.StreamCorruptedException
79.14 -java.io.UTFDataFormatException
79.15 -java.util.zip.ZipException
79.16 -java.util.jar.JarException
79.17 -:java.util.Comparator:
79.18 -org.bar.Comparator3
79.19 -org.bar.Comparator2
79.20 -#position=5
80.1 --- a/lookup/src/test/resources/org/openide/util/lookup/services-jar-1.txt Wed Jan 27 17:46:23 2010 -0500
80.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
80.3 @@ -1,17 +0,0 @@
80.4 -:somedummyfile:
80.5 -org.foo.Interface
80.6 -:java.lang.Runnable:
80.7 -org.foo.impl.Runnable1
80.8 -:java.util.Comparator:
80.9 -#some comment
80.10 -org.foo.impl.Comparator1
80.11 -#position=10
80.12 -#som comment2
80.13 -:java.util.Iterator:
80.14 -org.foo.impl.Iterator1
80.15 -:org.foo.Interface:
80.16 -# Some header info, maybe.
80.17 -
80.18 -# Our first impl here
80.19 -org.foo.impl.Implementation1
80.20 -
81.1 --- a/lookup/src/test/resources/org/openide/util/lookup/services-jar-2.txt Wed Jan 27 17:46:23 2010 -0500
81.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
81.3 @@ -1,10 +0,0 @@
81.4 -:java.lang.Runnable:
81.5 -#-org.foo.impl.Runnable1
81.6 -:java.util.Comparator:
81.7 -org.bar.Comparator2
81.8 -#position=5
81.9 -:java.util.Iterator:
81.10 -org.bar.Iterator2
81.11 -#position=100
81.12 -:org.foo.Interface:
81.13 -org.bar.Implementation2
82.1 --- a/openide.util.lookup/apichanges.xml Wed Jan 27 17:46:23 2010 -0500
82.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
82.3 @@ -1,495 +0,0 @@
82.4 -<?xml version="1.0" encoding="UTF-8"?>
82.5 -<!--
82.6 -DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
82.7 -
82.8 -Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
82.9 -
82.10 -
82.11 -The contents of this file are subject to the terms of either the GNU
82.12 -General Public License Version 2 only ("GPL") or the Common
82.13 -Development and Distribution License("CDDL") (collectively, the
82.14 -"License"). You may not use this file except in compliance with the
82.15 -License. You can obtain a copy of the License at
82.16 -http://www.netbeans.org/cddl-gplv2.html
82.17 -or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
82.18 -specific language governing permissions and limitations under the
82.19 -License. When distributing the software, include this License Header
82.20 -Notice in each file and include the License file at
82.21 -nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
82.22 -particular file as subject to the "Classpath" exception as provided
82.23 -by Sun in the GPL Version 2 section of the License file that
82.24 -accompanied this code. If applicable, add the following below the
82.25 -License Header, with the fields enclosed by brackets [] replaced by
82.26 -your own identifying information:
82.27 -"Portions Copyrighted [year] [name of copyright owner]"
82.28 -
82.29 -Contributor(s):
82.30 -
82.31 -The Original Software is NetBeans. The Initial Developer of the Original
82.32 -Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
82.33 -Microsystems, Inc. All Rights Reserved.
82.34 -
82.35 -If you wish your version of this file to be governed by only the CDDL
82.36 -or only the GPL Version 2, indicate your decision by adding
82.37 -"[Contributor] elects to include this software in this distribution
82.38 -under the [CDDL or GPL Version 2] license." If you do not indicate a
82.39 -single choice of license, a recipient has the option to distribute
82.40 -your version of this file under either the CDDL, the GPL Version 2 or
82.41 -to extend the choice of license to its licensees as provided above.
82.42 -However, if you add GPL Version 2 code and therefore, elected the GPL
82.43 -Version 2 license, then the option applies only if the new code is
82.44 -made subject to such option by the copyright holder.
82.45 --->
82.46 -<!DOCTYPE apichanges PUBLIC "-//NetBeans//DTD API changes list 1.0//EN" "../nbbuild/javadoctools/apichanges.dtd">
82.47 -<apichanges>
82.48 -<apidefs>
82.49 - <apidef name="lookup">Lookup API</apidef>
82.50 -</apidefs>
82.51 -<changes>
82.52 - <change id="named.services.provider">
82.53 - <api name="lookup"/>
82.54 - <summary>Introducing semihidden SPI</summary>
82.55 - <version major="8" minor="1"/>
82.56 - <date day="15" month="1" year="2010"/>
82.57 - <author login="jtulach"/>
82.58 - <compatibility
82.59 - addition="yes"
82.60 - binary="compatible" deletion="no" deprecation="no"
82.61 - modification="no" semantic="compatible" source="compatible"
82.62 - />
82.63 - <description>
82.64 - <p>
82.65 - Adding SPI interface package for those who implement
82.66 - the NetBeans platform. This package is not shown in Javadoc
82.67 - as it does not form a generally available public API.
82.68 - </p>
82.69 - </description>
82.70 - <issue number="179289"/>
82.71 - </change>
82.72 - <change id="lookup.is.free">
82.73 - <api name="lookup"/>
82.74 - <summary>Separate module for Lookup API</summary>
82.75 - <version major="8" minor="0"/>
82.76 - <date day="20" month="12" year="2009"/>
82.77 - <author login="jtulach"/>
82.78 - <compatibility modification="yes">
82.79 - <p>
82.80 - Runtime compatibility remains, compile time compatibility is
82.81 - mostly preserved too. It is however recommended to upgrade
82.82 - dependencies of your modules. Try running
82.83 - <code>ant fix-dependencies</code> in your Ant module.
82.84 - </p>
82.85 - </compatibility>
82.86 - <description>
82.87 - <p>
82.88 - <a href="@org-openide-util-lookup@/org/openide/util/Lookup.html">Lookup</a>
82.89 - and its associated interfaces are now available as a
82.90 - <a href="@org-openide-util-lookup@/overview-summary.html">separate module</a>.
82.91 - </p>
82.92 - </description>
82.93 - <class package="org.openide.util" name="Lookup"/>
82.94 - <class package="org.openide.util.lookup" name="AbstractLookup"/>
82.95 - <class package="org.openide.util.lookup" name="ProxyLookup"/>
82.96 - <class package="org.openide.util.lookup" name="Lookups"/>
82.97 - <issue number="170056"/>
82.98 - </change>
82.99 - <change id="org.openide.util.Lookup.paths">
82.100 - <api name="lookup"/>
82.101 - <summary>Added
82.102 - <code>org.openide.util.Lookup.paths</code> property
82.103 - </summary>
82.104 - <version major="7" minor="24"/>
82.105 - <date day="19" month="6" year="2009"/>
82.106 - <author login="jtulach"/>
82.107 - <compatibility addition="yes"/>
82.108 - <description>
82.109 - <p>
82.110 - Better way to integrate Lookup.getDefault() and system filesystem.
82.111 - </p>
82.112 - </description>
82.113 - <class package="org.openide.util" name="Lookup"/>
82.114 - <issue number="166782"/>
82.115 - </change>
82.116 - <change id="ServiceProvider">
82.117 - <api name="lookup"/>
82.118 - <summary>Added <code>ServiceProvider</code> annotation</summary>
82.119 - <version major="7" minor="20"/>
82.120 - <date day="1" month="11" year="2008"/>
82.121 - <author login="jglick"/>
82.122 - <compatibility addition="yes">
82.123 - <p>
82.124 - Modules registering services using <code>META-INF/services</code>
82.125 - files in the source tree are encouraged to switch to the annotation.
82.126 - </p>
82.127 - </compatibility>
82.128 - <description>
82.129 - <p>
82.130 - Added annotations <code>ServiceProvider</code> and <code>ServiceProviders</code>
82.131 - to simplify registration of global singleton services.
82.132 - </p>
82.133 - </description>
82.134 - <class package="org.openide.util.lookup" name="ServiceProvider"/>
82.135 - <class package="org.openide.util.lookup" name="ServiceProviders"/>
82.136 - <issue number="150447"/>
82.137 - </change>
82.138 - <change id="Lookup.asynchronous">
82.139 - <api name="lookup"/>
82.140 - <summary>AbstractLookup and ProxyLookup fire changes asynchronously</summary>
82.141 - <version major="7" minor="16"/>
82.142 - <date day="27" month="6" year="2008"/>
82.143 - <author login="jtulach"/>
82.144 - <compatibility addition="yes" binary="compatible" semantic="compatible"/>
82.145 - <description>
82.146 - <p>
82.147 - All modification methods in <code>AbstractLookup</code> and <code>ProxyLookup</code>
82.148 - were extended to accept an
82.149 - <a href="@JDK@/java/util/concurrent/Executor.html">Executor</a>.
82.150 - If not null, it is used to dispatch events to listeners sometime
82.151 - "later". Also the <code>AbstractLookup.Content</code>
82.152 - and <code>InstanceContent</code> constructors
82.153 - have been extended to accept such <code>Executor</code>s.
82.154 - </p>
82.155 - </description>
82.156 - <class package="org.openide.util.lookup" name="AbstractLookup"/>
82.157 - <class package="org.openide.util.lookup" name="ProxyLookup"/>
82.158 - <class package="org.openide.util.lookup" name="InstanceContent"/>
82.159 - <issue number="134297"/>
82.160 - </change>
82.161 -
82.162 - <change id="Lookups.forPath">
82.163 - <api name="lookup"/>
82.164 - <summary>Added simplified support for named lookups <code>Lookups.forPath</code></summary>
82.165 - <version major="7" minor="9"/>
82.166 - <date day="17" month="4" year="2007"/>
82.167 - <author login="jtulach"/>
82.168 - <compatibility addition="yes"/>
82.169 - <description>
82.170 - <p>
82.171 - New method <a href="@TOP@/org/openide/util/lookup/Lookups.html#forPath(java.lang.String)">Lookups.forPath(String)</a>
82.172 - has been added to replace now deprecated <a href="@org-openide-loaders@/org/openide/loaders/FolderLookup.html">FolderLookup</a>
82.173 - and allow modules who wants to read settings from layers
82.174 - to do so with a simpler code, without dependency on DataSystems API.
82.175 - </p>
82.176 - </description>
82.177 - <class package="org.openide.util.lookup" name="Lookups"/>
82.178 - <issue number="98426"/>
82.179 - </change>
82.180 -
82.181 - <change id="lookupAll-lookupResult">
82.182 - <api name="lookup"/>
82.183 - <summary>Convenience methods added to <code>Lookup</code></summary>
82.184 - <version major="6" minor="10"/>
82.185 - <date day="3" month="4" year="2006"/>
82.186 - <author login="jglick"/>
82.187 - <compatibility addition="yes" binary="compatible" source="incompatible">
82.188 - <p>
82.189 - Could conceivably conflict with existing subclass method with same signature
82.190 - with different semantics or return type.
82.191 - </p>
82.192 - </compatibility>
82.193 - <description>
82.194 - <p>
82.195 - Two methods, <code>lookupResult</code> and <code>lookupAll</code>, were
82.196 - added to <code>Lookup</code> to encapsulate the most common usage patterns
82.197 - with less typing, and more importantly avoiding the need to explicitly
82.198 - make a <code>Lookup.Template</code> object.
82.199 - </p>
82.200 - </description>
82.201 - <class package="org.openide.util" name="Lookup"/>
82.202 - <issue number="73848"/>
82.203 - </change>
82.204 - <change id="less-events-from-proxylookup" >
82.205 - <api name="lookup"/>
82.206 - <summary>Less change notifications from ProxyLookup</summary>
82.207 - <version major="6" minor="7"/>
82.208 - <date day="11" month="11" year="2005"/>
82.209 - <author login="jtulach"/>
82.210 - <compatibility addition="no" modification="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no"/>
82.211 - <description>
82.212 - <a href="@TOP@/org/openide/util/lookup/ProxyLookup.html">ProxyLookup.setLookups</a>
82.213 - used to fire <a href="@TOP@/org/openide/util/LookupEvent.html">LookupEvent</a> every
82.214 - time it was called. Now it always checks whether there was a change to the
82.215 - previous state. This will reduce the number of events delivered when a small
82.216 - change is made. Also results from both
82.217 - <a href="@TOP@/org/openide/util/lookup/ProxyLookup.html">ProxyLookup</a>
82.218 - and <a href="@TOP@/org/openide/util/lookup/AbstractLookup.html">AbstractLookup</a>
82.219 - were modified to return immutable <code>Collection</code>s.
82.220 - So do not try to modify them. It was always documented that the
82.221 - results, are immutable and also it was never said that a change is
82.222 - delivered when there is no change in the result, so this is considered
82.223 - compatible change, even it is know that at least one piece of code
82.224 - in NetBeans relied on this behaviour.
82.225 - </description>
82.226 - <class package="org.openide.util.lookup" name="ProxyLookup"/>
82.227 - <class package="org.openide.util.lookup" name="AbstractLookup"/>
82.228 - <issue number="68031"/>
82.229 - </change>
82.230 -
82.231 -
82.232 - <change id="excluding-lookup">
82.233 - <api name="lookup"/>
82.234 - <summary>
82.235 -<code>Lookups.exclude</code> added to simplify writing of lookups that filter content of other lookups</summary>
82.236 - <version major="5" minor="4"/>
82.237 - <date day="14" month="1" year="2005"/>
82.238 - <author login="jtulach"/>
82.239 - <compatibility binary="compatible" source="compatible" semantic="compatible" deprecation="no" addition="no" deletion="no" modification="no"/>
82.240 - <description>
82.241 - <p>New method that takes lookup and set of classes and return new lookup
82.242 - which contains everything from the original one except instances of
82.243 - the specified classes has been added.
82.244 - </p>
82.245 - </description>
82.246 - <class package="org.openide.util.lookup" name="Lookups"/>
82.247 - <issue number="53058"/>
82.248 - </change>
82.249 - <change>
82.250 - <api name="lookup"/>
82.251 - <summary>Added ability to order items in META-INF/services/ lookup</summary>
82.252 - <version major="4" minor="34"/>
82.253 - <date day="9" month="5" year="2004"/>
82.254 - <author login="dkonecny"/>
82.255 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
82.256 - <description>
82.257 - Items in META-INF/services/ lookup can be followed by advisory
82.258 - "position" attribute. The resulting lookup will list first items with lower
82.259 - position value. Items without position attribute will be listed
82.260 - last. See documentation for more details on format.
82.261 - </description>
82.262 - <class package="org.openide.util.lookup" name="Lookups"/>
82.263 - <issue number="41606"/>
82.264 - </change>
82.265 - <change>
82.266 - <api name="lookup"/>
82.267 - <summary>New <code>lookupItem()</code> method in Lookups</summary>
82.268 - <version major="4" minor="8"/>
82.269 - <date day="9" month="7" year="2003"/>
82.270 - <author login="vstejskal"/>
82.271 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
82.272 - <description>
82.273 - New method that returns Lookup.Item implementation for given instance and key identifying
82.274 - that instance in the lookup. This method is useful when writing Looks which need to
82.275 - return some cookies (Collection of Lookup.Items).
82.276 - </description>
82.277 - <class package="org.openide.util.lookup" name="Lookups"/>
82.278 - </change>
82.279 - <change>
82.280 - <api name="lookup"/>
82.281 - <summary>New method Lookups.metaInfServices</summary>
82.282 - <version major="3" minor="35"/>
82.283 - <date day="5" month="2" year="2003"/>
82.284 - <author login="dstrupl"/>
82.285 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
82.286 - <description>
82.287 - A lookup that implements the JDK1.3 JAR services mechanism and delegates
82.288 - to META-INF/services/name.of.class files. This lookup was (is) used by core
82.289 - and the core had to use reflection to create an instance. Moreover can
82.290 - be usefull for module authors and in standalone library.
82.291 - </description>
82.292 - <class package="org.openide.util.lookup" name="Lookups"/>
82.293 - <issue number="29126"/>
82.294 - </change>
82.295 - <change>
82.296 - <api name="lookup"/>
82.297 - <summary>New method Lookups.proxy</summary>
82.298 - <version major="3" minor="9"/>
82.299 - <date day="20" month="9" year="2002"/>
82.300 - <author login="dstrupl"/>
82.301 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
82.302 - <description>
82.303 - Creates a lookup that delegates to another one but that one can change
82.304 - from time to time. The returned lookup checks every time somebody calls
82.305 - lookup or lookupItem method whether the provider still returns
82.306 - the same lookup. If not, it updates state of all Lookup.Results
82.307 - that it created (and that still exists).
82.308 - </description>
82.309 - <class package="org.openide.util.lookup" name="Lookups"/>
82.310 - <issue number="27425"/>
82.311 - </change>
82.312 - <change id="meta-inf-services">
82.313 - <api name="lookup"/>
82.314 - <summary>Modules can specify the content of Lookup.getDefault
82.315 - in META-INF/services</summary>
82.316 - <version major="3" minor="3"/>
82.317 - <date day="22" month="7" year="2002"/>
82.318 - <author login="jtulach"/>
82.319 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
82.320 - <description>
82.321 - The content of <code>Lookup.getDefault()</code> can be specified
82.322 - by a standard JDK registration mechanism, using JARs'
82.323 - <a href="http://java.sun.com/j2se/1.4/docs/guide/jar/jar.html#Service%20Provider" shape="rect">
82.324 - META-INF/services
82.325 - </a>
82.326 - directory. This is suitable for services that do not change,
82.327 - do not require user modification and that need to be ready
82.328 - soon during initialization of the system.
82.329 - </description>
82.330 - </change>
82.331 - <change>
82.332 - <api name="lookup"/>
82.333 - <summary>Added org.openide.util.lookup.Lookups</summary>
82.334 - <version major="2" minor="21"/>
82.335 - <date day="28" month="5" year="2002"/>
82.336 - <author login="dstrupl"/>
82.337 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
82.338 - <description>New utility class added. The class cannot be instantiated
82.339 - and contains following static methods:
82.340 - <pre xml:space="preserve">
82.341 -<span class="keyword">public</span> <span class="keyword">static</span> <span class="type">Lookup</span> <span class="function-name">singleton</span>(<span class="type">Object</span> <span class="variable-name">objectToLookup</span>);
82.342 -<span class="keyword">public</span> <span class="keyword">static</span> <span class="type">Lookup</span> <span class="function-name">fixed</span>(<span class="type">Object</span>[] <span class="variable-name">objectsToLookup</span>);
82.343 -<span class="keyword">public</span> <span class="keyword">static</span> <span class="type">Lookup</span> <span class="function-name">fixed</span>(<span class="type">Object</span>[] <span class="variable-name">keys</span>, <span class="type">InstanceContent.Convertor</span> <span class="variable-name">convertor</span>);
82.344 -</pre>
82.345 - The methods return an instance of simple lookup implementation
82.346 - that holds the objects passed a parameter.
82.347 - </description>
82.348 - <class package="org.openide.util.lookup" name="Lookups"/>
82.349 - <issue number="20550"/>
82.350 - </change>
82.351 - <change id="AbstractLookup.Content-ProxyLookup.beforeLookup">
82.352 - <api name="lookup"/>
82.353 - <summary>Enhanced usage of ProxyLookup & AbstractLookup.Content</summary>
82.354 - <version major="1" minor="31"/>
82.355 - <date day="18" month="8" year="2001"/>
82.356 - <author login="jtulach"/>
82.357 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
82.358 - <description>
82.359 - <code>AbstractLookup.Content</code> made public to allow its usage
82.360 - for objects that do not subclass AbstractLookup. <code>ProxyLookup.beforeLookup</code>
82.361 - added so subclasses can update themselves (call setLookups (...)) before the actual lookup is
82.362 - performed.
82.363 - </description>
82.364 - <class package="org.openide.util.lookup" name="AbstractLookup"/>
82.365 - <class package="org.openide.util.lookup" name="ProxyLookup"/>
82.366 - </change>
82.367 - <change>
82.368 - <api name="lookup"/>
82.369 - <summary>Instance content simplifies creation of lookups</summary>
82.370 - <version major="1" minor="25"/>
82.371 - <!-- XXX date unknown -->
82.372 - <author login="jtulach"/>
82.373 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
82.374 - <description>
82.375 - Added <code>AbstractLookup.Content</code> which can be passed to an
82.376 - abstract lookup in its constructor and used to control the contents
82.377 - easily. Also <code>InstanceLookup</code> provides the common easy
82.378 - implementation.
82.379 - </description>
82.380 - <class package="org.openide.util.lookup" name="AbstractLookup"/>
82.381 - <class package="org.openide.util.lookup" name="InstanceContent"/>
82.382 - </change>
82.383 - <change>
82.384 - <api name="lookup"/>
82.385 - <summary>Folder lookup may be serialized</summary>
82.386 - <version major="3" minor="27"/>
82.387 - <date day="7" month="1" year="2003"/>
82.388 - <author login="jglick"/>
82.389 - <compatibility modification="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" addition="no" deletion="no">
82.390 - Modules which rely on a data object under <samp>Services/</samp> gaining
82.391 - or losing <code>InstanceCookie</code> between sessions may not work
82.392 - correctly with the cache. This is probably very rare.
82.393 - </compatibility>
82.394 - <description>
82.395 - To implement lookup caching, some lookup implementations are now
82.396 - serializable: <code>AbstractLookup</code> as well as
82.397 - <code>FolderLookup</code>'s lookup. <code>ProxyLookup</code> has a
82.398 - protected subclass constructor permitting subclasses to be serializable.
82.399 - </description>
82.400 - <class package="org.openide.util.lookup" name="AbstractLookup"/>
82.401 - <class package="org.openide.util.lookup" name="ProxyLookup"/>
82.402 - <issue number="20190"/>
82.403 - </change>
82.404 - <change>
82.405 - <api name="lookup"/>
82.406 - <summary>Changes in access protection of proxy lookup</summary>
82.407 - <version major="1" minor="19"/>
82.408 - <date day="8" month="7" year="2001"/>
82.409 - <compatibility modification="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" addition="no" deletion="no">
82.410 - Changes to newly added feature.
82.411 - </compatibility>
82.412 - <description>
82.413 - <code>ProxyLookup.setLookups</code> made protected instead of public so
82.414 - nobody can misuse the method except the creator of the object and
82.415 - <code>ProxyLookup.getLookups</code> added. <code>ProxyLookup</code> made
82.416 - non final.
82.417 - </description>
82.418 - <class package="org.openide.util.lookup" name="ProxyLookup"/>
82.419 - </change>
82.420 - <change>
82.421 - <api name="lookup"/>
82.422 - <summary>Lookup service providers package created</summary>
82.423 - <version major="1" minor="9"/>
82.424 - <date day="1" month="6" year="2001"/>
82.425 - <author login="jtulach"/>
82.426 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
82.427 - <description>
82.428 - Package <code>org.openide.util.lookup</code> created, should hold SPI
82.429 - interfaces for lookup. Initially filled with <code>AbstractLookup</code>
82.430 - which introduces <code>AbstractLookup.Pair</code> and with
82.431 - <code>ProxyLookup</code>.
82.432 - </description>
82.433 - <class package="org.openide.util.lookup" name="AbstractLookup"/>
82.434 - <class package="org.openide.util.lookup" name="ProxyLookup"/>
82.435 - <package name="org.openide.util.lookup"/>
82.436 - </change>
82.437 - <change>
82.438 - <api name="lookup"/>
82.439 - <summary>Added lookup items and support APIs</summary>
82.440 - <version major="1" minor="8"/>
82.441 - <date day="25" month="5" year="2001"/>
82.442 - <author login="jtulach"/>
82.443 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
82.444 - <description>
82.445 - <code>Lookup</code> enhanced. Interface <code>Lookup.Item</code> and
82.446 - additional methods to access it also added.
82.447 - </description>
82.448 - <class package="org.openide.util" name="Lookup"/>
82.449 - </change>
82.450 - <change>
82.451 - <api name="lookup"/>
82.452 - <summary>Lookup system introduced</summary>
82.453 - <date day="1" month="3" year="2001"/>
82.454 - <author login="jtulach"/>
82.455 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
82.456 - <description>
82.457 - Better version of <code>Lookup</code> introduced. There is a
82.458 - <code>org.openide.util.Lookup</code> with bunch of inner classes and
82.459 - <code>org.openide.util.LookupListener</code> and
82.460 - <code>org.openide.util.LookupEvent</code>.
82.461 - </description>
82.462 - <class package="org.openide.util" name="Lookup"/>
82.463 - <class package="org.openide.util" name="LookupEvent"/>
82.464 - <class package="org.openide.util" name="LookupListener"/>
82.465 - </change>
82.466 -</changes>
82.467 -<htmlcontents>
82.468 -<head>
82.469 -<title>Change History for the Lookup API</title>
82.470 -<link rel="stylesheet" href="prose.css" type="text/css"/>
82.471 -</head>
82.472 -<body>
82.473 -<p class="overviewlink">
82.474 -<a href="overview-summary.html">Overview</a>
82.475 -</p>
82.476 -<h1>Introduction</h1>
82.477 -<h2>What do the Dates Mean?</h2>
82.478 -<p>The supplied dates indicate when the API change was made, on the CVS
82.479 -trunk. From this you can generally tell whether the change should be
82.480 -present in a given build or not; for trunk builds, simply whether it
82.481 -was made before or after the change; for builds on a stabilization
82.482 -branch, whether the branch was made before or after the given date. In
82.483 -some cases corresponding API changes have been made both in the trunk
82.484 -and in an in-progress stabilization branch, if they were needed for a
82.485 -bug fix; this ought to be marked in this list.</p>
82.486 -<ul>
82.487 -<li>The <code>release41</code> branch was made on Apr 03 '05 for use in the NetBeans 4.1 release.
82.488 -Specification versions: 6.0 begins after this point.</li>
82.489 -<li>The <code>release40</code> branch was made on Nov 01 '04 for use in the NetBeans 4.0 release.
82.490 -Specification versions: 5.0 begins after this point.</li>
82.491 -</ul>
82.492 -<hr/>
82.493 -<standard-changelists module-code-name="$codebase"/>
82.494 -<hr/>
82.495 -<p>@FOOTER@</p>
82.496 -</body>
82.497 -</htmlcontents>
82.498 -</apichanges>
83.1 --- a/openide.util.lookup/manifest.mf Wed Jan 27 17:46:23 2010 -0500
83.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
83.3 @@ -1,5 +0,0 @@
83.4 -Manifest-Version: 1.0
83.5 -OpenIDE-Module: org.openide.util.lookup
83.6 -OpenIDE-Module-Localizing-Bundle: org/openide/util/lookup/Bundle.properties
83.7 -OpenIDE-Module-Specification-Version: 8.1
83.8 -
84.1 --- a/openide.util.lookup/nbproject/project.properties Wed Jan 27 17:46:23 2010 -0500
84.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
84.3 @@ -1,47 +0,0 @@
84.4 -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
84.5 -#
84.6 -# Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
84.7 -#
84.8 -# The contents of this file are subject to the terms of either the GNU
84.9 -# General Public License Version 2 only ("GPL") or the Common
84.10 -# Development and Distribution License("CDDL") (collectively, the
84.11 -# "License"). You may not use this file except in compliance with the
84.12 -# License. You can obtain a copy of the License at
84.13 -# http://www.netbeans.org/cddl-gplv2.html
84.14 -# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
84.15 -# specific language governing permissions and limitations under the
84.16 -# License. When distributing the software, include this License Header
84.17 -# Notice in each file and include the License file at
84.18 -# nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
84.19 -# particular file as subject to the "Classpath" exception as provided
84.20 -# by Sun in the GPL Version 2 section of the License file that
84.21 -# accompanied this code. If applicable, add the following below the
84.22 -# License Header, with the fields enclosed by brackets [] replaced by
84.23 -# your own identifying information:
84.24 -# "Portions Copyrighted [year] [name of copyright owner]"
84.25 -#
84.26 -# Contributor(s):
84.27 -#
84.28 -# The Original Software is NetBeans. The Initial Developer of the Original
84.29 -# Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
84.30 -# Microsystems, Inc. All Rights Reserved.
84.31 -#
84.32 -# If you wish your version of this file to be governed by only the CDDL
84.33 -# or only the GPL Version 2, indicate your decision by adding
84.34 -# "[Contributor] elects to include this software in this distribution
84.35 -# under the [CDDL or GPL Version 2] license." If you do not indicate a
84.36 -# single choice of license, a recipient has the option to distribute
84.37 -# your version of this file under either the CDDL, the GPL Version 2 or
84.38 -# to extend the choice of license to its licensees as provided above.
84.39 -# However, if you add GPL Version 2 code and therefore, elected the GPL
84.40 -# Version 2 license, then the option applies only if the new code is
84.41 -# made subject to such option by the copyright holder.
84.42 -
84.43 -module.jar.dir=lib
84.44 -javac.source=1.6
84.45 -javac.compilerargs=-Xlint -Xlint:-serial
84.46 -
84.47 -javadoc.arch=${basedir}/arch.xml
84.48 -javadoc.apichanges=${basedir}/apichanges.xml
84.49 -# Hide org.openide.util.lookup.implspi:
84.50 -module.javadoc.packages=org.openide.util,org.openide.util.lookup
85.1 --- a/openide.util.lookup/nbproject/project.xml Wed Jan 27 17:46:23 2010 -0500
85.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
85.3 @@ -1,29 +0,0 @@
85.4 -<?xml version="1.0" encoding="UTF-8"?>
85.5 -<project xmlns="http://www.netbeans.org/ns/project/1">
85.6 - <type>org.netbeans.modules.apisupport.project</type>
85.7 - <configuration>
85.8 - <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
85.9 - <code-name-base>org.openide.util.lookup</code-name-base>
85.10 - <module-dependencies/>
85.11 - <test-dependencies>
85.12 - <test-type>
85.13 - <name>unit</name>
85.14 - <test-dependency>
85.15 - <code-name-base>org.netbeans.libs.junit4</code-name-base>
85.16 - <compile-dependency/>
85.17 - </test-dependency>
85.18 - <test-dependency>
85.19 - <code-name-base>org.netbeans.modules.nbjunit</code-name-base>
85.20 - <recursive/>
85.21 - <compile-dependency/>
85.22 - </test-dependency>
85.23 - </test-type>
85.24 - </test-dependencies>
85.25 - <public-packages>
85.26 - <package>org.openide.util</package>
85.27 - <package>org.openide.util.lookup</package>
85.28 - <package>org.openide.util.lookup.implspi</package>
85.29 - </public-packages>
85.30 - </data>
85.31 - </configuration>
85.32 -</project>
86.1 --- a/openide.util.lookup/src/org/netbeans/modules/openide/util/ServiceProviderProcessor.java Wed Jan 27 17:46:23 2010 -0500
86.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
86.3 @@ -1,174 +0,0 @@
86.4 -/*
86.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
86.6 - *
86.7 - * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
86.8 - *
86.9 - * The contents of this file are subject to the terms of either the GNU
86.10 - * General Public License Version 2 only ("GPL") or the Common
86.11 - * Development and Distribution License("CDDL") (collectively, the
86.12 - * "License"). You may not use this file except in compliance with the
86.13 - * License. You can obtain a copy of the License at
86.14 - * http://www.netbeans.org/cddl-gplv2.html
86.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
86.16 - * specific language governing permissions and limitations under the
86.17 - * License. When distributing the software, include this License Header
86.18 - * Notice in each file and include the License file at
86.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
86.20 - * particular file as subject to the "Classpath" exception as provided
86.21 - * by Sun in the GPL Version 2 section of the License file that
86.22 - * accompanied this code. If applicable, add the following below the
86.23 - * License Header, with the fields enclosed by brackets [] replaced by
86.24 - * your own identifying information:
86.25 - * "Portions Copyrighted [year] [name of copyright owner]"
86.26 - *
86.27 - * If you wish your version of this file to be governed by only the CDDL
86.28 - * or only the GPL Version 2, indicate your decision by adding
86.29 - * "[Contributor] elects to include this software in this distribution
86.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
86.31 - * single choice of license, a recipient has the option to distribute
86.32 - * your version of this file under either the CDDL, the GPL Version 2 or
86.33 - * to extend the choice of license to its licensees as provided above.
86.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
86.35 - * Version 2 license, then the option applies only if the new code is
86.36 - * made subject to such option by the copyright holder.
86.37 - *
86.38 - * Contributor(s):
86.39 - *
86.40 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
86.41 - */
86.42 -
86.43 -package org.netbeans.modules.openide.util;
86.44 -
86.45 -import java.lang.annotation.Annotation;
86.46 -import java.util.Arrays;
86.47 -import java.util.Collection;
86.48 -import java.util.Collections;
86.49 -import java.util.HashSet;
86.50 -import java.util.LinkedList;
86.51 -import java.util.List;
86.52 -import java.util.Set;
86.53 -import javax.annotation.processing.Completion;
86.54 -import javax.annotation.processing.RoundEnvironment;
86.55 -import javax.annotation.processing.SupportedSourceVersion;
86.56 -import javax.lang.model.SourceVersion;
86.57 -import javax.lang.model.element.AnnotationMirror;
86.58 -import javax.lang.model.element.Element;
86.59 -import javax.lang.model.element.ExecutableElement;
86.60 -import javax.lang.model.element.TypeElement;
86.61 -import javax.lang.model.type.MirroredTypeException;
86.62 -import javax.lang.model.type.TypeKind;
86.63 -import javax.lang.model.type.TypeMirror;
86.64 -import org.openide.util.lookup.ServiceProvider;
86.65 -import org.openide.util.lookup.ServiceProviders;
86.66 -import org.openide.util.lookup.implspi.AbstractServiceProviderProcessor;
86.67 -
86.68 -@SupportedSourceVersion(SourceVersion.RELEASE_6)
86.69 -public class ServiceProviderProcessor extends AbstractServiceProviderProcessor {
86.70 -
86.71 - public @Override Set<String> getSupportedAnnotationTypes() {
86.72 - return new HashSet<String>(Arrays.asList(
86.73 - ServiceProvider.class.getCanonicalName(),
86.74 - ServiceProviders.class.getCanonicalName()
86.75 - ));
86.76 - }
86.77 -
86.78 - /** public for ServiceLoader */
86.79 - public ServiceProviderProcessor() {}
86.80 -
86.81 - protected boolean handleProcess(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
86.82 - for (Element el : roundEnv.getElementsAnnotatedWith(ServiceProvider.class)) {
86.83 - TypeElement clazz = (TypeElement) el;
86.84 - ServiceProvider sp = clazz.getAnnotation(ServiceProvider.class);
86.85 - register(clazz, ServiceProvider.class, sp);
86.86 - }
86.87 - for (Element el : roundEnv.getElementsAnnotatedWith(ServiceProviders.class)) {
86.88 - TypeElement clazz = (TypeElement) el;
86.89 - ServiceProviders spp = clazz.getAnnotation(ServiceProviders.class);
86.90 - for (ServiceProvider sp : spp.value()) {
86.91 - register(clazz, ServiceProviders.class, sp);
86.92 - }
86.93 - }
86.94 - return true;
86.95 - }
86.96 -
86.97 - private void register(TypeElement clazz, Class<? extends Annotation> annotation, ServiceProvider svc) {
86.98 - try {
86.99 - svc.service();
86.100 - assert false;
86.101 - return;
86.102 - } catch (MirroredTypeException e) {
86.103 - register(clazz, annotation, e.getTypeMirror(), svc.path(), svc.position(), svc.supersedes());
86.104 - }
86.105 - }
86.106 -
86.107 - @Override
86.108 - public Iterable<? extends Completion> getCompletions(Element annotated, AnnotationMirror annotation, ExecutableElement attr, String userText) {
86.109 - if (processingEnv == null || annotated == null || !annotated.getKind().isClass()) {
86.110 - return Collections.emptyList();
86.111 - }
86.112 -
86.113 - if ( annotation == null
86.114 - || !"org.openide.util.lookup.ServiceProvider".contentEquals(((TypeElement) annotation.getAnnotationType().asElement()).getQualifiedName())) {
86.115 - return Collections.emptyList();
86.116 - }
86.117 -
86.118 - if (!"service".contentEquals(attr.getSimpleName())) {
86.119 - return Collections.emptyList();
86.120 - }
86.121 -
86.122 - TypeElement jlObject = processingEnv.getElementUtils().getTypeElement("java.lang.Object");
86.123 -
86.124 - if (jlObject == null) {
86.125 - return Collections.emptyList();
86.126 - }
86.127 -
86.128 - Collection<Completion> result = new LinkedList<Completion>();
86.129 - List<TypeElement> toProcess = new LinkedList<TypeElement>();
86.130 -
86.131 - toProcess.add((TypeElement) annotated);
86.132 -
86.133 - while (!toProcess.isEmpty()) {
86.134 - TypeElement c = toProcess.remove(0);
86.135 -
86.136 - result.add(new TypeCompletion(c.getQualifiedName().toString() + ".class"));
86.137 -
86.138 - List<TypeMirror> parents = new LinkedList<TypeMirror>();
86.139 -
86.140 - parents.add(c.getSuperclass());
86.141 - parents.addAll(c.getInterfaces());
86.142 -
86.143 - for (TypeMirror tm : parents) {
86.144 - if (tm == null || tm.getKind() != TypeKind.DECLARED) {
86.145 - continue;
86.146 - }
86.147 -
86.148 - TypeElement type = (TypeElement) processingEnv.getTypeUtils().asElement(tm);
86.149 -
86.150 - if (!jlObject.equals(type)) {
86.151 - toProcess.add(type);
86.152 - }
86.153 - }
86.154 - }
86.155 -
86.156 - return result;
86.157 - }
86.158 -
86.159 - private static final class TypeCompletion implements Completion {
86.160 -
86.161 - private final String type;
86.162 -
86.163 - public TypeCompletion(String type) {
86.164 - this.type = type;
86.165 - }
86.166 -
86.167 - public String getValue() {
86.168 - return type;
86.169 - }
86.170 -
86.171 - public String getMessage() {
86.172 - return null;
86.173 - }
86.174 -
86.175 - }
86.176 -
86.177 -}
87.1 --- a/openide.util.lookup/src/org/openide/util/lookup/AbstractLookup.java Wed Jan 27 17:46:23 2010 -0500
87.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
87.3 @@ -1,1463 +0,0 @@
87.4 -/*
87.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
87.6 - *
87.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
87.8 - *
87.9 - * The contents of this file are subject to the terms of either the GNU
87.10 - * General Public License Version 2 only ("GPL") or the Common
87.11 - * Development and Distribution License("CDDL") (collectively, the
87.12 - * "License"). You may not use this file except in compliance with the
87.13 - * License. You can obtain a copy of the License at
87.14 - * http://www.netbeans.org/cddl-gplv2.html
87.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
87.16 - * specific language governing permissions and limitations under the
87.17 - * License. When distributing the software, include this License Header
87.18 - * Notice in each file and include the License file at
87.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
87.20 - * particular file as subject to the "Classpath" exception as provided
87.21 - * by Sun in the GPL Version 2 section of the License file that
87.22 - * accompanied this code. If applicable, add the following below the
87.23 - * License Header, with the fields enclosed by brackets [] replaced by
87.24 - * your own identifying information:
87.25 - * "Portions Copyrighted [year] [name of copyright owner]"
87.26 - *
87.27 - * Contributor(s):
87.28 - *
87.29 - * The Original Software is NetBeans. The Initial Developer of the Original
87.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
87.31 - * Microsystems, Inc. All Rights Reserved.
87.32 - *
87.33 - * If you wish your version of this file to be governed by only the CDDL
87.34 - * or only the GPL Version 2, indicate your decision by adding
87.35 - * "[Contributor] elects to include this software in this distribution
87.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
87.37 - * single choice of license, a recipient has the option to distribute
87.38 - * your version of this file under either the CDDL, the GPL Version 2 or
87.39 - * to extend the choice of license to its licensees as provided above.
87.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
87.41 - * Version 2 license, then the option applies only if the new code is
87.42 - * made subject to such option by the copyright holder.
87.43 - */
87.44 -package org.openide.util.lookup;
87.45 -
87.46 -import java.io.IOException;
87.47 -import java.io.ObjectOutputStream;
87.48 -import java.io.Serializable;
87.49 -import java.lang.ref.ReferenceQueue;
87.50 -import java.lang.ref.WeakReference;
87.51 -import java.util.ArrayList;
87.52 -import java.util.Arrays;
87.53 -import java.util.Collection;
87.54 -import java.util.Collections;
87.55 -import java.util.Enumeration;
87.56 -import java.util.HashMap;
87.57 -import java.util.HashSet;
87.58 -import java.util.Iterator;
87.59 -import java.util.LinkedHashSet;
87.60 -import java.util.Map;
87.61 -import java.util.Set;
87.62 -import java.util.TreeSet;
87.63 -import java.util.concurrent.Executor;
87.64 -import org.openide.util.Lookup;
87.65 -import org.openide.util.LookupEvent;
87.66 -import org.openide.util.LookupListener;
87.67 -import org.openide.util.lookup.implspi.ActiveQueue;
87.68 -
87.69 -
87.70 -/** Implementation of the lookup from OpenAPIs that is based on the
87.71 - * introduction of Item. This class should provide the default way
87.72 - * of how to store (Class, Object) pairs in the lookups. It offers
87.73 - * protected methods for subclasses to register the pairs.
87.74 - * <p>Serializable since 3.27.
87.75 - * @author Jaroslav Tulach
87.76 - * @since 1.9
87.77 - */
87.78 -public class AbstractLookup extends Lookup implements Serializable {
87.79 - static final long serialVersionUID = 5L;
87.80 -
87.81 - /** lock for initialization of the maps of lookups */
87.82 - private static final Object treeLock = new Object();
87.83 -
87.84 - /** the tree that registers all items (or Integer as a treshold size) */
87.85 - private Object tree;
87.86 -
87.87 - /** count of items in to lookup */
87.88 - private int count;
87.89 -
87.90 - /** Constructor to create this lookup and associate it with given
87.91 - * Content. The content than allows the creator to invoke protected
87.92 - * methods which are not accessible for any other user of the lookup.
87.93 - *
87.94 - * @param content the content to assciate with
87.95 - *
87.96 - * @since 1.25
87.97 - */
87.98 - public AbstractLookup(Content content) {
87.99 - content.attach(this);
87.100 - }
87.101 -
87.102 - /** Constructor for testing purposes that allows specification of storage
87.103 - * as mechanism as well.
87.104 - */
87.105 - AbstractLookup(Content content, Storage<?> storage) {
87.106 - this(content);
87.107 - this.tree = storage;
87.108 - initialize();
87.109 - }
87.110 -
87.111 - /** Constructor for testing purposes that allows specification of storage
87.112 - * as mechanism as well.
87.113 - * @param trashhold number of Pair to "remain small"
87.114 - */
87.115 - AbstractLookup(Content content, Integer trashhold) {
87.116 - this(content);
87.117 - this.tree = trashhold;
87.118 - }
87.119 -
87.120 - /** Default constructor for subclasses that do not need to provide a content
87.121 - */
87.122 - protected AbstractLookup() {
87.123 - }
87.124 -
87.125 - @Override
87.126 - public String toString() {
87.127 - if (tree instanceof Storage) {
87.128 - return "AbstractLookup" + lookup(new Lookup.Template<Object>(Object.class)).allItems(); // NOI18N
87.129 - } else {
87.130 - return super.toString();
87.131 - }
87.132 - }
87.133 -
87.134 - /** Entres the storage management system.
87.135 - */
87.136 - @SuppressWarnings("unchecked")
87.137 - private <T> AbstractLookup.Storage<T> enterStorage() {
87.138 - for (;;) {
87.139 - synchronized (treeLock) {
87.140 - if (tree instanceof AbstractLookup.Storage) {
87.141 - if (tree instanceof DelegatingStorage) {
87.142 - // somebody is using the lookup right now
87.143 - DelegatingStorage del = (DelegatingStorage) tree;
87.144 -
87.145 - // check whether there is not access from the same
87.146 - // thread (can throw exception)
87.147 - del.checkForTreeModification();
87.148 -
87.149 - try {
87.150 - treeLock.wait();
87.151 - } catch (InterruptedException ex) {
87.152 - // ignore and go on
87.153 - }
87.154 -
87.155 - continue;
87.156 - } else {
87.157 - // ok, tree is initialized and nobody is using it yet
87.158 - tree = new DelegatingStorage((Storage<T>) tree);
87.159 -
87.160 - return (Storage<T>) tree;
87.161 - }
87.162 - }
87.163 -
87.164 - // first time initialization of the tree
87.165 - if (tree instanceof Integer) {
87.166 - tree = new ArrayStorage((Integer) tree);
87.167 - } else {
87.168 - tree = new ArrayStorage();
87.169 - }
87.170 - }
87.171 -
87.172 - // the tree has not yet been initilized, initialize and go on again
87.173 - initialize();
87.174 - }
87.175 - }
87.176 -
87.177 - /** Exists tree ownership.
87.178 - */
87.179 - private AbstractLookup.Storage exitStorage() {
87.180 - synchronized (treeLock) {
87.181 - AbstractLookup.Storage stor = ((DelegatingStorage) tree).exitDelegate();
87.182 - tree = stor;
87.183 - treeLock.notifyAll();
87.184 -
87.185 - return stor;
87.186 - }
87.187 - }
87.188 -
87.189 - /** Method for subclasses to initialize them selves.
87.190 - */
87.191 - protected void initialize() {
87.192 - }
87.193 -
87.194 - /** Notifies subclasses that a query is about to be processed.
87.195 - * @param template the template
87.196 - */
87.197 - protected void beforeLookup(Template<?> template) {
87.198 - }
87.199 -
87.200 - /** The method to add instance to the lookup with.
87.201 - * @param pair class/instance pair
87.202 - */
87.203 - protected final void addPair(Pair<?> pair) {
87.204 - addPairImpl(pair, null);
87.205 - }
87.206 -
87.207 - /** The method to add instance to the lookup with.
87.208 - * @param pair class/instance pair
87.209 - * @param notifyIn the executor that will handle the notification of events
87.210 - * @since 7.16
87.211 - */
87.212 - protected final void addPair(Pair<?> pair, Executor notifyIn) {
87.213 - addPairImpl(pair, notifyIn);
87.214 - }
87.215 -
87.216 - private final <Transaction> void addPairImpl(Pair<?> pair, Executor notifyIn) {
87.217 - HashSet<R> toNotify = new HashSet<R>();
87.218 -
87.219 - AbstractLookup.Storage<Transaction> t = enterStorage();
87.220 - Transaction transaction = null;
87.221 -
87.222 - try {
87.223 - transaction = t.beginTransaction(-2);
87.224 -
87.225 - if (t.add(pair, transaction)) {
87.226 - try {
87.227 - pair.setIndex(t, count++);
87.228 - } catch (IllegalStateException ex) {
87.229 - // remove the pair
87.230 - t.remove(pair, transaction);
87.231 -
87.232 - // rethrow the exception
87.233 - throw ex;
87.234 - }
87.235 -
87.236 - // if the pair is newly added and was not there before
87.237 - t.endTransaction(transaction, toNotify);
87.238 - } else {
87.239 - // just finish the process by calling endTransaction
87.240 - t.endTransaction(transaction, new HashSet<R>());
87.241 - }
87.242 - } finally {
87.243 - exitStorage();
87.244 - }
87.245 -
87.246 - notifyIn(notifyIn, toNotify);
87.247 - }
87.248 -
87.249 - /** Remove instance.
87.250 - * @param pair class/instance pair
87.251 - */
87.252 - protected final void removePair(Pair<?> pair) {
87.253 - removePairImpl(pair, null);
87.254 - }
87.255 - /** Remove instance.
87.256 - * @param pair class/instance pair
87.257 - * @param notifyIn the executor that will handle the notification of events
87.258 - * @since 7.16
87.259 - */
87.260 - protected final void removePair(Pair<?> pair, Executor notifyIn) {
87.261 - removePairImpl(pair, notifyIn);
87.262 - }
87.263 -
87.264 - private <Transaction> void removePairImpl(Pair<?> pair, Executor notifyIn) {
87.265 - HashSet<R> toNotify = new HashSet<R>();
87.266 -
87.267 - AbstractLookup.Storage<Transaction> t = enterStorage();
87.268 - Transaction transaction = null;
87.269 -
87.270 - try {
87.271 - transaction = t.beginTransaction(-1);
87.272 - t.remove(pair, transaction);
87.273 - t.endTransaction(transaction, toNotify);
87.274 - } finally {
87.275 - exitStorage();
87.276 - }
87.277 -
87.278 - notifyIn(notifyIn, toNotify);
87.279 - }
87.280 -
87.281 - /** Changes all pairs in the lookup to new values.
87.282 - * @param collection the collection of (Pair) objects
87.283 - */
87.284 - protected final void setPairs(Collection<? extends Pair> collection) {
87.285 - setPairs(collection, null);
87.286 - }
87.287 -
87.288 - /** Changes all pairs in the lookup to new values, notifies listeners
87.289 - * using provided executor.
87.290 - *
87.291 - * @param collection the collection of (Pair) objects
87.292 - * @param notifyIn the executor that will handle the notification of events
87.293 - * @since 7.16
87.294 - */
87.295 - protected final void setPairs(Collection<? extends Pair> collection, Executor notifyIn) {
87.296 - HashSet<R> listeners = setPairsAndCollectListeners(collection);
87.297 - notifyIn(notifyIn, listeners);
87.298 - }
87.299 -
87.300 - private final void notifyIn(Executor notifyIn, final HashSet<R> listeners) {
87.301 - NotifyListeners notify = new NotifyListeners(listeners);
87.302 - if (notify.shallRun()) {
87.303 - if (notifyIn == null) {
87.304 - notify.run();
87.305 - } else {
87.306 - notifyIn.execute(notify);
87.307 - }
87.308 - }
87.309 - }
87.310 -
87.311 - /** Getter for set of pairs. Package private contract with MetaInfServicesLookup.
87.312 - * @return a LinkedHashSet that can be modified
87.313 - */
87.314 - final LinkedHashSet<Pair<?>> getPairsAsLHS() {
87.315 - AbstractLookup.Storage<?> t = enterStorage();
87.316 -
87.317 - try {
87.318 - Enumeration<Pair<Object>> en = t.lookup(Object.class);
87.319 - TreeSet<Pair<?>> arr = new TreeSet<Pair<?>>(ALPairComparator.DEFAULT);
87.320 - while (en.hasMoreElements()) {
87.321 - Pair<Object> item = en.nextElement();
87.322 - arr.add(item);
87.323 - }
87.324 - return new LinkedHashSet<Pair<?>>(arr);
87.325 - } finally {
87.326 - exitStorage();
87.327 - }
87.328 - }
87.329 -
87.330 - /** Collects listeners without notification. Needed in MetaInfServicesLookup
87.331 - * right now, but maybe will become an API later.
87.332 - */
87.333 - final <Transaction> HashSet<R> setPairsAndCollectListeners(Collection<? extends Pair> collection) {
87.334 - HashSet<R> toNotify = new HashSet<R>(27);
87.335 -
87.336 - AbstractLookup.Storage<Transaction> t = enterStorage();
87.337 - Transaction transaction = null;
87.338 -
87.339 - try {
87.340 - // map between the Items and their indexes (Integer)
87.341 - HashMap<Item<?>,Info> shouldBeThere = new HashMap<Item<?>,Info>(collection.size() * 2);
87.342 -
87.343 - count = 0;
87.344 -
87.345 - Iterator it = collection.iterator();
87.346 - transaction = t.beginTransaction(collection.size());
87.347 -
87.348 - while (it.hasNext()) {
87.349 - Pair item = (Pair) it.next();
87.350 -
87.351 - if (t.add(item, transaction)) {
87.352 - // the item has not been there yet
87.353 - //t.endTransaction(transaction, toNotify);
87.354 - }
87.355 -
87.356 - // remeber the item, because it should not be removed
87.357 - shouldBeThere.put(item, new Info(count++, transaction));
87.358 -
87.359 - // arr.clear ();
87.360 - }
87.361 -
87.362 - // Object transaction = t.beginTransaction ();
87.363 - // deletes all objects that should not be there and
87.364 - t.retainAll(shouldBeThere, transaction);
87.365 -
87.366 - // collect listeners
87.367 - t.endTransaction(transaction, toNotify);
87.368 -
87.369 - /*
87.370 - // check consistency
87.371 - Enumeration en = t.lookup (java.lang.Object.class);
87.372 - boolean[] max = new boolean[count];
87.373 - int mistake = -1;
87.374 - while (en.hasMoreElements ()) {
87.375 - Pair item = (Pair)en.nextElement ();
87.376 -
87.377 - if (max[item.index]) {
87.378 - mistake = item.index;
87.379 - }
87.380 - max[item.index] = true;
87.381 - }
87.382 -
87.383 - if (mistake != -1) {
87.384 - System.err.println ("Mistake at: " + mistake);
87.385 - tree.print (System.err, true);
87.386 - }
87.387 - */
87.388 - } finally {
87.389 - exitStorage();
87.390 - }
87.391 -
87.392 - return toNotify;
87.393 - }
87.394 -
87.395 - private final void writeObject(ObjectOutputStream oos)
87.396 - throws IOException {
87.397 - AbstractLookup.Storage s = enterStorage();
87.398 -
87.399 - try {
87.400 - // #36830: Serializing only InheritanceTree no ArrayStorage
87.401 - s.beginTransaction(Integer.MAX_VALUE);
87.402 -
87.403 - // #32040: don't write half-made changes
87.404 - oos.defaultWriteObject();
87.405 - } finally {
87.406 - exitStorage();
87.407 - }
87.408 - }
87.409 -
87.410 - public final <T> T lookup(Class<T> clazz) {
87.411 - Lookup.Item<T> item = lookupItem(new Lookup.Template<T>(clazz));
87.412 - return (item == null) ? null : item.getInstance();
87.413 - }
87.414 -
87.415 - @Override
87.416 - public final <T> Lookup.Item<T> lookupItem(Lookup.Template<T> template) {
87.417 - AbstractLookup.this.beforeLookup(template);
87.418 -
87.419 - ArrayList<Pair<T>> list = null;
87.420 - AbstractLookup.Storage<?> t = enterStorage();
87.421 -
87.422 - try {
87.423 - Enumeration<Pair<T>> en;
87.424 -
87.425 - try {
87.426 - en = t.lookup(template.getType());
87.427 -
87.428 - return findSmallest(en, template, false);
87.429 - } catch (AbstractLookup.ISE ex) {
87.430 - // not possible to enumerate the exception, ok, copy it
87.431 - // to create new
87.432 - list = new ArrayList<Pair<T>>();
87.433 - en = t.lookup(null); // this should get all the items without any checks
87.434 -
87.435 - // the checks will be done out side of the storage
87.436 - while (en.hasMoreElements()) {
87.437 - list.add(en.nextElement());
87.438 - }
87.439 - }
87.440 - } finally {
87.441 - exitStorage();
87.442 - }
87.443 -
87.444 - return findSmallest(Collections.enumeration(list), template, true);
87.445 - }
87.446 -
87.447 - private static <T> Pair<T> findSmallest(Enumeration<Pair<T>> en, Lookup.Template<T> template, boolean deepCheck) {
87.448 - int smallest = InheritanceTree.unsorted(en) ? Integer.MAX_VALUE : Integer.MIN_VALUE;
87.449 - Pair<T> res = null;
87.450 -
87.451 - while (en.hasMoreElements()) {
87.452 - Pair<T> item = en.nextElement();
87.453 -
87.454 - if (matches(template, item, deepCheck)) {
87.455 - if (smallest == Integer.MIN_VALUE) {
87.456 - // ok, sorted enumeration the first that matches is fine
87.457 - return item;
87.458 - } else {
87.459 - // check for the smallest item
87.460 - if (smallest > item.getIndex()) {
87.461 - smallest = item.getIndex();
87.462 - res = item;
87.463 - }
87.464 - }
87.465 - }
87.466 - }
87.467 -
87.468 - return res;
87.469 - }
87.470 -
87.471 - public final <T> Lookup.Result<T> lookup(Lookup.Template<T> template) {
87.472 - for (;;) {
87.473 - AbstractLookup.ISE toRun = null;
87.474 -
87.475 - AbstractLookup.Storage<?> t = enterStorage();
87.476 -
87.477 - try {
87.478 - R<T> r = new R<T>();
87.479 - ReferenceToResult<T> newRef = new ReferenceToResult<T>(r, this, template);
87.480 - newRef.next = t.registerReferenceToResult(newRef);
87.481 -
87.482 - return r;
87.483 - } catch (AbstractLookup.ISE ex) {
87.484 - toRun = ex;
87.485 - } finally {
87.486 - exitStorage();
87.487 - }
87.488 -
87.489 - toRun.recover(this);
87.490 -
87.491 - // and try again
87.492 - }
87.493 - }
87.494 -
87.495 - /** Notifies listeners.
87.496 - * @param allAffectedResults set of R
87.497 - */
87.498 - static final class NotifyListeners implements Runnable {
87.499 - private final ArrayList<Object> evAndListeners;
87.500 -
87.501 - public NotifyListeners(Set<R> allAffectedResults) {
87.502 - if (allAffectedResults.isEmpty()) {
87.503 - evAndListeners = null;
87.504 - return;
87.505 - }
87.506 -
87.507 - evAndListeners = new ArrayList<Object>();
87.508 - {
87.509 - for (R<?> result : allAffectedResults) {
87.510 - result.collectFires(evAndListeners);
87.511 - }
87.512 - }
87.513 - }
87.514 -
87.515 - public boolean shallRun() {
87.516 - return evAndListeners != null && !evAndListeners.isEmpty();
87.517 - }
87.518 -
87.519 - public void run() {
87.520 - Iterator it = evAndListeners.iterator();
87.521 - while (it.hasNext()) {
87.522 - LookupEvent ev = (LookupEvent)it.next();
87.523 - LookupListener l = (LookupListener)it.next();
87.524 - l.resultChanged(ev);
87.525 - }
87.526 - }
87.527 - }
87.528 -
87.529 - /**
87.530 - * Call resultChanged on all listeners.
87.531 - * @param listeners array of listeners in the format used by
87.532 - * javax.swing.EventListenerList. It means that there are Class
87.533 - * objects on even positions and the listeners on odd positions
87.534 - * @param ev the event to fire
87.535 - */
87.536 - static void notifyListeners(Object[] listeners, LookupEvent ev, Collection<Object> evAndListeners) {
87.537 - for (int i = listeners.length - 1; i >= 0; i--) {
87.538 - if (! (listeners[i] instanceof LookupListener)) {
87.539 - continue;
87.540 - }
87.541 - LookupListener ll = (LookupListener)listeners[i];
87.542 -
87.543 - try {
87.544 - if (evAndListeners != null) {
87.545 - if (ll instanceof WaitableResult) {
87.546 - WaitableResult<?> wr = (WaitableResult<?>)ll;
87.547 - wr.collectFires(evAndListeners);
87.548 - } else {
87.549 - evAndListeners.add(ev);
87.550 - evAndListeners.add(ll);
87.551 - }
87.552 - } else {
87.553 - ll.resultChanged(ev);
87.554 - }
87.555 - } catch (StackOverflowError err) {
87.556 - throw new CycleError(evAndListeners); // NOI18N
87.557 - } catch (RuntimeException e) {
87.558 - // Such as e.g. occurred in #32040. Do not halt other things.
87.559 - e.printStackTrace();
87.560 - }
87.561 - }
87.562 - }
87.563 -
87.564 - private static class CycleError extends StackOverflowError {
87.565 - private final Collection<Object> print;
87.566 - public CycleError(Collection<Object> evAndListeners) {
87.567 - this.print = evAndListeners;
87.568 - }
87.569 -
87.570 - @Override
87.571 - public String getMessage() {
87.572 - StringBuilder sb = new StringBuilder();
87.573 - sb.append("StackOverflowError, here are the listeners:\n"); // NOI18N
87.574 - for (Object o : print) {
87.575 - sb.append('\n').append(o);
87.576 - if (sb.length() > 10000) {
87.577 - break;
87.578 - }
87.579 - }
87.580 - return sb.toString();
87.581 - }
87.582 - } // end of CycleError
87.583 -
87.584 - /** A method that defines matching between Item and Template.
87.585 - * @param t template providing the criteria
87.586 - * @param item the item to match
87.587 - * @param deepCheck true if type of the pair should be tested, false if it is already has been tested
87.588 - * @return true if item matches the template requirements, false if not
87.589 - */
87.590 - static boolean matches(Template<?> t, Pair<?> item, boolean deepCheck) {
87.591 - String id = t.getId();
87.592 -
87.593 - if (id != null && !id.equals(item.getId())) {
87.594 - return false;
87.595 - }
87.596 -
87.597 - Object instance = t.getInstance();
87.598 -
87.599 - if ((instance != null) && !item.creatorOf(instance)) {
87.600 - return false;
87.601 - }
87.602 -
87.603 - if (deepCheck) {
87.604 - return item.instanceOf(t.getType());
87.605 - } else {
87.606 - return true;
87.607 - }
87.608 - }
87.609 -
87.610 - /**
87.611 - * Compares the array elements for equality.
87.612 - * @return true if all elements in the arrays are equal
87.613 - * (by calling equals(Object x) method)
87.614 - */
87.615 - private static boolean compareArrays(Object[] a, Object[] b) {
87.616 - // handle null values
87.617 - if (a == null) {
87.618 - return (b == null);
87.619 - } else {
87.620 - if (b == null) {
87.621 - return false;
87.622 - }
87.623 - }
87.624 -
87.625 - if (a.length != b.length) {
87.626 - return false;
87.627 - }
87.628 -
87.629 - for (int i = 0; i < a.length; i++) {
87.630 - // handle null values for individual elements
87.631 - if (a[i] == null) {
87.632 - if (b[i] != null) {
87.633 - return false;
87.634 - }
87.635 -
87.636 - // both are null --> ok, take next
87.637 - continue;
87.638 - } else {
87.639 - if (b[i] == null) {
87.640 - return false;
87.641 - }
87.642 - }
87.643 -
87.644 - // perform the comparison
87.645 - if (!a[i].equals(b[i])) {
87.646 - return false;
87.647 - }
87.648 - }
87.649 -
87.650 - return true;
87.651 - }
87.652 -
87.653 - /** Method to be called when a result is cleared to signal that the list
87.654 - * of all result should be checked for clearing.
87.655 - * @param template the template the result was for
87.656 - * @return true if the hash map with all items has been cleared
87.657 - */
87.658 - <T> boolean cleanUpResult(Lookup.Template<T> template) {
87.659 - AbstractLookup.Storage<?> t = enterStorage();
87.660 -
87.661 - try {
87.662 - return t.cleanUpResult(template) == null;
87.663 - } finally {
87.664 - exitStorage();
87.665 - }
87.666 - }
87.667 -
87.668 - /** Storage check for tests. */
87.669 - static boolean isSimple(AbstractLookup l) {
87.670 - return DelegatingStorage.isSimple((Storage)l.tree);
87.671 - }
87.672 -
87.673 - /** Generic support for listeners, so it can be used in other results
87.674 - * as well.
87.675 - * @param add true to add it, false to modify
87.676 - * @param l listener to modify
87.677 - * @param ref the value of the reference to listener or listener list
87.678 - * @return new value to the reference to listener or list
87.679 - */
87.680 - @SuppressWarnings("unchecked")
87.681 - static Object modifyListenerList(boolean add, LookupListener l, Object ref) {
87.682 - if (add) {
87.683 - if (ref == null) {
87.684 - return l;
87.685 - }
87.686 -
87.687 - if (ref instanceof LookupListener) {
87.688 - ArrayList arr = new ArrayList();
87.689 - arr.add(ref);
87.690 - ref = arr;
87.691 - }
87.692 -
87.693 - ((ArrayList) ref).add(l);
87.694 -
87.695 - return ref;
87.696 - } else {
87.697 - // remove
87.698 - if (ref == null) {
87.699 - return null;
87.700 - }
87.701 -
87.702 - if (ref == l) {
87.703 - return null;
87.704 - }
87.705 -
87.706 - ArrayList arr = (ArrayList) ref;
87.707 - arr.remove(l);
87.708 -
87.709 - if (arr.size() == 1) {
87.710 - return arr.iterator().next();
87.711 - } else {
87.712 - return arr;
87.713 - }
87.714 - }
87.715 - }
87.716 -
87.717 - private static ReferenceQueue<Object> activeQueue() {
87.718 - return ActiveQueue.queue();
87.719 - }
87.720 -
87.721 - /** Storage to keep the internal structure of Pairs and to answer
87.722 - * different queries.
87.723 - */
87.724 - interface Storage<Transaction> {
87.725 - /** Initializes a modification operation by creating an object
87.726 - * that will be passsed to all add, remove, retainAll methods
87.727 - * and should collect enough information about the change to
87.728 - * notify listeners about the transaction later
87.729 - *
87.730 - * @param ensure the amount of items that will appear in the storage
87.731 - * after the modifications (-1 == remove one, -2 == add one, >= 0
87.732 - * the amount of objects at the end
87.733 - * @return a token to identify the transaction
87.734 - */
87.735 - public Transaction beginTransaction(int ensure);
87.736 -
87.737 - /** Collects all affected results R that were modified in the
87.738 - * given transaction.
87.739 - *
87.740 - * @param modified place to add results R to
87.741 - * @param transaction the transaction indentification
87.742 - */
87.743 - public void endTransaction(Transaction transaction, Set<R> modifiedResults);
87.744 -
87.745 - /** Adds an item into the storage.
87.746 - * @param item to add
87.747 - * @param transaction transaction token
87.748 - * @return true if the Item has been added for the first time or false if some other
87.749 - * item equal to this one already existed in the lookup
87.750 - */
87.751 - public boolean add(AbstractLookup.Pair<?> item, Transaction transaction);
87.752 -
87.753 - /** Removes an item.
87.754 - */
87.755 - public void remove(AbstractLookup.Pair item, Transaction transaction);
87.756 -
87.757 - /** Removes all items that are not present in the provided collection.
87.758 - * @param retain collection of Pairs to keep them in
87.759 - * @param transaction the transaction context
87.760 - */
87.761 - public void retainAll(Map retain, Transaction transaction);
87.762 -
87.763 - /** Queries for instances of given class.
87.764 - * @param clazz the class to check
87.765 - * @return enumeration of Item
87.766 - * @see #unsorted
87.767 - */
87.768 - public <T> Enumeration<Pair<T>> lookup(Class<T> clazz);
87.769 -
87.770 - /** Registers another reference to a result with the storage. This method
87.771 - * has also a special meaning.
87.772 - *
87.773 - * @param newRef the new reference to remember
87.774 - * @return the previous reference that was kept (null if newRef is the first one)
87.775 - * the applications is expected to link from newRef to this returned
87.776 - * value to form a linked list
87.777 - */
87.778 - public ReferenceToResult<?> registerReferenceToResult(ReferenceToResult<?> newRef);
87.779 -
87.780 - /** Given the provided template, Do cleanup the results.
87.781 - * @param templ template of a result(s) that should be checked
87.782 - * @return null if all references for this template were cleared or one of them
87.783 - */
87.784 - public ReferenceToResult<?> cleanUpResult(Lookup.Template<?> templ);
87.785 - }
87.786 -
87.787 - /** Extension to the default lookup item that offers additional information
87.788 - * for the data structures use in AbstractLookup
87.789 - */
87.790 - public static abstract class Pair<T> extends Lookup.Item<T> implements Serializable {
87.791 - private static final long serialVersionUID = 1L;
87.792 -
87.793 - /** possition of this item in the lookup, manipulated in addPair, removePair, setPairs methods */
87.794 - private int index = -1;
87.795 -
87.796 - /** For use by subclasses. */
87.797 - protected Pair() {
87.798 - }
87.799 -
87.800 - final int getIndex() {
87.801 - return index;
87.802 - }
87.803 -
87.804 - final void setIndex(AbstractLookup.Storage<?> tree, int x) {
87.805 - if (tree == null) {
87.806 - this.index = x;
87.807 -
87.808 - return;
87.809 - }
87.810 -
87.811 - if (this.index == -1) {
87.812 - this.index = x;
87.813 - } else {
87.814 - throw new IllegalStateException("You cannot use " + this + " in more than one AbstractLookup. Prev: " + this.index + " new: " + x); // NOI18N
87.815 - }
87.816 - }
87.817 -
87.818 - /** Tests whether this item can produce object
87.819 - * of class c.
87.820 - */
87.821 - protected abstract boolean instanceOf(Class<?> c);
87.822 -
87.823 - /** Method that can test whether an instance of a class has been created
87.824 - * by this item.
87.825 - *
87.826 - * @param obj the instance
87.827 - * @return if the item has already create an instance and it is the same
87.828 - * as obj.
87.829 - */
87.830 - protected abstract boolean creatorOf(Object obj);
87.831 - }
87.832 -
87.833 - /** Result based on one instance returned.
87.834 - */
87.835 - static final class R<T> extends WaitableResult<T> {
87.836 - /** reference our result is attached to (do not modify) */
87.837 - public ReferenceToResult<T> reference;
87.838 -
87.839 - /** listeners on the results or pointer to one listener */
87.840 - private Object listeners;
87.841 -
87.842 - public R() {
87.843 - }
87.844 -
87.845 - /** Checks whether we have simple behaviour of complex.
87.846 - */
87.847 - private boolean isSimple() {
87.848 - Storage s = (Storage) reference.lookup.tree;
87.849 -
87.850 - return DelegatingStorage.isSimple(s);
87.851 - }
87.852 -
87.853 - //
87.854 - // Handling cache management for both cases, no caches
87.855 - // for simple (but mark that we needed them, so refresh can
87.856 - // be done in cloneList) and complex when all 3 types
87.857 - // of result are cached
87.858 - //
87.859 - private Object getFromCache(int indx) {
87.860 - if (isSimple()) {
87.861 - return null;
87.862 - }
87.863 -
87.864 - Object maybeArray = reference.caches;
87.865 -
87.866 - if (maybeArray instanceof Object[]) {
87.867 - return ((Object[]) maybeArray)[indx];
87.868 - }
87.869 -
87.870 - return null;
87.871 - }
87.872 -
87.873 - @SuppressWarnings("unchecked")
87.874 - private Set<Class<? extends T>> getClassesCache() {
87.875 - return (Set<Class<? extends T>>) getFromCache(0);
87.876 - }
87.877 -
87.878 - private void setClassesCache(Set s) {
87.879 - if (isSimple()) {
87.880 - // mark it as being used
87.881 - reference.caches = reference;
87.882 -
87.883 - return;
87.884 - }
87.885 -
87.886 - if (!(reference.caches instanceof Object[])) {
87.887 - reference.caches = new Object[3];
87.888 - }
87.889 -
87.890 - ((Object[]) reference.caches)[0] = s;
87.891 - }
87.892 -
87.893 - @SuppressWarnings("unchecked")
87.894 - private Collection<T> getInstancesCache() {
87.895 - return (Collection<T>) getFromCache(1);
87.896 - }
87.897 -
87.898 - private void setInstancesCache(Collection c) {
87.899 - if (isSimple()) {
87.900 - // mark it as being used
87.901 - reference.caches = reference;
87.902 -
87.903 - return;
87.904 - }
87.905 -
87.906 - if (!(reference.caches instanceof Object[])) {
87.907 - reference.caches = new Object[3];
87.908 - }
87.909 -
87.910 - ((Object[]) reference.caches)[1] = c;
87.911 - }
87.912 -
87.913 - @SuppressWarnings("unchecked")
87.914 - private Pair<T>[] getItemsCache() {
87.915 - return (Pair<T>[]) getFromCache(2);
87.916 - }
87.917 -
87.918 - private void setItemsCache(Collection<?> c) {
87.919 - if (isSimple()) {
87.920 - // mark it as being used
87.921 - reference.caches = reference;
87.922 -
87.923 - return;
87.924 - }
87.925 -
87.926 - if (!(reference.caches instanceof Object[])) {
87.927 - reference.caches = new Object[3];
87.928 - }
87.929 -
87.930 - ((Object[]) reference.caches)[2] = c.toArray(new Pair[0]);
87.931 - }
87.932 -
87.933 - private void clearCaches() {
87.934 - if (reference.caches instanceof Object[]) {
87.935 - reference.caches = new Object[3];
87.936 - }
87.937 - }
87.938 -
87.939 - /** Ok, register listeners to all classes and super classes.
87.940 - */
87.941 - public synchronized void addLookupListener(LookupListener l) {
87.942 - listeners = modifyListenerList(true, l, listeners);
87.943 - }
87.944 -
87.945 - /** Ok, register listeners to all classes and super classes.
87.946 - */
87.947 - public synchronized void removeLookupListener(LookupListener l) {
87.948 - listeners = modifyListenerList(false, l, listeners);
87.949 - }
87.950 -
87.951 - /** Delete all cached values, the template changed.
87.952 - */
87.953 - protected void collectFires(Collection<Object> evAndListeners) {
87.954 - Object[] previousItems = getItemsCache();
87.955 - clearCaches();
87.956 -
87.957 - if (previousItems != null) {
87.958 - Object[] newArray = allItemsWithoutBeforeLookup().toArray();
87.959 -
87.960 - if (compareArrays(previousItems, newArray)) {
87.961 - // do not fire any change if nothing has been changed
87.962 - return;
87.963 - }
87.964 - }
87.965 -
87.966 - LookupListener[] arr;
87.967 -
87.968 - synchronized (this) {
87.969 - if (listeners == null) {
87.970 - return;
87.971 - }
87.972 -
87.973 - if (listeners instanceof LookupListener) {
87.974 - arr = new LookupListener[] { (LookupListener) listeners };
87.975 - } else {
87.976 - ArrayList<?> l = (ArrayList<?>) listeners;
87.977 - arr = l.toArray(new LookupListener[l.size()]);
87.978 - }
87.979 - }
87.980 -
87.981 - final LookupListener[] ll = arr;
87.982 - final LookupEvent ev = new LookupEvent(this);
87.983 - notifyListeners(ll, ev, evAndListeners);
87.984 - }
87.985 -
87.986 - public Collection<T> allInstances() {
87.987 - reference.lookup.beforeLookup(reference.template);
87.988 -
87.989 - Collection<T> s = getInstancesCache();
87.990 -
87.991 - if (s != null) {
87.992 - return s;
87.993 - }
87.994 -
87.995 - Collection<Pair<T>> items = allItemsWithoutBeforeLookup();
87.996 - ArrayList<T> list = new ArrayList<T>(items.size());
87.997 -
87.998 - Iterator<Pair<T>> it = items.iterator();
87.999 -
87.1000 - while (it.hasNext()) {
87.1001 - Pair<T> item = it.next();
87.1002 - T obj = item.getInstance();
87.1003 -
87.1004 - if (reference.template.getType().isInstance(obj)) {
87.1005 - list.add(obj);
87.1006 - }
87.1007 - }
87.1008 -
87.1009 - s = Collections.unmodifiableList(list);
87.1010 - setInstancesCache(s);
87.1011 -
87.1012 - return s;
87.1013 - }
87.1014 -
87.1015 - /** Set of all classes.
87.1016 - *
87.1017 - */
87.1018 - @Override
87.1019 - public Set<Class<? extends T>> allClasses() {
87.1020 - reference.lookup.beforeLookup(reference.template);
87.1021 -
87.1022 - Set<Class<? extends T>> s = getClassesCache();
87.1023 -
87.1024 - if (s != null) {
87.1025 - return s;
87.1026 - }
87.1027 -
87.1028 - s = new HashSet<Class<? extends T>>();
87.1029 -
87.1030 - for (Pair<T> item : allItemsWithoutBeforeLookup()) {
87.1031 - Class<? extends T> clazz = item.getType();
87.1032 -
87.1033 - if (clazz != null) {
87.1034 - s.add(clazz);
87.1035 - }
87.1036 - }
87.1037 -
87.1038 - s = Collections.unmodifiableSet(s);
87.1039 - setClassesCache(s);
87.1040 -
87.1041 - return s;
87.1042 - }
87.1043 -
87.1044 - /** Items are stored directly in the allItems.
87.1045 - */
87.1046 - @Override
87.1047 - public Collection<? extends Item<T>> allItems() {
87.1048 - reference.lookup.beforeLookup(reference.template);
87.1049 -
87.1050 - return allItemsWithoutBeforeLookup();
87.1051 - }
87.1052 -
87.1053 - /** Implements the search for allItems, but without asking for before lookup */
87.1054 - private Collection<Pair<T>> allItemsWithoutBeforeLookup() {
87.1055 - Pair<T>[] c = getItemsCache();
87.1056 -
87.1057 - if (c != null) {
87.1058 - return Collections.unmodifiableList(Arrays.asList(c));
87.1059 - }
87.1060 -
87.1061 - ArrayList<Pair<Object>> saferCheck = null;
87.1062 - AbstractLookup.Storage<?> t = reference.lookup.enterStorage();
87.1063 -
87.1064 - try {
87.1065 - try {
87.1066 - return Collections.unmodifiableCollection(initItems(t));
87.1067 - } catch (AbstractLookup.ISE ex) {
87.1068 - // do less effective evaluation of items outside of the
87.1069 - // locked storage
87.1070 - saferCheck = new ArrayList<Pair<Object>>();
87.1071 -
87.1072 - Enumeration<Pair<Object>> en = t.lookup(null); // get all Pairs
87.1073 -
87.1074 - while (en.hasMoreElements()) {
87.1075 - Pair<Object> i = en.nextElement();
87.1076 - saferCheck.add(i);
87.1077 - }
87.1078 - }
87.1079 - } finally {
87.1080 - reference.lookup.exitStorage();
87.1081 - }
87.1082 - return extractPairs(saferCheck);
87.1083 - }
87.1084 -
87.1085 - @SuppressWarnings("unchecked")
87.1086 - private Collection<Pair<T>> extractPairs(final ArrayList<Pair<Object>> saferCheck) {
87.1087 - TreeSet<Pair<T>> items = new TreeSet<Pair<T>>(ALPairComparator.DEFAULT);
87.1088 - for (Pair<Object> i : saferCheck) {
87.1089 - if (matches(reference.template, i, false)) {
87.1090 - items.add((Pair<T>)i);
87.1091 - }
87.1092 - }
87.1093 - return Collections.unmodifiableCollection(items);
87.1094 - }
87.1095 -
87.1096 - /** Initializes items.
87.1097 - */
87.1098 - private Collection<Pair<T>> initItems(Storage<?> t) {
87.1099 - // manipulation with the tree must be synchronized
87.1100 - Enumeration<Pair<T>> en = t.lookup(reference.template.getType());
87.1101 -
87.1102 - // InheritanceTree is comparator for AbstractLookup.Pairs
87.1103 - TreeSet<Pair<T>> items = new TreeSet<Pair<T>>(ALPairComparator.DEFAULT);
87.1104 -
87.1105 - while (en.hasMoreElements()) {
87.1106 - Pair<T> i = en.nextElement();
87.1107 -
87.1108 - if (matches(reference.template, i, false)) {
87.1109 - items.add(i);
87.1110 - }
87.1111 - }
87.1112 -
87.1113 - // create a correctly sorted copy using the tree as the comparator
87.1114 - setItemsCache(items);
87.1115 -
87.1116 - return items;
87.1117 - }
87.1118 -
87.1119 - /** Used by proxy results to synchronize before lookup.
87.1120 - */
87.1121 - protected void beforeLookup(Lookup.Template t) {
87.1122 - if (t.getType() == reference.template.getType()) {
87.1123 - reference.lookup.beforeLookup(t);
87.1124 - }
87.1125 - }
87.1126 -
87.1127 - /* Do not need to implement it, the default way is ok.
87.1128 - public boolean equals(java.lang.Object obj) {
87.1129 - return obj == this;
87.1130 - }
87.1131 - */
87.1132 - @Override
87.1133 - public String toString() {
87.1134 - return super.toString() + " for " + reference.template;
87.1135 - }
87.1136 - }
87.1137 - // end of R
87.1138 -
87.1139 - /** A class that can be used by the creator of the AbstractLookup to
87.1140 - * control its content. It can be passed to AbstractLookup constructor
87.1141 - * and used to add and remove pairs.
87.1142 - *
87.1143 - * @since 1.25
87.1144 - */
87.1145 - public static class Content extends Object implements Serializable {
87.1146 - private static final long serialVersionUID = 1L;
87.1147 -
87.1148 - // one of them is always null (except attach stage)
87.1149 -
87.1150 - /** abstract lookup we are connected to */
87.1151 - private AbstractLookup al;
87.1152 - private transient Object notifyIn;
87.1153 -
87.1154 - /** Default constructor.
87.1155 - */
87.1156 - public Content() {
87.1157 - this(null);
87.1158 - }
87.1159 -
87.1160 - /** Creates a content associated with an executor to handle dispatch
87.1161 - * of changes.
87.1162 - * @param notifyIn the executor to notify changes in
87.1163 - * @since 7.16
87.1164 - */
87.1165 - public Content(Executor notifyIn) {
87.1166 - this.notifyIn = notifyIn;
87.1167 - }
87.1168 -
87.1169 - /** for testing purposes */
87.1170 - final void attachExecutor(Executor notifyIn) {
87.1171 - this.notifyIn = notifyIn;
87.1172 - }
87.1173 -
87.1174 - /** A lookup attaches to this object.
87.1175 - */
87.1176 - final synchronized void attach(AbstractLookup al) {
87.1177 - if (this.al == null) {
87.1178 - this.al = al;
87.1179 -
87.1180 - ArrayList<Pair> ep = getEarlyPairs();
87.1181 - if (ep != null) {
87.1182 - notifyIn = null;
87.1183 - setPairs(ep);
87.1184 - }
87.1185 - } else {
87.1186 - throw new IllegalStateException(
87.1187 - "Trying to use content for " + al + " but it is already used for " + this.al
87.1188 - ); // NOI18N
87.1189 - }
87.1190 - }
87.1191 -
87.1192 - /** The method to add instance to the lookup with.
87.1193 - * @param pair class/instance pair
87.1194 - */
87.1195 - public final void addPair(Pair<?> pair) {
87.1196 - AbstractLookup a = al;
87.1197 - Executor e = getExecutor();
87.1198 -
87.1199 - if (a != null || e != null) {
87.1200 - a.addPair(pair, e);
87.1201 - } else {
87.1202 - if (notifyIn == null) {
87.1203 - notifyIn = new ArrayList<Pair>(3);
87.1204 - }
87.1205 -
87.1206 - getEarlyPairs().add(pair);
87.1207 - }
87.1208 - }
87.1209 -
87.1210 - /** Remove instance.
87.1211 - * @param pair class/instance pair
87.1212 - */
87.1213 - public final void removePair(Pair<?> pair) {
87.1214 - AbstractLookup a = al;
87.1215 - Executor e = getExecutor();
87.1216 -
87.1217 - if (a != null || e != null) {
87.1218 - a.removePair(pair, e);
87.1219 - } else {
87.1220 - if (notifyIn == null) {
87.1221 - notifyIn = new ArrayList<Pair>(3);
87.1222 - }
87.1223 -
87.1224 - getEarlyPairs().remove(pair);
87.1225 - }
87.1226 - }
87.1227 -
87.1228 - /** Changes all pairs in the lookup to new values.
87.1229 - * @param c the collection of (Pair) objects
87.1230 - */
87.1231 - public final void setPairs(Collection<? extends Pair> c) {
87.1232 - AbstractLookup a = al;
87.1233 - Executor e = getExecutor();
87.1234 -
87.1235 - if (a != null || e != null) {
87.1236 - a.setPairs(c, e);
87.1237 - } else {
87.1238 - notifyIn = new ArrayList<Pair>(c);
87.1239 - }
87.1240 - }
87.1241 -
87.1242 - @SuppressWarnings("unchecked")
87.1243 - private ArrayList<Pair> getEarlyPairs() {
87.1244 - Object o = notifyIn;
87.1245 - return o instanceof ArrayList ? (ArrayList<Pair>)o : null;
87.1246 - }
87.1247 -
87.1248 - private Executor getExecutor() {
87.1249 - Object o = notifyIn;
87.1250 - return o instanceof Executor ? (Executor)o : null;
87.1251 - }
87.1252 - }
87.1253 - // end of Content
87.1254 -
87.1255 - /** Just a holder for index & modified values.
87.1256 - */
87.1257 - final static class Info extends Object {
87.1258 - public int index;
87.1259 - public Object transaction;
87.1260 -
87.1261 - public Info(int i, Object t) {
87.1262 - index = i;
87.1263 - transaction = t;
87.1264 - }
87.1265 - }
87.1266 -
87.1267 - /** Reference to a result R
87.1268 - */
87.1269 - static final class ReferenceToResult<T> extends WeakReference<R<T>> implements Runnable {
87.1270 - /** next refernece in chain, modified only from AbstractLookup or this */
87.1271 - private ReferenceToResult<?> next;
87.1272 -
87.1273 - /** the template for the result */
87.1274 - public final Template<T> template;
87.1275 -
87.1276 - /** the lookup we are attached to */
87.1277 - public final AbstractLookup lookup;
87.1278 -
87.1279 - /** caches for results */
87.1280 - public Object caches;
87.1281 -
87.1282 - /** Creates a weak refernece to a new result R in context of lookup
87.1283 - * for given template
87.1284 - */
87.1285 - private ReferenceToResult(R<T> result, AbstractLookup lookup, Template<T> template) {
87.1286 - super(result, activeQueue());
87.1287 - this.template = template;
87.1288 - this.lookup = lookup;
87.1289 - getResult().reference = this;
87.1290 - }
87.1291 -
87.1292 - /** Returns the result or null
87.1293 - */
87.1294 - R<T> getResult() {
87.1295 - return get();
87.1296 - }
87.1297 -
87.1298 - /** Cleans the reference. Implements Runnable interface, do not call
87.1299 - * directly.
87.1300 - */
87.1301 - public void run() {
87.1302 - lookup.cleanUpResult(this.template);
87.1303 - }
87.1304 -
87.1305 - /** Clones the reference list to given Storage.
87.1306 - * @param storage storage to clone to
87.1307 - */
87.1308 - public void cloneList(AbstractLookup.Storage<?> storage) {
87.1309 - ReferenceIterator it = new ReferenceIterator(this);
87.1310 -
87.1311 - while (it.next()) {
87.1312 - ReferenceToResult<?> current = it.current();
87.1313 - ReferenceToResult<?> newRef = current.cloneRef();
87.1314 - newRef.next = storage.registerReferenceToResult(newRef);
87.1315 - newRef.caches = current.caches;
87.1316 -
87.1317 - if (current.caches == current) {
87.1318 - current.getResult().initItems(storage);
87.1319 - }
87.1320 - }
87.1321 - }
87.1322 -
87.1323 - private ReferenceToResult<T> cloneRef() {
87.1324 - return new ReferenceToResult<T>(getResult(), lookup, template);
87.1325 - }
87.1326 - }
87.1327 - // end of ReferenceToResult
87.1328 -
87.1329 - /** Supporting class to iterate over linked list of ReferenceToResult
87.1330 - * Use:
87.1331 - * <PRE>
87.1332 - * ReferenceIterator it = new ReferenceIterator (this.ref);
87.1333 - * while (it.next ()) {
87.1334 - * it.current (): // do some work
87.1335 - * }
87.1336 - * this.ref = it.first (); // remember the first one
87.1337 - */
87.1338 - static final class ReferenceIterator extends Object {
87.1339 - private ReferenceToResult<?> first;
87.1340 - private ReferenceToResult<?> current;
87.1341 -
87.1342 - /** hard reference to current result, so it is not GCed meanwhile */
87.1343 - private R<?> currentResult;
87.1344 -
87.1345 - /** Initializes the iterator with first reference.
87.1346 - */
87.1347 - public ReferenceIterator(ReferenceToResult<?> first) {
87.1348 - this.first = first;
87.1349 - }
87.1350 -
87.1351 - /** Moves the current to next possition */
87.1352 - public boolean next() {
87.1353 - ReferenceToResult<?> prev;
87.1354 - ReferenceToResult<?> ref;
87.1355 -
87.1356 - if (current == null) {
87.1357 - ref = first;
87.1358 - prev = null;
87.1359 - } else {
87.1360 - prev = current;
87.1361 - ref = current.next;
87.1362 - }
87.1363 -
87.1364 - while (ref != null) {
87.1365 - R<?> result = ref.get();
87.1366 -
87.1367 - if (result == null) {
87.1368 - if (prev == null) {
87.1369 - // move the head
87.1370 - first = ref.next;
87.1371 - } else {
87.1372 - // skip over this reference
87.1373 - prev.next = ref.next;
87.1374 - }
87.1375 -
87.1376 - prev = ref;
87.1377 - ref = ref.next;
87.1378 - } else {
87.1379 - // we have found next item
87.1380 - currentResult = result;
87.1381 - current = ref;
87.1382 -
87.1383 - return true;
87.1384 - }
87.1385 - }
87.1386 -
87.1387 - currentResult = null;
87.1388 - current = null;
87.1389 -
87.1390 - return false;
87.1391 - }
87.1392 -
87.1393 - /** Access to current reference.
87.1394 - */
87.1395 - public ReferenceToResult<?> current() {
87.1396 - return current;
87.1397 - }
87.1398 -
87.1399 - /** Access to reference that is supposed to be the first one.
87.1400 - */
87.1401 - public ReferenceToResult<?> first() {
87.1402 - return first;
87.1403 - }
87.1404 - }
87.1405 -
87.1406 - /** Signals that a lookup is being modified from a lookup query.
87.1407 - *
87.1408 - * @author Jaroslav Tulach
87.1409 - */
87.1410 - static final class ISE extends IllegalStateException {
87.1411 - static final long serialVersionUID = 100L;
87.1412 -
87.1413 - /** list of jobs to execute. */
87.1414 - private java.util.List<Job> jobs;
87.1415 -
87.1416 - /** @param msg message
87.1417 - */
87.1418 - public ISE(String msg) {
87.1419 - super(msg);
87.1420 - }
87.1421 -
87.1422 - /** Registers a job to be executed partially out and partially in
87.1423 - * the lock over storage.
87.1424 - */
87.1425 - public void registerJob(Job job) {
87.1426 - if (jobs == null) {
87.1427 - jobs = new java.util.ArrayList<Job>();
87.1428 - }
87.1429 -
87.1430 - jobs.add(job);
87.1431 - }
87.1432 -
87.1433 - /** Executes the jobs outside, and then inside a locked session.
87.1434 - */
87.1435 - public void recover(AbstractLookup lookup) {
87.1436 - if (jobs == null) {
87.1437 - // no recovery plan, throw itself
87.1438 - throw this;
87.1439 - }
87.1440 -
87.1441 - for (Job j : jobs) {
87.1442 - j.before();
87.1443 - }
87.1444 -
87.1445 - AbstractLookup.Storage s = lookup.enterStorage();
87.1446 -
87.1447 - try {
87.1448 - for (Job j : jobs) {
87.1449 - j.inside();
87.1450 - }
87.1451 - } finally {
87.1452 - lookup.exitStorage();
87.1453 - }
87.1454 - }
87.1455 -
87.1456 - /** A job to be executed partially outside and partially inside
87.1457 - * the storage lock.
87.1458 - */
87.1459 - static interface Job {
87.1460 - public void before();
87.1461 -
87.1462 - public void inside();
87.1463 - }
87.1464 - }
87.1465 - // end of ISE
87.1466 -}
88.1 --- a/openide.util.lookup/src/org/openide/util/lookup/Lookups.java Wed Jan 27 17:46:23 2010 -0500
88.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
88.3 @@ -1,325 +0,0 @@
88.4 -/*
88.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
88.6 - *
88.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
88.8 - *
88.9 - * The contents of this file are subject to the terms of either the GNU
88.10 - * General Public License Version 2 only ("GPL") or the Common
88.11 - * Development and Distribution License("CDDL") (collectively, the
88.12 - * "License"). You may not use this file except in compliance with the
88.13 - * License. You can obtain a copy of the License at
88.14 - * http://www.netbeans.org/cddl-gplv2.html
88.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
88.16 - * specific language governing permissions and limitations under the
88.17 - * License. When distributing the software, include this License Header
88.18 - * Notice in each file and include the License file at
88.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
88.20 - * particular file as subject to the "Classpath" exception as provided
88.21 - * by Sun in the GPL Version 2 section of the License file that
88.22 - * accompanied this code. If applicable, add the following below the
88.23 - * License Header, with the fields enclosed by brackets [] replaced by
88.24 - * your own identifying information:
88.25 - * "Portions Copyrighted [year] [name of copyright owner]"
88.26 - *
88.27 - * Contributor(s):
88.28 - *
88.29 - * The Original Software is NetBeans. The Initial Developer of the Original
88.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2009 Sun
88.31 - * Microsystems, Inc. All Rights Reserved.
88.32 - *
88.33 - * If you wish your version of this file to be governed by only the CDDL
88.34 - * or only the GPL Version 2, indicate your decision by adding
88.35 - * "[Contributor] elects to include this software in this distribution
88.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
88.37 - * single choice of license, a recipient has the option to distribute
88.38 - * your version of this file under either the CDDL, the GPL Version 2 or
88.39 - * to extend the choice of license to its licensees as provided above.
88.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
88.41 - * Version 2 license, then the option applies only if the new code is
88.42 - * made subject to such option by the copyright holder.
88.43 - */
88.44 -
88.45 -package org.openide.util.lookup;
88.46 -
88.47 -import java.lang.ref.Reference;
88.48 -import java.lang.ref.WeakReference;
88.49 -import java.util.Arrays;
88.50 -import java.util.Collections;
88.51 -import java.util.HashMap;
88.52 -import java.util.Map;
88.53 -import org.openide.util.Lookup;
88.54 -import org.openide.util.lookup.implspi.NamedServicesProvider;
88.55 -
88.56 -/**
88.57 - * Static factory methods for creating common lookup implementations.
88.58 - *
88.59 - * @author David Strupl
88.60 - * @since 2.21
88.61 - */
88.62 -public class Lookups {
88.63 -
88.64 - /** static methods only */
88.65 - private Lookups() {}
88.66 -
88.67 - /**
88.68 - * Creates a singleton lookup. It means lookup that contains only
88.69 - * one object specified via the supplied parameter. The lookup will
88.70 - * either return the object or null if the supplied template does
88.71 - * not match the class. If the specified argument is null the method
88.72 - * will end with NullPointerException.
88.73 - * @return Fully initialized lookup object ready to use
88.74 - * @throws NullPointerException if the supplied argument is null
88.75 - * @since 2.21
88.76 - */
88.77 - public static Lookup singleton(Object objectToLookup) {
88.78 - if (objectToLookup == null) {
88.79 - throw new NullPointerException();
88.80 - }
88.81 -
88.82 - return new SingletonLookup(objectToLookup);
88.83 - }
88.84 -
88.85 - /**
88.86 - * Creates a lookup that contains an array of objects specified via the
88.87 - * parameter. The resulting lookup is fixed in the following sense: it
88.88 - * contains only fixed set of objects passed in by the array parameter.
88.89 - * Its contents never changes so registering listeners on such lookup
88.90 - * does not have any observable effect (the listeners are never called).
88.91 - *
88.92 - * @param objectsToLookup list of objects to include
88.93 - * @return Fully initialized lookup object ready to use
88.94 - * @throws NullPointerException if the supplied argument is null
88.95 - * @since 2.21
88.96 - *
88.97 - */
88.98 - public static Lookup fixed(Object... objectsToLookup) {
88.99 - if (objectsToLookup == null) {
88.100 - throw new NullPointerException();
88.101 - }
88.102 -
88.103 - if (objectsToLookup.length == 0) {
88.104 - return Lookup.EMPTY;
88.105 - }
88.106 -
88.107 - if (objectsToLookup.length == 1) {
88.108 - return singleton(objectsToLookup[0]);
88.109 - }
88.110 -
88.111 - return new SimpleLookup(Arrays.asList(objectsToLookup));
88.112 - }
88.113 -
88.114 - /**
88.115 - * Creates a lookup that contains an array of objects specified via the
88.116 - * parameter. The resulting lookup is fixed in the following sense: it
88.117 - * contains only fixed set of objects passed in by the array parameter.
88.118 - * The objects returned from this lookup are converted to real objects
88.119 - * before they are returned by the lookup.
88.120 - * Its contents never changes so registering listeners on such lookup
88.121 - * does not have any observable effect (the listeners are never called).
88.122 - *
88.123 - * @return Fully initialized lookup object ready to use
88.124 - * @throws NullPointerException if the any of the arguments is null
88.125 - * @since 2.21
88.126 - *
88.127 - */
88.128 - public static <T,R> Lookup fixed(T[] keys, InstanceContent.Convertor<? super T,R> convertor) {
88.129 - if (keys == null) {
88.130 - throw new NullPointerException();
88.131 - }
88.132 -
88.133 - if (convertor == null) {
88.134 - throw new NullPointerException();
88.135 - }
88.136 -
88.137 - return new SimpleLookup(Arrays.asList(keys), convertor);
88.138 - }
88.139 -
88.140 - /** Creates a lookup that delegates to another one but that one can change
88.141 - * from time to time. The returned lookup checks every time somebody calls
88.142 - * <code>lookup</code> or <code>lookupItem</code> method whether the
88.143 - * provider still returns the same lookup. If not, it updates state of
88.144 - * all {@link org.openide.util.Lookup.Result}s
88.145 - * that it created (and that still exists).
88.146 - * <P>
88.147 - * The user of this method has to implement its provider's <code>getLookup</code>
88.148 - * method (must be thread safe and fast, will be called often and from any thread)
88.149 - * pass it to this method and use the returned lookup. Whenever the user
88.150 - * changes the return value from the <code>getLookup</code> method and wants
88.151 - * to notify listeners on the lookup about that it should trigger the event
88.152 - * firing, for example by calling <code>lookup.lookup (Object.class)</code>
88.153 - * directly on the lookup returned by this method
88.154 - * that forces a check of the return value of {@link org.openide.util.Lookup.Provider#getLookup}</code>.
88.155 - *
88.156 - * @param provider the provider that returns a lookup to delegate to
88.157 - * @return lookup delegating to the lookup returned by the provider
88.158 - * @since 3.9
88.159 - */
88.160 - public static Lookup proxy(Lookup.Provider provider) {
88.161 - return new SimpleProxyLookup(provider);
88.162 - }
88.163 -
88.164 - /** Returns a lookup that implements the JDK1.3 JAR services mechanism and delegates
88.165 - * to META-INF/services/name.of.class files.
88.166 - * <p>Some extensions to the JAR services specification are implemented:
88.167 - * <ol>
88.168 - * <li>An entry may be followed by a line of the form <code>#position=<i>integer</i></code>
88.169 - * to specify ordering. (Smaller numbers first, entries with unspecified position last.)
88.170 - * <li>A line of the form <code>#-<i>classname</i></code> suppresses an entry registered
88.171 - * in another file, so can be used to supersede one implementation with another.
88.172 - * </ol>
88.173 - * <p>Note: It is not dynamic - so if you need to change the classloader or JARs,
88.174 - * wrap it in a {@link ProxyLookup} and change the delegate when necessary.
88.175 - * Existing instances will be kept if the implementation classes are unchanged,
88.176 - * so there is "stability" in doing this provided some parent loaders are the same
88.177 - * as the previous ones.
88.178 - * @since 3.35
88.179 - * @see ServiceProvider
88.180 - */
88.181 - public static Lookup metaInfServices(ClassLoader classLoader) {
88.182 - return new MetaInfServicesLookup(classLoader, "META-INF/services/"); // NOI18N
88.183 - }
88.184 -
88.185 - /** Returns a lookup that behaves exactly like {@link #metaInfServices(ClassLoader)}
88.186 - * except that it does not read data from <code>META-INF/services/</code>, but instead
88.187 - * from the specified prefix.
88.188 - * @param classLoader class loader to use for loading
88.189 - * @param prefix prefix to prepend to the class name when searching
88.190 - * @since 7.9
88.191 - */
88.192 - public static Lookup metaInfServices(ClassLoader classLoader, String prefix) {
88.193 - return new MetaInfServicesLookup(classLoader, prefix);
88.194 - }
88.195 -
88.196 - /** Creates a <q>named</q> lookup.
88.197 - * It is a lookup identified by a given path.
88.198 - * Two lookups with the same path should have the same content.
88.199 - * <p>It is expected that each <q>named</q> lookup
88.200 - * will contain a superset of what would be created by:
88.201 - * <code>{@linkplain #metaInfServices(ClassLoader,String) metaInfServices}(theRightLoader, "META-INF/namedservices/" + path + "/")</code>
88.202 - *
88.203 - * <p class="nonnormative">Various environments can add their own
88.204 - * extensions to its content. As such
88.205 - * {@link Lookups#forPath(java.lang.String)} can combine lookups
88.206 - * from several sources. In current NetBeans Runtime Container, two lookups are used:
88.207 - * </p>
88.208 - * <ul class="nonnormative">
88.209 - * <li><code>Lookups.metaInfServices("META-INF/namedservices/" + path)</code></li>
88.210 - * <li><code>org.openide.loaders.FolderLookup(path)</code></li>
88.211 - * </ul>
88.212 - * <p class="nonnormative">
88.213 - * Please note that these lookups differ in the way they inspect sub-folders.
88.214 - * The first lookup just returns instances from the given path, ignoring
88.215 - * sub-folders, the second one retrieves instances from the whole sub-tree.
88.216 - * </p>
88.217 - * <p>
88.218 - * Read more about the <a href="@org-openide-util@/org/openide/util/doc-files/api.html#folderlookup">usage of this method</a>.
88.219 - *
88.220 - * @param path the path identifying the lookup, e.g. <code>Projects/Actions</code>
88.221 - * @return lookup associated with this path
88.222 - * @since 7.9
88.223 - */
88.224 - public static Lookup forPath(String path) {
88.225 - if (!path.endsWith("/")) {
88.226 - path = path + "/";
88.227 - }
88.228 - return NamedServicesProvider.forPath(path);
88.229 - }
88.230 -
88.231 - /** Creates a lookup that wraps another one and filters out instances
88.232 - * of specified classes. If you have a lookup and
88.233 - * you want to remove all instances of ActionMap you can use:
88.234 - * <pre>
88.235 - * l = Lookups.exclude(lookup, ActionMap.class);
88.236 - * </pre>
88.237 - * Then anybody who asks for <code>l.lookup(ActionMap.class)</code> or
88.238 - * subclass will get <code>null</code>. Even if the original lookup contains the
88.239 - * value.
88.240 - * To create empty lookup (well, just an example, otherwise use {@link Lookup#EMPTY}) one could use:
88.241 - * <pre>
88.242 - * Lookup.exclude(anyLookup, Object.class);
88.243 - * </pre>
88.244 - * as any instance in any lookup is of type Object and thus would be excluded.
88.245 - * <p>
88.246 - * The complete behavior can be described as <code>classes</code> being
88.247 - * a barrier. For an object not to be excluded, there has to be an inheritance
88.248 - * path between the queried class and the actual class of the instance,
88.249 - * that is not blocked by any of the excluded classes:
88.250 - * <pre>
88.251 - * interface A {}
88.252 - * interface B {}
88.253 - * class C implements A, B {}
88.254 - * Object c = new C();
88.255 - * Lookup l1 = Lookups.singleton(c);
88.256 - * Lookup l2 = Lookups.exclude(l1, A.class);
88.257 - * assertNull("A is directly excluded", l2.lookup(A.class));
88.258 - * assertEquals("Returns C as A.class is not between B and C", c, l2.lookup(B.class));
88.259 - * </pre>
88.260 - * For more info check the
88.261 - * <a href="http://hg.netbeans.org/main-golden/annotate/4883eaeda744/openide.util/test/unit/src/org/openide/util/lookup/ExcludingLookupTest.java">
88.262 - * excluding lookup tests</a> and the discussion in issue
88.263 - * <a href="http://openide.netbeans.org/issues/show_bug.cgi?id=53058">53058</a>.
88.264 - *
88.265 - * @param lookup the original lookup that should be filtered
88.266 - * @param classes array of classes those instances should be excluded
88.267 - * @since 5.4
88.268 - */
88.269 - public static Lookup exclude(Lookup lookup, Class... classes) {
88.270 - return new ExcludingLookup(lookup, classes);
88.271 - }
88.272 -
88.273 - /** Creates <code>Lookup.Item</code> representing the instance passed in.
88.274 - *
88.275 - * @param instance the object for which Lookup.Item should be creted
88.276 - * @param id unique identification of the object, for details see {@link org.openide.util.Lookup.Item#getId},
88.277 - * can be <code>null</code>
88.278 - * @return lookup item representing instance
88.279 - * @since 4.8
88.280 - */
88.281 - public static <T> Lookup.Item<T> lookupItem(T instance, String id) {
88.282 - return new LookupItem<T>(instance, id);
88.283 - }
88.284 -
88.285 - private static class LookupItem<T> extends Lookup.Item<T> {
88.286 - private String id;
88.287 - private T instance;
88.288 -
88.289 - public LookupItem(T instance) {
88.290 - this(instance, null);
88.291 - }
88.292 -
88.293 - public LookupItem(T instance, String id) {
88.294 - this.id = id;
88.295 - this.instance = instance;
88.296 - }
88.297 -
88.298 - public String getDisplayName() {
88.299 - return getId();
88.300 - }
88.301 -
88.302 - public String getId() {
88.303 - return (id == null) ? instance.toString() : id;
88.304 - }
88.305 -
88.306 - public T getInstance() {
88.307 - return instance;
88.308 - }
88.309 -
88.310 - @SuppressWarnings("unchecked")
88.311 - public Class<? extends T> getType() {
88.312 - return (Class<? extends T>)instance.getClass();
88.313 - }
88.314 -
88.315 - public @Override boolean equals(Object object) {
88.316 - if (object instanceof LookupItem) {
88.317 - return instance == ((LookupItem) object).getInstance();
88.318 - }
88.319 -
88.320 - return false;
88.321 - }
88.322 -
88.323 - public @Override int hashCode() {
88.324 - return instance.hashCode();
88.325 - }
88.326 - }
88.327 - // End of LookupItem class
88.328 -}
89.1 --- a/openide.util.lookup/src/org/openide/util/lookup/MetaInfServicesLookup.java Wed Jan 27 17:46:23 2010 -0500
89.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
89.3 @@ -1,576 +0,0 @@
89.4 -/*
89.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
89.6 - *
89.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
89.8 - *
89.9 - * The contents of this file are subject to the terms of either the GNU
89.10 - * General Public License Version 2 only ("GPL") or the Common
89.11 - * Development and Distribution License("CDDL") (collectively, the
89.12 - * "License"). You may not use this file except in compliance with the
89.13 - * License. You can obtain a copy of the License at
89.14 - * http://www.netbeans.org/cddl-gplv2.html
89.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
89.16 - * specific language governing permissions and limitations under the
89.17 - * License. When distributing the software, include this License Header
89.18 - * Notice in each file and include the License file at
89.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
89.20 - * particular file as subject to the "Classpath" exception as provided
89.21 - * by Sun in the GPL Version 2 section of the License file that
89.22 - * accompanied this code. If applicable, add the following below the
89.23 - * License Header, with the fields enclosed by brackets [] replaced by
89.24 - * your own identifying information:
89.25 - * "Portions Copyrighted [year] [name of copyright owner]"
89.26 - *
89.27 - * Contributor(s):
89.28 - *
89.29 - * The Original Software is NetBeans. The Initial Developer of the Original
89.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
89.31 - * Microsystems, Inc. All Rights Reserved.
89.32 - *
89.33 - * If you wish your version of this file to be governed by only the CDDL
89.34 - * or only the GPL Version 2, indicate your decision by adding
89.35 - * "[Contributor] elects to include this software in this distribution
89.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
89.37 - * single choice of license, a recipient has the option to distribute
89.38 - * your version of this file under either the CDDL, the GPL Version 2 or
89.39 - * to extend the choice of license to its licensees as provided above.
89.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
89.41 - * Version 2 license, then the option applies only if the new code is
89.42 - * made subject to such option by the copyright holder.
89.43 - */
89.44 -
89.45 -package org.openide.util.lookup;
89.46 -
89.47 -import java.io.BufferedReader;
89.48 -import java.io.IOException;
89.49 -import java.io.InputStream;
89.50 -import java.io.InputStreamReader;
89.51 -import java.lang.ref.Reference;
89.52 -import java.lang.ref.WeakReference;
89.53 -import java.lang.reflect.Method;
89.54 -import java.net.URL;
89.55 -import java.util.ArrayList;
89.56 -import java.util.Collection;
89.57 -import java.util.Enumeration;
89.58 -import java.util.HashSet;
89.59 -import java.util.LinkedHashSet;
89.60 -import java.util.List;
89.61 -import java.util.Map;
89.62 -import java.util.WeakHashMap;
89.63 -import java.util.concurrent.Executor;
89.64 -import java.util.concurrent.Executors;
89.65 -import java.util.logging.Level;
89.66 -import java.util.logging.Logger;
89.67 -import org.openide.util.Lookup;
89.68 -
89.69 -/**
89.70 - * @author Jaroslav Tulach, Jesse Glick
89.71 - * @see Lookups#metaInfServices(ClassLoader,String)
89.72 - * @see "#14722"
89.73 - */
89.74 -final class MetaInfServicesLookup extends AbstractLookup {
89.75 -
89.76 - private static final Logger LOGGER = Logger.getLogger(MetaInfServicesLookup.class.getName());
89.77 - static final Executor RP;
89.78 - static {
89.79 - Executor res = null;
89.80 - try {
89.81 - Class<?> seek = Class.forName("org.openide.util.RequestProcessor");
89.82 - res = (Executor)seek.newInstance();
89.83 - } catch (Throwable t) {
89.84 - res = Executors.newSingleThreadExecutor();
89.85 - }
89.86 - RP = res;
89.87 - }
89.88 - /*TBD: Inject RequestProcessor somehow
89.89 - new RequestProcessor(MetaInfServicesLookup.class.getName(), 1);
89.90 - */
89.91 - private static int knownInstancesCount;
89.92 - private static final List<Reference<Object>> knownInstances;
89.93 - static {
89.94 - knownInstances = new ArrayList<Reference<Object>>();
89.95 - for (int i = 0; i < 512; i++) {
89.96 - knownInstances.add(null);
89.97 - }
89.98 - }
89.99 -
89.100 - /** A set of all requested classes.
89.101 - * Note that classes that we actually succeeded on can never be removed
89.102 - * from here because we hold a strong reference to the loader.
89.103 - * However we also hold classes which are definitely not loadable by
89.104 - * our loader.
89.105 - */
89.106 - private final Map<Class,Object> classes = new WeakHashMap<Class,Object>();
89.107 -
89.108 - /** class loader to use */
89.109 - private final ClassLoader loader;
89.110 - /** prefix to prepend */
89.111 - private final String prefix;
89.112 -
89.113 - /** Create a lookup reading from a specified classloader.
89.114 - */
89.115 - public MetaInfServicesLookup(ClassLoader loader, String prefix) {
89.116 - this.loader = loader;
89.117 - this.prefix = prefix;
89.118 -
89.119 - LOGGER.log(Level.FINE, "Created: {0}", this);
89.120 - }
89.121 -
89.122 - @Override
89.123 - public String toString() {
89.124 - return "MetaInfServicesLookup[" + loader + "]"; // NOI18N
89.125 - }
89.126 -
89.127 - /* Tries to load appropriate resources from manifest files.
89.128 - */
89.129 - @Override
89.130 - protected final void beforeLookup(Lookup.Template t) {
89.131 - Class c = t.getType();
89.132 -
89.133 - Collection<AbstractLookup.Pair<?>> toAdd = null;
89.134 - synchronized (this) {
89.135 - if (classes.get(c) == null) { // NOI18N
89.136 - toAdd = new ArrayList<Pair<?>>();
89.137 - } else {
89.138 - // ok, nothing needs to be done
89.139 - return;
89.140 - }
89.141 - }
89.142 - if (toAdd != null) {
89.143 - search(c, toAdd);
89.144 - }
89.145 - synchronized (this) {
89.146 - if (classes.put(c, "") == null) { // NOI18N
89.147 - // Added new class, search for it.
89.148 - LinkedHashSet<AbstractLookup.Pair<?>> arr = getPairsAsLHS();
89.149 - arr.addAll(toAdd);
89.150 - setPairs(arr, RP);
89.151 - }
89.152 - }
89.153 - }
89.154 -
89.155 - /** Finds all pairs and adds them to the collection.
89.156 - *
89.157 - * @param clazz class to find
89.158 - * @param result collection to add Pair to
89.159 - */
89.160 - private void search(Class<?> clazz, Collection<AbstractLookup.Pair<?>> result) {
89.161 - if (LOGGER.isLoggable(Level.FINER)) {
89.162 - LOGGER.log(Level.FINER, "Searching for " + clazz.getName() + " in " + clazz.getClassLoader() + " from " + this);
89.163 - }
89.164 -
89.165 - String res = prefix + clazz.getName(); // NOI18N
89.166 - Enumeration<URL> en;
89.167 -
89.168 - try {
89.169 - en = loader.getResources(res);
89.170 - } catch (IOException ioe) {
89.171 - // do not use ErrorManager because we are in the startup code
89.172 - // and ErrorManager might not be ready
89.173 - ioe.printStackTrace();
89.174 -
89.175 - return;
89.176 - }
89.177 -
89.178 - // Do not create multiple instances in case more than one JAR
89.179 - // has the same entry in it (and they load to the same class).
89.180 - // Probably would not happen, assuming JARs only list classes
89.181 - // they own, but just in case...
89.182 - List<Item> foundClasses = new ArrayList<Item>();
89.183 - Collection<Class> removeClasses = new ArrayList<Class>();
89.184 -
89.185 - boolean foundOne = false;
89.186 -
89.187 - while (en.hasMoreElements()) {
89.188 - if (!foundOne) {
89.189 - foundOne = true;
89.190 -
89.191 - // Double-check that in fact we can load the *interface* class.
89.192 - // For example, say class I is defined in two JARs, J1 and J2.
89.193 - // There is also an implementation M1 defined in J1, and another
89.194 - // implementation M2 defined in J2.
89.195 - // Classloaders C1 and C2 are made from J1 and J2.
89.196 - // A MetaInfServicesLookup is made from C1. Then the user asks to
89.197 - // lookup I as loaded from C2. J1 has the services line and lists
89.198 - // M1, and we can in fact make it. However it is not of the desired
89.199 - // type to be looked up. Don't do this check, which could be expensive,
89.200 - // unless we expect to be getting some results, however.
89.201 - Class realMcCoy = null;
89.202 -
89.203 - try {
89.204 - realMcCoy = loader.loadClass(clazz.getName());
89.205 - } catch (ClassNotFoundException cnfe) {
89.206 - // our loader does not know about it, OK
89.207 - }
89.208 -
89.209 - if (realMcCoy != clazz) {
89.210 - // Either the interface class is not available at all in our loader,
89.211 - // or it is not the same version as we expected. Don't provide results.
89.212 - if (LOGGER.isLoggable(Level.WARNING)) {
89.213 - if (realMcCoy != null) {
89.214 - LOGGER.log(Level.WARNING,
89.215 - clazz.getName() + " is not the real McCoy! Actually found it in " +
89.216 - realMcCoy.getClassLoader()
89.217 - ); // NOI18N
89.218 - } else {
89.219 - LOGGER.log(Level.WARNING, clazz.getName() + " could not be found in " + loader); // NOI18N
89.220 - }
89.221 - }
89.222 -
89.223 - return;
89.224 - }
89.225 - }
89.226 -
89.227 - URL url = en.nextElement();
89.228 - Item currentItem = null;
89.229 -
89.230 - try {
89.231 - InputStream is = url.openStream();
89.232 -
89.233 - try {
89.234 - BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); // NOI18N
89.235 -
89.236 - while (true) {
89.237 - String line = reader.readLine();
89.238 -
89.239 - if (line == null) {
89.240 - break;
89.241 - }
89.242 -
89.243 - line = line.trim();
89.244 -
89.245 - // is it position attribute?
89.246 - if (line.startsWith("#position=")) {
89.247 - if (currentItem == null) {
89.248 - LOGGER.log(Level.WARNING, "Found line '{0}' in {1} but there is no item to associate it with", new Object[] {line, url});
89.249 - continue;
89.250 - }
89.251 -
89.252 - try {
89.253 - currentItem.position = Integer.parseInt(line.substring(10));
89.254 - } catch (NumberFormatException e) {
89.255 - // do not use ErrorManager because we are in the startup code
89.256 - // and ErrorManager might not be ready
89.257 - e.printStackTrace();
89.258 - }
89.259 - }
89.260 -
89.261 - if (currentItem != null) {
89.262 - insertItem(currentItem, foundClasses);
89.263 - currentItem = null;
89.264 - }
89.265 -
89.266 - // Ignore blank lines and comments.
89.267 - if (line.length() == 0) {
89.268 - continue;
89.269 - }
89.270 -
89.271 - boolean remove = false;
89.272 -
89.273 - if (line.charAt(0) == '#') {
89.274 - if ((line.length() == 1) || (line.charAt(1) != '-')) {
89.275 - continue;
89.276 - }
89.277 -
89.278 - // line starting with #- is a sign to remove that class from lookup
89.279 - remove = true;
89.280 - line = line.substring(2);
89.281 - }
89.282 -
89.283 - Class inst = null;
89.284 -
89.285 - try {
89.286 - // Most lines are fully-qualified class names.
89.287 - inst = Class.forName(line, false, loader);
89.288 - } catch (ClassNotFoundException cnfe) {
89.289 - if (remove) {
89.290 - // if we are removing somthing and the something
89.291 - // cannot be found it is ok to do nothing
89.292 - continue;
89.293 - } else {
89.294 - // but if we are not removing just rethrow
89.295 - throw cnfe;
89.296 - }
89.297 - }
89.298 -
89.299 - if (!clazz.isAssignableFrom(inst)) {
89.300 - throw new ClassNotFoundException(clazzToString(inst) + " not a subclass of " + clazzToString(clazz)); // NOI18N
89.301 - }
89.302 -
89.303 - if (remove) {
89.304 - removeClasses.add(inst);
89.305 - } else {
89.306 - // create new item here, but do not put it into
89.307 - // foundClasses array yet because following line
89.308 - // might specify its position
89.309 - currentItem = new Item();
89.310 - currentItem.clazz = inst;
89.311 - }
89.312 - }
89.313 -
89.314 - if (currentItem != null) {
89.315 - insertItem(currentItem, foundClasses);
89.316 - currentItem = null;
89.317 - }
89.318 - } finally {
89.319 - is.close();
89.320 - }
89.321 - } catch (ClassNotFoundException ex) {
89.322 - LOGGER.log(Level.WARNING, null, ex);
89.323 - } catch (IOException ex) {
89.324 - LOGGER.log(Level.WARNING, null, ex);
89.325 - }
89.326 - }
89.327 -
89.328 - LOGGER.log(Level.FINER, "Found impls of {0}: {1} and removed: {2} from: {3}", new Object[] {clazz.getName(), foundClasses, removeClasses, this});
89.329 -
89.330 - foundClasses.removeAll(removeClasses);
89.331 -
89.332 - for (Item item : foundClasses) {
89.333 - if (removeClasses.contains(item.clazz)) {
89.334 - continue;
89.335 - }
89.336 -
89.337 - result.add(new P(item.clazz));
89.338 - }
89.339 - }
89.340 - private static String clazzToString(Class clazz) {
89.341 - return clazz.getName() + "@" + clazz.getClassLoader() + ":" + clazz.getProtectionDomain().getCodeSource().getLocation(); // NOI18N
89.342 - }
89.343 -
89.344 - /**
89.345 - * Insert item to the list according to item.position value.
89.346 - */
89.347 - private void insertItem(Item item, List<Item> list) {
89.348 - // no position? -> add it to the end
89.349 - if (item.position == -1) {
89.350 - list.add(item);
89.351 -
89.352 - return;
89.353 - }
89.354 -
89.355 - int index = -1;
89.356 - for (Item i : list) {
89.357 - index++;
89.358 -
89.359 - if (i.position == -1) {
89.360 - list.add(index, item);
89.361 -
89.362 - return;
89.363 - } else {
89.364 - if (i.position > item.position) {
89.365 - list.add(index, item);
89.366 -
89.367 - return;
89.368 - }
89.369 - }
89.370 - }
89.371 -
89.372 - list.add(item);
89.373 - }
89.374 -
89.375 - private static class Item {
89.376 - private Class clazz;
89.377 - private int position = -1;
89.378 - @Override
89.379 - public String toString() {
89.380 - return "MetaInfServicesLookup.Item[" + clazz.getName() + "]"; // NOI18N
89.381 - }
89.382 - }
89.383 -
89.384 - /** Pair that holds name of a class and maybe the instance.
89.385 - */
89.386 - private static final class P extends AbstractLookup.Pair<Object> {
89.387 - /** May be one of three things:
89.388 - * 1. The implementation class which was named in the services file.
89.389 - * 2. An instance of it.
89.390 - * 3. Null, if creation of the instance resulted in an error.
89.391 - */
89.392 - private Object object;
89.393 -
89.394 - public P(Class<?> clazz) {
89.395 - this.object = clazz;
89.396 - }
89.397 -
89.398 - /** Finds the class.
89.399 - */
89.400 - private Class<? extends Object> clazz() {
89.401 - Object o = object;
89.402 -
89.403 - if (o instanceof Class) {
89.404 - return (Class<? extends Object>) o;
89.405 - } else if (o != null) {
89.406 - return o.getClass();
89.407 - } else {
89.408 - // Broken.
89.409 - return Object.class;
89.410 - }
89.411 - }
89.412 -
89.413 - @Override
89.414 - public boolean equals(Object o) {
89.415 - if (o instanceof P) {
89.416 - return ((P) o).clazz().equals(clazz());
89.417 - }
89.418 -
89.419 - return false;
89.420 - }
89.421 -
89.422 - @Override
89.423 - public int hashCode() {
89.424 - return clazz().hashCode();
89.425 - }
89.426 -
89.427 - protected boolean instanceOf(Class<?> c) {
89.428 - return c.isAssignableFrom(clazz());
89.429 - }
89.430 -
89.431 - public Class<?> getType() {
89.432 - return clazz();
89.433 - }
89.434 -
89.435 - public Object getInstance() {
89.436 - Object o = object; // keeping local copy to avoid another
89.437 -
89.438 - // thread to modify it under my hands
89.439 - if (o instanceof Class) {
89.440 - synchronized (o) { // o is Class and we will not create
89.441 - // 2 instances of the same class
89.442 -
89.443 - try {
89.444 - Class<?> c = ((Class) o);
89.445 - o = null;
89.446 -
89.447 - synchronized (knownInstances) { // guards only the static cache
89.448 - int size = knownInstances.size();
89.449 - int index = hashForClass(c, size);
89.450 - for (int i = 0; i < size; i++) {
89.451 - Reference<Object> ref = knownInstances.get(index);
89.452 - Object obj = ref == null ? null : ref.get();
89.453 - if (obj == null) {
89.454 - break;
89.455 - }
89.456 - if (c == obj.getClass()) {
89.457 - o = obj;
89.458 - break;
89.459 - }
89.460 - if (++index == size) {
89.461 - index = 0;
89.462 - }
89.463 - }
89.464 - }
89.465 -
89.466 - if (o == null) {
89.467 - o = createInstance(c);
89.468 -
89.469 - synchronized (knownInstances) { // guards only the static cache
89.470 - hashPut(o);
89.471 -
89.472 - int size = knownInstances.size();
89.473 - if (knownInstancesCount > size * 2 / 3) {
89.474 - LOGGER.log(Level.CONFIG, "Cache of size {0} is 2/3 full. Rehashing.", size);
89.475 - HashSet<Reference<Object>> all = new HashSet<Reference<Object>>();
89.476 - all.addAll(knownInstances);
89.477 - for (int i = 0; i < size; i++) {
89.478 - knownInstances.set(i, null);
89.479 - }
89.480 - for (int i = 0; i < size; i++) {
89.481 - knownInstances.add(null);
89.482 - }
89.483 - knownInstancesCount = 0;
89.484 - for (Reference<Object> r : all) {
89.485 - if (r == null) {
89.486 - continue;
89.487 - }
89.488 - Object instance = r.get();
89.489 - if (instance == null) {
89.490 - continue;
89.491 - }
89.492 - hashPut(instance);
89.493 - }
89.494 - }
89.495 -
89.496 - }
89.497 - }
89.498 -
89.499 - // Do not assign to instance var unless there is a complete synch
89.500 - // block between the newInstance and this line. Otherwise we could
89.501 - // be assigning a half-constructed instance that another thread
89.502 - // could see and return immediately.
89.503 - object = o;
89.504 - } catch (Exception ex) {
89.505 - LOGGER.log(Level.WARNING, "Cannot create " + object, ex);
89.506 - object = null;
89.507 - } catch (LinkageError x) { // #174055 + NoClassDefFoundError
89.508 - LOGGER.log(Level.WARNING, "Cannot create " + object, x);
89.509 - object = null;
89.510 - }
89.511 - }
89.512 - }
89.513 -
89.514 - return object;
89.515 - }
89.516 -
89.517 - public String getDisplayName() {
89.518 - return clazz().getName();
89.519 - }
89.520 -
89.521 - public String getId() {
89.522 - return clazz().getName();
89.523 - }
89.524 -
89.525 - protected boolean creatorOf(Object obj) {
89.526 - return obj == object;
89.527 - }
89.528 - private static int hashForClass(Class<?> c, int size) {
89.529 - return Math.abs(c.hashCode()) % size;
89.530 - }
89.531 -
89.532 - private static void hashPut(Object o) {
89.533 - Class<?> c = o.getClass();
89.534 - int size = knownInstances.size();
89.535 - int index = hashForClass(c, size);
89.536 - for (int i = 0; i < size; i++) {
89.537 - Reference<Object> ref = knownInstances.get(index);
89.538 - Object obj = ref == null ? null : ref.get();
89.539 - if (obj == null) {
89.540 - knownInstances.set(index, new WeakReference<Object>(o));
89.541 - knownInstancesCount++;
89.542 - break;
89.543 - }
89.544 - if (++index == size) {
89.545 - index = 0;
89.546 - }
89.547 - }
89.548 - }
89.549 -
89.550 - private static boolean findSharedClassObjectSkip;
89.551 - private static Method findSharedClassObject;
89.552 - /** Basically does c.newInstance(), however the method is complicated
89.553 - * with a special behaviour for old and almost obsoleted NetBeans
89.554 - * class: SharedClassObject.
89.555 - */
89.556 - private static Object createInstance(Class<?> c) throws InstantiationException, IllegalAccessException {
89.557 - if (!findSharedClassObjectSkip) {
89.558 - try {
89.559 - if (findSharedClassObject == null) {
89.560 - Class<?> sco;
89.561 - try {
89.562 - sco = Class.forName("org.openide.util.SharedClassObject"); // NOI18N
89.563 - } catch (ClassNotFoundException ex) {
89.564 - findSharedClassObjectSkip = true;
89.565 - return c.newInstance();
89.566 - }
89.567 - findSharedClassObject = sco.getMethod("findObject", Class.class, boolean.class);
89.568 - }
89.569 - if (findSharedClassObject.getReturnType().isAssignableFrom(c)) {
89.570 - return findSharedClassObject.invoke(null, c, true);
89.571 - }
89.572 - } catch (Exception problem) {
89.573 - throw (InstantiationException)new InstantiationException(problem.getMessage()).initCause(problem);
89.574 - }
89.575 - }
89.576 - return c.newInstance();
89.577 - }
89.578 - }
89.579 -}
90.1 --- a/openide.util.lookup/src/org/openide/util/lookup/implspi/AbstractServiceProviderProcessor.java Wed Jan 27 17:46:23 2010 -0500
90.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
90.3 @@ -1,307 +0,0 @@
90.4 -/*
90.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
90.6 - *
90.7 - * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
90.8 - *
90.9 - * The contents of this file are subject to the terms of either the GNU
90.10 - * General Public License Version 2 only ("GPL") or the Common
90.11 - * Development and Distribution License("CDDL") (collectively, the
90.12 - * "License"). You may not use this file except in compliance with the
90.13 - * License. You can obtain a copy of the License at
90.14 - * http://www.netbeans.org/cddl-gplv2.html
90.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
90.16 - * specific language governing permissions and limitations under the
90.17 - * License. When distributing the software, include this License Header
90.18 - * Notice in each file and include the License file at
90.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
90.20 - * particular file as subject to the "Classpath" exception as provided
90.21 - * by Sun in the GPL Version 2 section of the License file that
90.22 - * accompanied this code. If applicable, add the following below the
90.23 - * License Header, with the fields enclosed by brackets [] replaced by
90.24 - * your own identifying information:
90.25 - * "Portions Copyrighted [year] [name of copyright owner]"
90.26 - *
90.27 - * If you wish your version of this file to be governed by only the CDDL
90.28 - * or only the GPL Version 2, indicate your decision by adding
90.29 - * "[Contributor] elects to include this software in this distribution
90.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
90.31 - * single choice of license, a recipient has the option to distribute
90.32 - * your version of this file under either the CDDL, the GPL Version 2 or
90.33 - * to extend the choice of license to its licensees as provided above.
90.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
90.35 - * Version 2 license, then the option applies only if the new code is
90.36 - * made subject to such option by the copyright holder.
90.37 - *
90.38 - * Contributor(s):
90.39 - *
90.40 - * Portions Copyrighted 2009 Sun Microsystems, Inc.
90.41 - */
90.42 -
90.43 -package org.openide.util.lookup.implspi;
90.44 -
90.45 -import java.io.BufferedReader;
90.46 -import java.io.FileNotFoundException;
90.47 -import java.io.IOException;
90.48 -import java.io.InputStream;
90.49 -import java.io.InputStreamReader;
90.50 -import java.io.OutputStream;
90.51 -import java.io.OutputStreamWriter;
90.52 -import java.io.PrintWriter;
90.53 -import java.lang.annotation.Annotation;
90.54 -import java.util.ArrayList;
90.55 -import java.util.HashMap;
90.56 -import java.util.List;
90.57 -import java.util.Map;
90.58 -import java.util.Set;
90.59 -import java.util.WeakHashMap;
90.60 -import javax.annotation.processing.AbstractProcessor;
90.61 -import javax.annotation.processing.ProcessingEnvironment;
90.62 -import javax.annotation.processing.RoundEnvironment;
90.63 -import javax.lang.model.element.AnnotationMirror;
90.64 -import javax.lang.model.element.AnnotationValue;
90.65 -import javax.lang.model.element.Element;
90.66 -import javax.lang.model.element.ExecutableElement;
90.67 -import javax.lang.model.element.Modifier;
90.68 -import javax.lang.model.element.TypeElement;
90.69 -import javax.lang.model.type.TypeMirror;
90.70 -import javax.lang.model.util.ElementFilter;
90.71 -import javax.tools.Diagnostic.Kind;
90.72 -import javax.tools.FileObject;
90.73 -import javax.tools.StandardLocation;
90.74 -
90.75 -/**
90.76 - * Infrastructure for generating {@code META-INF/services/*} and
90.77 - * {@code META-INF/namedservices/*} registrations from annotations.
90.78 - * @since 8.1
90.79 - */
90.80 -public abstract class AbstractServiceProviderProcessor extends AbstractProcessor {
90.81 -
90.82 - private final Map<ProcessingEnvironment,Map<String,List<String>>> outputFilesByProcessor = new WeakHashMap<ProcessingEnvironment,Map<String,List<String>>>();
90.83 - private final Map<ProcessingEnvironment,Map<String,List<Element>>> originatingElementsByProcessor = new WeakHashMap<ProcessingEnvironment,Map<String,List<Element>>>();
90.84 - private final Map<TypeElement,Boolean> verifiedClasses = new WeakHashMap<TypeElement,Boolean>();
90.85 -
90.86 - /** Throws IllegalStateException. For access by selected subclasses. */
90.87 - protected AbstractServiceProviderProcessor() {
90.88 - if (getClass().getName().equals("org.netbeans.modules.openide.util.ServiceProviderProcessor")) { // NOI18N
90.89 - // OK subclass
90.90 - return;
90.91 - }
90.92 - if (getClass().getName().equals("org.netbeans.modules.openide.util.URLStreamHandlerRegistrationProcessor")) { // NOI18N
90.93 - // OK subclass
90.94 - return;
90.95 - }
90.96 - throw new IllegalStateException();
90.97 - }
90.98 -
90.99 - public @Override final boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
90.100 - if (roundEnv.errorRaised()) {
90.101 - return false;
90.102 - }
90.103 - if (roundEnv.processingOver()) {
90.104 - writeServices();
90.105 - outputFilesByProcessor.clear();
90.106 - originatingElementsByProcessor.clear();
90.107 - return true;
90.108 - } else {
90.109 - return handleProcess(annotations, roundEnv);
90.110 - }
90.111 - }
90.112 -
90.113 - /**
90.114 - * The regular body of {@link #process}.
90.115 - * Called during regular rounds if there are no outstanding errors.
90.116 - * In the last round, one of the processors will write out generated registrations.
90.117 - * @param annotations as in {@link #process}
90.118 - * @param roundEnv as in {@link #process}
90.119 - * @return as in {@link #process}
90.120 - */
90.121 - protected abstract boolean handleProcess(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv);
90.122 -
90.123 - /**
90.124 - * Register a service.
90.125 - * If the class does not have an appropriate signature, an error will be printed and the registration skipped.
90.126 - * @param clazz the service implementation type
90.127 - * @param annotation the (top-level) annotation registering the service, for diagnostic purposes
90.128 - * @param type the type to which the implementation must be assignable
90.129 - * @param path a path under which to register, or "" if inapplicable
90.130 - * @param position a position at which to register, or {@link Integer#MAX_VALUE} to skip
90.131 - * @param supersedes possibly empty list of implementation to supersede
90.132 - */
90.133 - protected final void register(TypeElement clazz, Class<? extends Annotation> annotation,
90.134 - TypeMirror type, String path, int position, String[] supersedes) {
90.135 - Boolean verify = verifiedClasses.get(clazz);
90.136 - if (verify == null) {
90.137 - verify = verifyServiceProviderSignature(clazz, annotation);
90.138 - verifiedClasses.put(clazz, verify);
90.139 - }
90.140 - if (!verify) {
90.141 - return;
90.142 - }
90.143 - String impl = processingEnv.getElementUtils().getBinaryName(clazz).toString();
90.144 - String xface = processingEnv.getElementUtils().getBinaryName((TypeElement) processingEnv.getTypeUtils().asElement(type)).toString();
90.145 - if (!processingEnv.getTypeUtils().isAssignable(clazz.asType(), type)) {
90.146 - AnnotationMirror ann = findAnnotationMirror(clazz, annotation);
90.147 - processingEnv.getMessager().printMessage(Kind.ERROR, impl + " is not assignable to " + xface,
90.148 - clazz, ann, findAnnotationValue(ann, "service"));
90.149 - return;
90.150 - }
90.151 - processingEnv.getMessager().printMessage(Kind.NOTE,
90.152 - impl + " to be registered as a " + xface + (path.length() > 0 ? " under " + path : ""));
90.153 - String rsrc = (path.length() > 0 ? "META-INF/namedservices/" + path + "/" : "META-INF/services/") + xface;
90.154 - {
90.155 - Map<String,List<Element>> originatingElements = originatingElementsByProcessor.get(processingEnv);
90.156 - if (originatingElements == null) {
90.157 - originatingElements = new HashMap<String,List<Element>>();
90.158 - originatingElementsByProcessor.put(processingEnv, originatingElements);
90.159 - }
90.160 - List<Element> origEls = originatingElements.get(rsrc);
90.161 - if (origEls == null) {
90.162 - origEls = new ArrayList<Element>();
90.163 - originatingElements.put(rsrc, origEls);
90.164 - }
90.165 - origEls.add(clazz);
90.166 - }
90.167 - Map<String,List<String>> outputFiles = outputFilesByProcessor.get(processingEnv);
90.168 - if (outputFiles == null) {
90.169 - outputFiles = new HashMap<String,List<String>>();
90.170 - outputFilesByProcessor.put(processingEnv, outputFiles);
90.171 - }
90.172 - List<String> lines = outputFiles.get(rsrc);
90.173 - if (lines == null) {
90.174 - lines = new ArrayList<String>();
90.175 - try {
90.176 - try {
90.177 - FileObject in = processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, "", rsrc);
90.178 - in.openInputStream().close();
90.179 - processingEnv.getMessager().printMessage(Kind.ERROR,
90.180 - "Cannot generate " + rsrc + " because it already exists in sources: " + in.toUri());
90.181 - return;
90.182 - } catch (NullPointerException ex) {
90.183 - // trying to prevent java.lang.NullPointerException
90.184 - // at com.sun.tools.javac.util.DefaultFileManager.getFileForOutput(DefaultFileManager.java:1078)
90.185 - // at com.sun.tools.javac.util.DefaultFileManager.getFileForOutput(DefaultFileManager.java:1054)
90.186 - // at com.sun.tools.javac.processing.JavacFiler.getResource(JavacFiler.java:434)
90.187 - // at org.netbeans.modules.openide.util.AbstractServiceProviderProcessor.register(AbstractServiceProviderProcessor.java:163)
90.188 - // at org.netbeans.modules.openide.util.ServiceProviderProcessor.register(ServiceProviderProcessor.java:99)
90.189 - } catch (FileNotFoundException x) {
90.190 - // Good.
90.191 - }
90.192 - try {
90.193 - FileObject in = processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", rsrc);
90.194 - InputStream is = in.openInputStream();
90.195 - try {
90.196 - BufferedReader r = new BufferedReader(new InputStreamReader(is, "UTF-8"));
90.197 - String line;
90.198 - while ((line = r.readLine()) != null) {
90.199 - lines.add(line);
90.200 - }
90.201 - } finally {
90.202 - is.close();
90.203 - }
90.204 - } catch (FileNotFoundException x) {
90.205 - // OK, created for the first time
90.206 - }
90.207 - } catch (IOException x) {
90.208 - processingEnv.getMessager().printMessage(Kind.ERROR, x.toString());
90.209 - return;
90.210 - }
90.211 - outputFiles.put(rsrc, lines);
90.212 - }
90.213 - int idx = lines.indexOf(impl);
90.214 - if (idx != -1) {
90.215 - lines.remove(idx);
90.216 - while (lines.size() > idx && lines.get(idx).matches("#position=.+|#-.+")) {
90.217 - lines.remove(idx);
90.218 - }
90.219 - }
90.220 - lines.add(impl);
90.221 - if (position != Integer.MAX_VALUE) {
90.222 - lines.add("#position=" + position);
90.223 - }
90.224 - for (String exclude : supersedes) {
90.225 - lines.add("#-" + exclude);
90.226 - }
90.227 - }
90.228 -
90.229 - /**
90.230 - * @param element a source element
90.231 - * @param annotation a type of annotation
90.232 - * @return the instance of that annotation on the element, or null if not found
90.233 - */
90.234 - private AnnotationMirror findAnnotationMirror(Element element, Class<? extends Annotation> annotation) {
90.235 - for (AnnotationMirror ann : element.getAnnotationMirrors()) {
90.236 - if (processingEnv.getElementUtils().getBinaryName((TypeElement) ann.getAnnotationType().asElement()).
90.237 - contentEquals(annotation.getName())) {
90.238 - return ann;
90.239 - }
90.240 - }
90.241 - return null;
90.242 - }
90.243 -
90.244 - /**
90.245 - * @param annotation an annotation instance (null permitted)
90.246 - * @param name the name of an attribute of that annotation
90.247 - * @return the corresponding value if found
90.248 - */
90.249 - private AnnotationValue findAnnotationValue(AnnotationMirror annotation, String name) {
90.250 - if (annotation != null) {
90.251 - for (Map.Entry<? extends ExecutableElement,? extends AnnotationValue> entry : annotation.getElementValues().entrySet()) {
90.252 - if (entry.getKey().getSimpleName().contentEquals(name)) {
90.253 - return entry.getValue();
90.254 - }
90.255 - }
90.256 - }
90.257 - return null;
90.258 - }
90.259 -
90.260 - private final boolean verifyServiceProviderSignature(TypeElement clazz, Class<? extends Annotation> annotation) {
90.261 - AnnotationMirror ann = findAnnotationMirror(clazz, annotation);
90.262 - if (!clazz.getModifiers().contains(Modifier.PUBLIC)) {
90.263 - processingEnv.getMessager().printMessage(Kind.ERROR, clazz + " must be public", clazz, ann);
90.264 - return false;
90.265 - }
90.266 - if (clazz.getModifiers().contains(Modifier.ABSTRACT)) {
90.267 - processingEnv.getMessager().printMessage(Kind.ERROR, clazz + " must not be abstract", clazz, ann);
90.268 - return false;
90.269 - }
90.270 - {
90.271 - boolean hasDefaultCtor = false;
90.272 - for (ExecutableElement constructor : ElementFilter.constructorsIn(clazz.getEnclosedElements())) {
90.273 - if (constructor.getModifiers().contains(Modifier.PUBLIC) && constructor.getParameters().isEmpty()) {
90.274 - hasDefaultCtor = true;
90.275 - break;
90.276 - }
90.277 - }
90.278 - if (!hasDefaultCtor) {
90.279 - processingEnv.getMessager().printMessage(Kind.ERROR, clazz + " must have a public no-argument constructor", clazz, ann);
90.280 - return false;
90.281 - }
90.282 - }
90.283 - return true;
90.284 - }
90.285 -
90.286 - private void writeServices() {
90.287 - for (Map.Entry<ProcessingEnvironment,Map<String,List<String>>> outputFiles : outputFilesByProcessor.entrySet()) {
90.288 - for (Map.Entry<String, List<String>> entry : outputFiles.getValue().entrySet()) {
90.289 - try {
90.290 - FileObject out = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", entry.getKey(),
90.291 - originatingElementsByProcessor.get(outputFiles.getKey()).get(entry.getKey()).toArray(new Element[0]));
90.292 - OutputStream os = out.openOutputStream();
90.293 - try {
90.294 - PrintWriter w = new PrintWriter(new OutputStreamWriter(os, "UTF-8"));
90.295 - for (String line : entry.getValue()) {
90.296 - w.println(line);
90.297 - }
90.298 - w.flush();
90.299 - w.close();
90.300 - } finally {
90.301 - os.close();
90.302 - }
90.303 - } catch (IOException x) {
90.304 - processingEnv.getMessager().printMessage(Kind.ERROR, "Failed to write to " + entry.getKey() + ": " + x.toString());
90.305 - }
90.306 - }
90.307 - }
90.308 - }
90.309 -
90.310 -}
91.1 --- a/openide.util.lookup/src/org/openide/util/lookup/implspi/ActiveQueue.java Wed Jan 27 17:46:23 2010 -0500
91.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
91.3 @@ -1,120 +0,0 @@
91.4 -package org.openide.util.lookup.implspi;
91.5 -
91.6 -import java.lang.ref.Reference;
91.7 -import java.lang.ref.ReferenceQueue;
91.8 -import java.util.logging.Level;
91.9 -import java.util.logging.Logger;
91.10 -
91.11 -/**
91.12 - * Implementation of the active reference queue.
91.13 - * @since 8.1
91.14 - */
91.15 -public final class ActiveQueue {
91.16 -
91.17 - private ActiveQueue() {}
91.18 -
91.19 - private static final Logger LOGGER = Logger.getLogger(ActiveQueue.class.getName().replace('$', '.'));
91.20 - private static Impl activeReferenceQueue;
91.21 -
91.22 - /**
91.23 - * Gets the active reference queue.
91.24 - * @return the singleton queue
91.25 - */
91.26 - public static synchronized ReferenceQueue<Object> queue() {
91.27 - if (activeReferenceQueue == null) {
91.28 - activeReferenceQueue = new Impl(false);
91.29 - }
91.30 -
91.31 - activeReferenceQueue.ping();
91.32 -
91.33 - return activeReferenceQueue;
91.34 - }
91.35 -
91.36 - private static final class Impl extends ReferenceQueue<Object> implements Runnable {
91.37 -
91.38 - /** number of known outstanding references */
91.39 - private int count;
91.40 - private boolean deprecated;
91.41 -
91.42 - Impl(boolean deprecated) {
91.43 - super();
91.44 - this.deprecated = deprecated;
91.45 - }
91.46 -
91.47 - @Override
91.48 - public Reference<Object> poll() {
91.49 - throw new UnsupportedOperationException();
91.50 - }
91.51 -
91.52 - @Override
91.53 - public Reference<Object> remove(long timeout) throws IllegalArgumentException, InterruptedException {
91.54 - throw new InterruptedException();
91.55 - }
91.56 -
91.57 - @Override
91.58 - public Reference<Object> remove() throws InterruptedException {
91.59 - throw new InterruptedException();
91.60 - }
91.61 -
91.62 - public void run() {
91.63 - while (true) {
91.64 - try {
91.65 - Reference<?> ref = super.remove(0);
91.66 - LOGGER.finer("dequeued reference");
91.67 - if (!(ref instanceof Runnable)) {
91.68 - LOGGER.warning("A reference not implementing runnable has been added to the Utilities.activeReferenceQueue(): " + ref.getClass());
91.69 - continue;
91.70 - }
91.71 - if (deprecated) {
91.72 - LOGGER.warning("Utilities.ACTIVE_REFERENCE_QUEUE has been deprecated for " + ref.getClass() + " use Utilities.activeReferenceQueue");
91.73 - }
91.74 - // do the cleanup
91.75 - try {
91.76 - ((Runnable) ref).run();
91.77 - } catch (ThreadDeath td) {
91.78 - throw td;
91.79 - } catch (Throwable t) {
91.80 - // Should not happen.
91.81 - // If it happens, it is a bug in client code, notify!
91.82 - LOGGER.log(Level.WARNING, null, t);
91.83 - } finally {
91.84 - // to allow GC
91.85 - ref = null;
91.86 - }
91.87 - } catch (InterruptedException ex) {
91.88 - // Can happen during VM shutdown, it seems. Ignore.
91.89 - continue;
91.90 - }
91.91 - synchronized (this) {
91.92 - assert count > 0;
91.93 - count--;
91.94 - if (count == 0) {
91.95 - // We have processed all we have to process (for now at least).
91.96 - // Could be restarted later if ping() called again.
91.97 - // This could also happen in case someone called queue() once and tried
91.98 - // to use it for several references; in that case run() might never be called on
91.99 - // the later ones to be collected. Can't really protect against that situation.
91.100 - // See issue #86625 for details.
91.101 - LOGGER.fine("stopping thread");
91.102 - break;
91.103 - }
91.104 - }
91.105 - }
91.106 - }
91.107 -
91.108 - synchronized void ping() {
91.109 - if (count == 0) {
91.110 - Thread t = new Thread(this, "Active Reference Queue Daemon");
91.111 - t.setPriority(Thread.MIN_PRIORITY);
91.112 - t.setDaemon(true);
91.113 - t.start();
91.114 - LOGGER.fine("starting thread");
91.115 - } else {
91.116 - LOGGER.finer("enqueuing reference");
91.117 - }
91.118 - count++;
91.119 - }
91.120 -
91.121 - }
91.122 -
91.123 -}
92.1 --- a/openide.util.lookup/src/org/openide/util/lookup/implspi/NamedServicesProvider.java Wed Jan 27 17:46:23 2010 -0500
92.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
92.3 @@ -1,137 +0,0 @@
92.4 -/*
92.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
92.6 - *
92.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
92.8 - *
92.9 - * The contents of this file are subject to the terms of either the GNU
92.10 - * General Public License Version 2 only ("GPL") or the Common
92.11 - * Development and Distribution License("CDDL") (collectively, the
92.12 - * "License"). You may not use this file except in compliance with the
92.13 - * License. You can obtain a copy of the License at
92.14 - * http://www.netbeans.org/cddl-gplv2.html
92.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
92.16 - * specific language governing permissions and limitations under the
92.17 - * License. When distributing the software, include this License Header
92.18 - * Notice in each file and include the License file at
92.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
92.20 - * particular file as subject to the "Classpath" exception as provided
92.21 - * by Sun in the GPL Version 2 section of the License file that
92.22 - * accompanied this code. If applicable, add the following below the
92.23 - * License Header, with the fields enclosed by brackets [] replaced by
92.24 - * your own identifying information:
92.25 - * "Portions Copyrighted [year] [name of copyright owner]"
92.26 - *
92.27 - * Contributor(s):
92.28 - *
92.29 - * The Original Software is NetBeans. The Initial Developer of the Original
92.30 - * Software is Sun Microsystems, Inc.
92.31 - *
92.32 - * Portions Copyrighted 2006 Sun Microsystems, Inc.
92.33 - */
92.34 -
92.35 -package org.openide.util.lookup.implspi;
92.36 -
92.37 -import java.lang.ref.Reference;
92.38 -import java.lang.ref.WeakReference;
92.39 -import java.util.Collections;
92.40 -import java.util.HashMap;
92.41 -import java.util.Map;
92.42 -import org.openide.util.Lookup;
92.43 -import org.openide.util.lookup.Lookups;
92.44 -
92.45 -/** Infrastructure provider interface for those who control the overall
92.46 - * registration of services in the system. The first instance of this interface
92.47 - * found in {@link Lookup#getDefault()} is consulted when providing answers
92.48 - * to {@link Lookups#forPath(java.lang.String)} queries. Current implementation
92.49 - * is not ready for multiple instances of this interface (the first one wins)
92.50 - * and also changing the instances during runtime.
92.51 - *
92.52 - * <div class="nonnormative">
92.53 - * The basic implementation of this interface is provided in
92.54 - * <a href="@org-openide-filesystems@/overview-summary.html">Filesystem API</a>
92.55 - * and recognizes the
92.56 - * <a href="@org-openide-util@/org/openide/util/doc-files/api.html#instance-folders">.instance files</a>
92.57 - * registered in XML layers. As such one can rely on
92.58 - * <a href="@org-openide-util@/org/openide/util/doc-files/api.html#instance-folders">.instance files</a>
92.59 - * being recognized in unit tests, if the
92.60 - * <a href="@org-openide-filesystems@/overview-summary.html">Filesystem API</a>
92.61 - * is included.
92.62 - * The implementation
92.63 - * is then refined in
92.64 - * <a href="@org-netbeans-modules-settings@/overview-summary.html">Settings API</a>
92.65 - * to handle also <a href="@org-openide-util@/org/openide/util/doc-files/api.html#settings">.settings files</a>.
92.66 - * Again, including this module in unit tests
92.67 - * ensures
92.68 - * <a href="@org-openide-util@/org/openide/util/doc-files/api.html#settings">.settings files</a>
92.69 - * files are recognized.
92.70 - * </div>
92.71 - *
92.72 - * @author Jaroslav Tulach
92.73 - * @since 8.1
92.74 - */
92.75 -public abstract class NamedServicesProvider {
92.76 - private static final Map<String,Reference<Lookup>> namedServicesProviders = Collections.synchronizedMap(new HashMap<String,Reference<Lookup>>());
92.77 -
92.78 - public static Lookup forPath(String path) {
92.79 -
92.80 - Reference<Lookup> ref = namedServicesProviders.get(path);
92.81 - Lookup lkp = ref == null ? null : ref.get();
92.82 - if (lkp != null) {
92.83 - return lkp;
92.84 - }
92.85 - NamedServicesProvider prov = Lookup.getDefault().lookup(NamedServicesProvider.class);
92.86 - if (prov != null &&
92.87 - /* avoid stack overflow during initialization */
92.88 - !path.startsWith(
92.89 - "URLStreamHandler/"
92.90 - /*URLStreamHandlerRegistrationProcessor.REGISTRATION_PREFIX*/
92.91 - )
92.92 - ) {
92.93 - lkp = prov.create(path);
92.94 - } else {
92.95 - ClassLoader l = Lookup.getDefault().lookup(ClassLoader.class);
92.96 - if (l == null) {
92.97 - l = Thread.currentThread().getContextClassLoader();
92.98 - if (l == null) {
92.99 - l = NamedServicesProvider.class.getClassLoader();
92.100 - }
92.101 - }
92.102 - lkp = Lookups.metaInfServices(l, "META-INF/namedservices/" + path);
92.103 - }
92.104 -
92.105 - namedServicesProviders.put(path, new WeakReference<Lookup>(lkp));
92.106 - return lkp;
92.107 - }
92.108 -
92.109 - /** Throws an exception. Prevents unwanted instantiation of this class
92.110 - * by unknown subclasses.
92.111 - */
92.112 - protected NamedServicesProvider() {
92.113 - if (getClass().getName().equals("org.openide.util.lookup.PathInLookupTest$P")) { // NOI18N
92.114 - // OK for tests
92.115 - return;
92.116 - }
92.117 - if (getClass().getName().equals("org.openide.util.UtilitiesTest$NamedServicesProviderImpl")) { // NOI18N
92.118 - // OK for tests
92.119 - return;
92.120 - }
92.121 - if (getClass().getName().equals("org.netbeans.modules.openide.filesystems.RecognizeInstanceFiles")) { // NOI18N
92.122 - // OK for openide.filesystems
92.123 - return;
92.124 - }
92.125 - if (getClass().getName().equals("org.netbeans.modules.settings.RecognizeInstanceObjects")) { // NOI18N
92.126 - // OK for settings
92.127 - return;
92.128 - }
92.129 - throw new IllegalStateException();
92.130 - }
92.131 -
92.132 - /** Create the lookup for given path. Called as a result of query to
92.133 - * {@link Lookups#forPath(java.lang.String)}.
92.134 - *
92.135 - * @param path the identification of the path
92.136 - * @return the lookup representing objects in this path.
92.137 - */
92.138 - protected abstract Lookup create(String path);
92.139 -
92.140 -}
93.1 --- a/openide.util.lookup/src/org/openide/util/lookup/implspi/package-info.java Wed Jan 27 17:46:23 2010 -0500
93.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
93.3 @@ -1,43 +0,0 @@
93.4 -/*
93.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
93.6 - *
93.7 - * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
93.8 - *
93.9 - * The contents of this file are subject to the terms of either the GNU
93.10 - * General Public License Version 2 only ("GPL") or the Common
93.11 - * Development and Distribution License("CDDL") (collectively, the
93.12 - * "License"). You may not use this file except in compliance with the
93.13 - * License. You can obtain a copy of the License at
93.14 - * http://www.netbeans.org/cddl-gplv2.html
93.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
93.16 - * specific language governing permissions and limitations under the
93.17 - * License. When distributing the software, include this License Header
93.18 - * Notice in each file and include the License file at
93.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
93.20 - * particular file as subject to the "Classpath" exception as provided
93.21 - * by Sun in the GPL Version 2 section of the License file that
93.22 - * accompanied this code. If applicable, add the following below the
93.23 - * License Header, with the fields enclosed by brackets [] replaced by
93.24 - * your own identifying information:
93.25 - * "Portions Copyrighted [year] [name of copyright owner]"
93.26 - *
93.27 - * If you wish your version of this file to be governed by only the CDDL
93.28 - * or only the GPL Version 2, indicate your decision by adding
93.29 - * "[Contributor] elects to include this software in this distribution
93.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
93.31 - * single choice of license, a recipient has the option to distribute
93.32 - * your version of this file under either the CDDL, the GPL Version 2 or
93.33 - * to extend the choice of license to its licensees as provided above.
93.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
93.35 - * Version 2 license, then the option applies only if the new code is
93.36 - * made subject to such option by the copyright holder.
93.37 - *
93.38 - * Contributor(s):
93.39 - *
93.40 - * Portions Copyrighted 2010 Sun Microsystems, Inc.
93.41 - */
93.42 -
93.43 -/**
93.44 - * Interfaces intended to be used within the NetBeans Platform.
93.45 - */
93.46 -package org.openide.util.lookup.implspi;
94.1 --- a/openide.util.lookup/test/unit/src/org/netbeans/modules/openide/util/ActiveQueueTest.java Wed Jan 27 17:46:23 2010 -0500
94.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
94.3 @@ -1,133 +0,0 @@
94.4 -/*
94.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
94.6 - *
94.7 - * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
94.8 - *
94.9 - * The contents of this file are subject to the terms of either the GNU
94.10 - * General Public License Version 2 only ("GPL") or the Common
94.11 - * Development and Distribution License("CDDL") (collectively, the
94.12 - * "License"). You may not use this file except in compliance with the
94.13 - * License. You can obtain a copy of the License at
94.14 - * http://www.netbeans.org/cddl-gplv2.html
94.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
94.16 - * specific language governing permissions and limitations under the
94.17 - * License. When distributing the software, include this License Header
94.18 - * Notice in each file and include the License file at
94.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
94.20 - * particular file as subject to the "Classpath" exception as provided
94.21 - * by Sun in the GPL Version 2 section of the License file that
94.22 - * accompanied this code. If applicable, add the following below the
94.23 - * License Header, with the fields enclosed by brackets [] replaced by
94.24 - * your own identifying information:
94.25 - * "Portions Copyrighted [year] [name of copyright owner]"
94.26 - *
94.27 - * If you wish your version of this file to be governed by only the CDDL
94.28 - * or only the GPL Version 2, indicate your decision by adding
94.29 - * "[Contributor] elects to include this software in this distribution
94.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
94.31 - * single choice of license, a recipient has the option to distribute
94.32 - * your version of this file under either the CDDL, the GPL Version 2 or
94.33 - * to extend the choice of license to its licensees as provided above.
94.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
94.35 - * Version 2 license, then the option applies only if the new code is
94.36 - * made subject to such option by the copyright holder.
94.37 - *
94.38 - * Contributor(s):
94.39 - *
94.40 - * Portions Copyrighted 2009 Sun Microsystems, Inc.
94.41 - */
94.42 -
94.43 -package org.netbeans.modules.openide.util;
94.44 -
94.45 -import java.lang.ref.Reference;
94.46 -import java.lang.ref.ReferenceQueue;
94.47 -import java.lang.ref.WeakReference;
94.48 -import java.net.URL;
94.49 -import java.net.URLClassLoader;
94.50 -import org.netbeans.junit.NbTestCase;
94.51 -import org.openide.util.lookup.implspi.ActiveQueue;
94.52 -
94.53 -/**
94.54 - *
94.55 - * @author Jaroslav Tulach <jtulach@netbeans.org>
94.56 - */
94.57 -public class ActiveQueueTest extends NbTestCase{
94.58 -
94.59 - public ActiveQueueTest(String name) {
94.60 - super(name);
94.61 - }
94.62 -
94.63 - public void testMemoryLeak() throws Exception {
94.64 - final Class<?> u1 = ActiveQueue.class;
94.65 - class L extends URLClassLoader {
94.66 - public L() {
94.67 - super(new URL[] {u1.getProtectionDomain().getCodeSource().getLocation()}, u1.getClassLoader().getParent());
94.68 - }
94.69 - @Override
94.70 - protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
94.71 - if (name.equals(u1.getName()) || name.startsWith(u1.getName() + "$")) {
94.72 - Class c = findLoadedClass(name);
94.73 - if (c == null) {
94.74 - c = findClass(name);
94.75 - }
94.76 - if (resolve) {
94.77 - resolveClass(c);
94.78 - }
94.79 - return c;
94.80 - } else {
94.81 - return super.loadClass(name, resolve);
94.82 - }
94.83 - }
94.84 - }
94.85 - ClassLoader l = new L();
94.86 - Class<?> u2 = l.loadClass(u1.getName());
94.87 - assertEquals(l, u2.getClassLoader());
94.88 - Object obj = new Object();
94.89 - @SuppressWarnings("unchecked")
94.90 - ReferenceQueue<Object> q = (ReferenceQueue<Object>) u2.getMethod("queue").invoke(null);
94.91 - RunnableRef ref = new RunnableRef(obj, q);
94.92 - synchronized (ref) {
94.93 - obj = null;
94.94 - assertGC("Ref should be GC'ed as usual", ref);
94.95 - ref.wait();
94.96 - assertTrue("Run method has been executed", ref.executed);
94.97 - }
94.98 - Reference<?> r = new WeakReference<Object>(u2);
94.99 - q = null;
94.100 - u2 = null;
94.101 - l = null;
94.102 - assertGC("#86625: Utilities.class can also be collected now", r);
94.103 - }
94.104 -
94.105 -
94.106 - private static class RunnableRef extends WeakReference<Object>
94.107 - implements Runnable {
94.108 - public boolean wait;
94.109 - public boolean entered;
94.110 - public boolean executed;
94.111 -
94.112 - public RunnableRef (Object o) {
94.113 - this(o, ActiveQueue.queue());
94.114 - }
94.115 -
94.116 - public RunnableRef(Object o, ReferenceQueue<Object> q) {
94.117 - super(o, q);
94.118 - }
94.119 -
94.120 - public synchronized void run () {
94.121 - entered = true;
94.122 - if (wait) {
94.123 - // notify we are here
94.124 - notify ();
94.125 - try {
94.126 - wait ();
94.127 - } catch (InterruptedException ex) {
94.128 - }
94.129 - }
94.130 - executed = true;
94.131 -
94.132 - notifyAll ();
94.133 - }
94.134 - }
94.135 -
94.136 -}
94.137 \ No newline at end of file
95.1 --- a/openide.util.lookup/test/unit/src/org/openide/util/lookup/AbstractLookupMemoryTest.java Wed Jan 27 17:46:23 2010 -0500
95.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
95.3 @@ -1,160 +0,0 @@
95.4 -/*
95.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
95.6 - *
95.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
95.8 - *
95.9 - * The contents of this file are subject to the terms of either the GNU
95.10 - * General Public License Version 2 only ("GPL") or the Common
95.11 - * Development and Distribution License("CDDL") (collectively, the
95.12 - * "License"). You may not use this file except in compliance with the
95.13 - * License. You can obtain a copy of the License at
95.14 - * http://www.netbeans.org/cddl-gplv2.html
95.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
95.16 - * specific language governing permissions and limitations under the
95.17 - * License. When distributing the software, include this License Header
95.18 - * Notice in each file and include the License file at
95.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
95.20 - * particular file as subject to the "Classpath" exception as provided
95.21 - * by Sun in the GPL Version 2 section of the License file that
95.22 - * accompanied this code. If applicable, add the following below the
95.23 - * License Header, with the fields enclosed by brackets [] replaced by
95.24 - * your own identifying information:
95.25 - * "Portions Copyrighted [year] [name of copyright owner]"
95.26 - *
95.27 - * Contributor(s):
95.28 - *
95.29 - * The Original Software is NetBeans. The Initial Developer of the Original
95.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
95.31 - * Microsystems, Inc. All Rights Reserved.
95.32 - *
95.33 - * If you wish your version of this file to be governed by only the CDDL
95.34 - * or only the GPL Version 2, indicate your decision by adding
95.35 - * "[Contributor] elects to include this software in this distribution
95.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
95.37 - * single choice of license, a recipient has the option to distribute
95.38 - * your version of this file under either the CDDL, the GPL Version 2 or
95.39 - * to extend the choice of license to its licensees as provided above.
95.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
95.41 - * Version 2 license, then the option applies only if the new code is
95.42 - * made subject to such option by the copyright holder.
95.43 - */
95.44 -
95.45 -package org.openide.util.lookup;
95.46 -
95.47 -import java.util.Arrays;
95.48 -import java.util.Collections;
95.49 -import org.netbeans.junit.NbTestCase;
95.50 -import org.netbeans.junit.NbTestSuite;
95.51 -import org.openide.util.Lookup;
95.52 -import org.openide.util.lookup.implspi.ActiveQueue;
95.53 -
95.54 -/** Testing memory consumption of various AbstractLookup aspects.
95.55 - */
95.56 -public class AbstractLookupMemoryTest extends NbTestCase {
95.57 - public AbstractLookupMemoryTest(java.lang.String testName) {
95.58 - super(testName);
95.59 - }
95.60 -
95.61 - public static void main(java.lang.String[] args) {
95.62 - junit.textui.TestRunner.run(new NbTestSuite(AbstractLookupMemoryTest.class));
95.63 - }
95.64 -
95.65 - public void testEmptySize () {
95.66 - AbstractLookup instanceLookup = new AbstractLookup ();
95.67 - assertSize ("Empty lookup should be small", 16, instanceLookup);
95.68 -
95.69 - InstanceContent ic = new InstanceContent ();
95.70 - instanceLookup = new AbstractLookup (ic);
95.71 - assertSize ("Lookup with InstanceContent should be small as well", 16, instanceLookup);
95.72 - }
95.73 -
95.74 - public void testPairSize () {
95.75 - AbstractLookup.Pair pair = new EmptyPair ();
95.76 - assertSize ("Pair occupies only 16 bytes", 16, pair);
95.77 - }
95.78 -
95.79 - public void testPairWithOnePointerSize () {
95.80 - AbstractLookup.Pair pair = new OneItemPair ();
95.81 - assertSize ("Pair occupies only 16 bytes", 16, pair);
95.82 - }
95.83 -
95.84 - public void testLookupWithPairs () {
95.85 - Lookup.Template<Object> t = new Lookup.Template<Object>(Object.class);
95.86 - class L implements org.openide.util.LookupListener {
95.87 - public int cnt;
95.88 - public void resultChanged (org.openide.util.LookupEvent ev) {
95.89 - cnt++;
95.90 - }
95.91 - }
95.92 - L listener = new L ();
95.93 - L listener2 = new L ();
95.94 -
95.95 - EmptyPair[] pairs = {
95.96 - new EmptyPair(),
95.97 - new EmptyPair(),
95.98 - new EmptyPair(),
95.99 - new EmptyPair(),
95.100 - };
95.101 - Object[] ignore = {
95.102 - pairs[0],
95.103 - pairs[1],
95.104 - pairs[2],
95.105 - pairs[3],
95.106 - t,
95.107 - ActiveQueue.queue(),
95.108 - listener,
95.109 - listener2,
95.110 - new Integer (11) // trashhold is shared
95.111 - };
95.112 -
95.113 - AbstractLookup.Content c = new AbstractLookup.Content ();
95.114 - AbstractLookup l = new AbstractLookup (c, (Integer)ignore[ignore.length - 1]);
95.115 -
95.116 - c.addPair ((EmptyPair)ignore[0]);
95.117 - assertSize ("Should be really small (not counting the pair sizes)", Collections.singleton (l), 56, ignore);
95.118 -
95.119 - c.addPair ((EmptyPair)ignore[1]);
95.120 - assertSize ("Is bigger I guess (not counting the pair sizes)", Collections.singleton (l), 56, ignore);
95.121 -
95.122 - c.setPairs(Arrays.asList(pairs).subList(0, 3));
95.123 - assertSize ("Even bigger (not counting the pair sizes)", Collections.singleton (l), 64, ignore);
95.124 -
95.125 - c.setPairs(Arrays.asList(pairs).subList(0, 4));
95.126 - assertSize ("Now not that much(not counting the pair sizes)", Collections.singleton (l), 64, ignore);
95.127 -
95.128 - Lookup.Result res = l.lookup (t);
95.129 -
95.130 - assertSize ("After creating a result", Collections.singleton (l), 120, ignore);
95.131 -
95.132 - res.addLookupListener (listener);
95.133 -
95.134 - assertSize ("And attaching one listener", Collections.singleton (l), 120, ignore);
95.135 -
95.136 - res.addLookupListener (listener2);
95.137 - assertSize ("Second listener makes the situation much worse", Collections.singleton (l), 200, ignore);
95.138 - res.removeLookupListener(listener2);
95.139 - assertSize ("But removing it returns us back to original size", Collections.singleton (l), 120, ignore);
95.140 -
95.141 -
95.142 - assertEquals ("Current for pairs are in", res.allItems ().size (), 4); // also activates the listener
95.143 - assertSize ("and making the listener to work", Collections.singleton (l), 120, ignore);
95.144 -
95.145 - c.removePair ((EmptyPair)ignore[0]);
95.146 - assertEquals ("A changes has been delivered", 1, listener.cnt);
95.147 - }
95.148 -
95.149 - /** Simple pair with no data */
95.150 - private static class EmptyPair extends AbstractLookup.Pair {
95.151 - protected boolean creatorOf(Object obj) { return false; }
95.152 - public String getDisplayName() { return ""; }
95.153 - public String getId() { return ""; }
95.154 - public Object getInstance() { return null; }
95.155 - public Class getType() { return Object.class; }
95.156 - protected boolean instanceOf(Class c) { return c == getType (); }
95.157 - } // end of EmptyPair
95.158 -
95.159 - /** Pair with one item (like InstanceContent.Pair) */
95.160 - private static class OneItemPair extends EmptyPair {
95.161 - private Object pointer;
95.162 - }
95.163 -}
96.1 --- a/openide.util.lookup/test/unit/src/org/openide/util/lookup/PathInLookupTest.java Wed Jan 27 17:46:23 2010 -0500
96.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
96.3 @@ -1,116 +0,0 @@
96.4 -/*
96.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
96.6 - *
96.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
96.8 - *
96.9 - * The contents of this file are subject to the terms of either the GNU
96.10 - * General Public License Version 2 only ("GPL") or the Common
96.11 - * Development and Distribution License("CDDL") (collectively, the
96.12 - * "License"). You may not use this file except in compliance with the
96.13 - * License. You can obtain a copy of the License at
96.14 - * http://www.netbeans.org/cddl-gplv2.html
96.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
96.16 - * specific language governing permissions and limitations under the
96.17 - * License. When distributing the software, include this License Header
96.18 - * Notice in each file and include the License file at
96.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
96.20 - * particular file as subject to the "Classpath" exception as provided
96.21 - * by Sun in the GPL Version 2 section of the License file that
96.22 - * accompanied this code. If applicable, add the following below the
96.23 - * License Header, with the fields enclosed by brackets [] replaced by
96.24 - * your own identifying information:
96.25 - * "Portions Copyrighted [year] [name of copyright owner]"
96.26 - *
96.27 - * Contributor(s):
96.28 - *
96.29 - * The Original Software is NetBeans. The Initial Developer of the Original
96.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
96.31 - * Microsystems, Inc. All Rights Reserved.
96.32 - *
96.33 - * If you wish your version of this file to be governed by only the CDDL
96.34 - * or only the GPL Version 2, indicate your decision by adding
96.35 - * "[Contributor] elects to include this software in this distribution
96.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
96.37 - * single choice of license, a recipient has the option to distribute
96.38 - * your version of this file under either the CDDL, the GPL Version 2 or
96.39 - * to extend the choice of license to its licensees as provided above.
96.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
96.41 - * Version 2 license, then the option applies only if the new code is
96.42 - * made subject to such option by the copyright holder.
96.43 - */
96.44 -
96.45 -package org.openide.util.lookup;
96.46 -
96.47 -import java.lang.reflect.Field;
96.48 -import java.util.logging.Level;
96.49 -import org.netbeans.junit.MockServices;
96.50 -import org.netbeans.junit.NbTestCase;
96.51 -import org.openide.util.Lookup;
96.52 -import org.openide.util.lookup.implspi.NamedServicesProvider;
96.53 -
96.54 -/**
96.55 - * @author Jaroslav Tulach
96.56 - */
96.57 -public class PathInLookupTest extends NbTestCase {
96.58 - public PathInLookupTest(String name) {
96.59 - super(name);
96.60 - }
96.61 -
96.62 - @Override
96.63 - protected Level logLevel() {
96.64 - return Level.FINE;
96.65 - }
96.66 -
96.67 - @Override
96.68 - protected void setUp() throws Exception {
96.69 - Lookup.getDefault();
96.70 - Field f = Lookup.class.getDeclaredField("defaultLookup");
96.71 - f.setAccessible(true);
96.72 - f.set(null, null);
96.73 - System.setProperty("org.openide.util.Lookup.paths", "MyServices:YourServices");
96.74 - MockServices.setServices(P.class);
96.75 - Lookup.getDefault();
96.76 - }
96.77 -
96.78 - public void testInterfaceFoundInMyServices() throws Exception {
96.79 - assertNull("not found", Lookup.getDefault().lookup(Shared.class));
96.80 - Shared v = new Shared();
96.81 - P.ic1.add(v);
96.82 - assertNotNull("found", Lookup.getDefault().lookup(Shared.class));
96.83 - P.ic1.remove(v);
96.84 - assertNull("not found again", Lookup.getDefault().lookup(Shared.class));
96.85 - }
96.86 - public void testInterfaceFoundInMyServices2() throws Exception {
96.87 - assertNull("not found", Lookup.getDefault().lookup(Shared.class));
96.88 - Shared v = new Shared();
96.89 - P.ic2.add(v);
96.90 - assertNotNull("found", Lookup.getDefault().lookup(Shared.class));
96.91 - P.ic2.remove(v);
96.92 - assertNull("not found again", Lookup.getDefault().lookup(Shared.class));
96.93 - }
96.94 -
96.95 - static final class Shared extends Object {}
96.96 -
96.97 - public static final class P extends NamedServicesProvider {
96.98 - static InstanceContent ic1 = new InstanceContent();
96.99 - static InstanceContent ic2 = new InstanceContent();
96.100 - static AbstractLookup[] arr = {
96.101 - new AbstractLookup(ic1), new AbstractLookup(ic2)
96.102 - };
96.103 -
96.104 - public Lookup create(String path) {
96.105 - int indx = -1;
96.106 - if (path.equals("MyServices/")) {
96.107 - indx = 0;
96.108 - }
96.109 - if (path.equals("YourServices/")) {
96.110 - indx = 1;
96.111 - }
96.112 - if (indx == -1) {
96.113 - fail("Unexpected lookup query: " + path);
96.114 - }
96.115 - return arr[indx];
96.116 - }
96.117 - }
96.118 -
96.119 -}
97.1 --- a/openide.util.lookup/test/unit/src/org/openide/util/lookup/ProxyLookupTest.java Wed Jan 27 17:46:23 2010 -0500
97.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
97.3 @@ -1,657 +0,0 @@
97.4 -/*
97.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
97.6 - *
97.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
97.8 - *
97.9 - * The contents of this file are subject to the terms of either the GNU
97.10 - * General Public License Version 2 only ("GPL") or the Common
97.11 - * Development and Distribution License("CDDL") (collectively, the
97.12 - * "License"). You may not use this file except in compliance with the
97.13 - * License. You can obtain a copy of the License at
97.14 - * http://www.netbeans.org/cddl-gplv2.html
97.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
97.16 - * specific language governing permissions and limitations under the
97.17 - * License. When distributing the software, include this License Header
97.18 - * Notice in each file and include the License file at
97.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
97.20 - * particular file as subject to the "Classpath" exception as provided
97.21 - * by Sun in the GPL Version 2 section of the License file that
97.22 - * accompanied this code. If applicable, add the following below the
97.23 - * License Header, with the fields enclosed by brackets [] replaced by
97.24 - * your own identifying information:
97.25 - * "Portions Copyrighted [year] [name of copyright owner]"
97.26 - *
97.27 - * Contributor(s):
97.28 - *
97.29 - * The Original Software is NetBeans. The Initial Developer of the Original
97.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
97.31 - * Microsystems, Inc. All Rights Reserved.
97.32 - *
97.33 - * If you wish your version of this file to be governed by only the CDDL
97.34 - * or only the GPL Version 2, indicate your decision by adding
97.35 - * "[Contributor] elects to include this software in this distribution
97.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
97.37 - * single choice of license, a recipient has the option to distribute
97.38 - * your version of this file under either the CDDL, the GPL Version 2 or
97.39 - * to extend the choice of license to its licensees as provided above.
97.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
97.41 - * Version 2 license, then the option applies only if the new code is
97.42 - * made subject to such option by the copyright holder.
97.43 - */
97.44 -
97.45 -package org.openide.util.lookup;
97.46 -
97.47 -import java.io.Serializable;
97.48 -
97.49 -import java.lang.ref.Reference;
97.50 -import java.lang.ref.WeakReference;
97.51 -import java.util.ArrayList;
97.52 -import java.util.Collection;
97.53 -import java.util.Collections;
97.54 -import java.util.concurrent.Executor;
97.55 -import junit.framework.Test;
97.56 -import org.netbeans.junit.NbTestSuite;
97.57 -import org.openide.util.Lookup;
97.58 -import org.openide.util.Lookup.Result;
97.59 -import org.openide.util.LookupEvent;
97.60 -import org.openide.util.LookupListener;
97.61 -import org.openide.util.lookup.implspi.ActiveQueue;
97.62 -
97.63 -/** Runs all NbLookupTest tests on ProxyLookup and adds few additional.
97.64 - */
97.65 -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
97.66 -public class ProxyLookupTest extends AbstractLookupBaseHid
97.67 -implements AbstractLookupBaseHid.Impl {
97.68 - public ProxyLookupTest(java.lang.String testName) {
97.69 - super(testName, null);
97.70 - }
97.71 -
97.72 - public static Test suite() {
97.73 - return new NbTestSuite (ProxyLookupTest.class);
97.74 -// return new ProxyLookupTest("testDuplicatedLookupArrayIndexWithSetLookupAsInIssue123679");
97.75 - }
97.76 -
97.77 - /** Creates an lookup for given lookup. This class just returns
97.78 - * the object passed in, but subclasses can be different.
97.79 - * @param lookup in lookup
97.80 - * @return a lookup to use
97.81 - */
97.82 - public Lookup createLookup (Lookup lookup) {
97.83 - return new ProxyLookup (new Lookup[] { lookup });
97.84 - }
97.85 -
97.86 - public Lookup createInstancesLookup (InstanceContent ic) {
97.87 - return new AbstractLookup (ic);
97.88 - }
97.89 -
97.90 -
97.91 - public void clearCaches () {
97.92 - }
97.93 -
97.94 -
97.95 - /** Check whether setLookups method does not fire when there is no
97.96 - * change in the lookups.
97.97 - */
97.98 - public void testProxyListener () {
97.99 - ProxyLookup lookup = new ProxyLookup (new Lookup[0]);
97.100 -
97.101 - final Lookup.Template<Object> template = new Lookup.Template<Object>(Object.class);
97.102 - final Object[] IGNORE = {
97.103 - ProxyLookup.ImmutableInternalData.EMPTY,
97.104 - ProxyLookup.ImmutableInternalData.EMPTY_ARR,
97.105 - ActiveQueue.queue(),
97.106 - Collections.emptyMap(),
97.107 - Collections.emptyList(),
97.108 - Collections.emptySet()
97.109 - };
97.110 -
97.111 - assertSize("Pretty small", Collections.singleton(lookup), 16, IGNORE);
97.112 -
97.113 - Lookup.Result<Object> res = lookup.lookup (template);
97.114 -
97.115 - assertSize("Bigger", Collections.singleton(lookup), 216, IGNORE);
97.116 -
97.117 - LL ll = new LL ();
97.118 - res.addLookupListener (ll);
97.119 - Collection allRes = res.allInstances ();
97.120 -
97.121 - lookup.setLookups (new Lookup[0]);
97.122 -
97.123 - if (ll.getCount () != 0) {
97.124 - fail ("Calling setLookups (emptyarray) fired a change");
97.125 - }
97.126 -
97.127 - InstanceContent t = new InstanceContent();
97.128 - Lookup del = new AbstractLookup (t);
97.129 - t.add("Ahoj");
97.130 - lookup.setLookups (new Lookup[] { del });
97.131 -
97.132 - if (ll.getCount () != 1) {
97.133 - fail ("Changing lookups did not generate an event");
97.134 - }
97.135 -
97.136 - lookup.setLookups (new Lookup[] { del });
97.137 -
97.138 - if (ll.getCount () != 0) {
97.139 - fail ("Calling setLookups (thesamearray) fired a change");
97.140 - }
97.141 - }
97.142 -
97.143 - public void testNoListenersProxyListener () {
97.144 - ProxyLookup lookup = new ProxyLookup (new Lookup[0]);
97.145 - class E implements Executor {
97.146 - Runnable r;
97.147 - public void execute(Runnable command) {
97.148 - assertNull("NO previous", r);
97.149 - r = command;
97.150 - }
97.151 - public void perform() {
97.152 - assertNotNull("We shall have a runnable", r);
97.153 - r.run();
97.154 - r = null;
97.155 - }
97.156 - }
97.157 - E executor = new E();
97.158 -
97.159 -
97.160 - final Lookup.Template<Object> template = new Lookup.Template<Object>(Object.class);
97.161 - final Object[] IGNORE = {
97.162 - ProxyLookup.ImmutableInternalData.EMPTY,
97.163 - ProxyLookup.ImmutableInternalData.EMPTY_ARR,
97.164 - ActiveQueue.queue(),
97.165 - Collections.emptyMap(),
97.166 - Collections.emptyList(),
97.167 - Collections.emptySet()
97.168 - };
97.169 -
97.170 - assertSize("Pretty small", Collections.singleton(lookup), 16, IGNORE);
97.171 -
97.172 - Lookup.Result<Object> res = lookup.lookup (template);
97.173 -
97.174 - assertSize("Bigger", Collections.singleton(lookup), 216, IGNORE);
97.175 -
97.176 - LL ll = new LL ();
97.177 - res.addLookupListener (ll);
97.178 - Collection allRes = res.allInstances ();
97.179 -
97.180 - lookup.setLookups (executor, new Lookup[0]);
97.181 - if (ll.getCount () != 0) {
97.182 - fail ("Calling setLookups (emptyarray) fired a change");
97.183 - }
97.184 -
97.185 - InstanceContent t = new InstanceContent();
97.186 - Lookup del = new AbstractLookup (t);
97.187 - t.add("Ahoj");
97.188 - lookup.setLookups (executor, new Lookup[] { del });
97.189 - assertEquals("No change yet", 0, ll.getCount());
97.190 - executor.perform();
97.191 - if (ll.getCount () != 1) {
97.192 - fail ("Changing lookups did not generate an event");
97.193 - }
97.194 -
97.195 - lookup.setLookups (executor, new Lookup[] { del });
97.196 - if (ll.getCount () != 0) {
97.197 - fail ("Calling setLookups (thesamearray) fired a change");
97.198 - }
97.199 - }
97.200 -
97.201 - public void testSetLookups () throws Exception {
97.202 - AbstractLookup a1 = new AbstractLookup (new InstanceContent ());
97.203 - AbstractLookup a2 = new AbstractLookup (new InstanceContent ());
97.204 -
97.205 - InstanceContent i3 = new InstanceContent ();
97.206 - i3.add (i3);
97.207 - AbstractLookup a3 = new AbstractLookup (i3);
97.208 -
97.209 - final ProxyLookup p = new ProxyLookup (new Lookup[] { a1, a2 });
97.210 - final Lookup.Result res1 = p.lookup (new Lookup.Template (Object.class));
97.211 - Collection c1 = res1.allInstances();
97.212 -
97.213 - Lookup.Result res2 = p.lookup (new Lookup.Template (String.class));
97.214 - Collection c2 = res2.allInstances ();
97.215 -
97.216 -
97.217 - assertTrue ("We need two results", res1 != res2);
97.218 -
97.219 - final Object blocked = new Object ();
97.220 -
97.221 - class L extends Object implements LookupListener {
97.222 - public void resultChanged (LookupEvent ev) {
97.223 - try {
97.224 - res1.removeLookupListener(this);
97.225 -
97.226 - // waiting for second thread to start #111#
97.227 - blocked.wait ();
97.228 -
97.229 - } catch (Exception ex) {
97.230 - ex.printStackTrace();
97.231 - fail ("An exception occured ");
97.232 - }
97.233 - }
97.234 - }
97.235 -
97.236 - final L listener1 = new L ();
97.237 - res1.addLookupListener (listener1);
97.238 -
97.239 -
97.240 - Runnable newLookupSetter = new Runnable() {
97.241 - public void run () {
97.242 - synchronized (blocked) {
97.243 - try {
97.244 - p.setLookups (new Lookup[0]);
97.245 - } catch (Exception ex) {
97.246 - ex.printStackTrace();
97.247 - fail ("setLookups failed.");
97.248 - } finally {
97.249 - // starts the main thread #111#
97.250 - blocked.notify ();
97.251 - }
97.252 - }
97.253 - }
97.254 - };
97.255 -
97.256 - synchronized (blocked) {
97.257 - new Thread (newLookupSetter).start ();
97.258 -
97.259 - p.setLookups (new Lookup[] { a1, a2, a3 });
97.260 - }
97.261 - }
97.262 -
97.263 - public void testProxyLookupTemplateCaching(){
97.264 - Lookup lookups[] = new Lookup[1];
97.265 - doProxyLookupTemplateCaching(lookups, false);
97.266 - }
97.267 -
97.268 - public void testProxyLookupTemplateCachingOnSizeTwoArray() {
97.269 - Lookup lookups[] = new Lookup[2];
97.270 - lookups[1] = Lookup.EMPTY;
97.271 - doProxyLookupTemplateCaching(lookups, false);
97.272 - }
97.273 - public void testProxyLookupShallNotAllowModificationOfGetLookups(){
97.274 - Lookup lookups[] = new Lookup[1];
97.275 - doProxyLookupTemplateCaching(lookups, true);
97.276 - }
97.277 -
97.278 - public void testProxyLookupShallNotAllowModificationOfGetLookupsOnSizeTwoArray() {
97.279 - Lookup lookups[] = new Lookup[2];
97.280 - lookups[1] = Lookup.EMPTY;
97.281 - doProxyLookupTemplateCaching(lookups, true);
97.282 - }
97.283 -
97.284 - /** Index 0 of lookups will be modified, the rest is up to the
97.285 - * setup code.
97.286 - */
97.287 - private void doProxyLookupTemplateCaching(Lookup[] lookups, boolean reget) {
97.288 - // Create MyProxyLookup with one lookup containing the String object
97.289 - InstanceContent inst = new InstanceContent();
97.290 - inst.add(new String("Hello World")); //NOI18N
97.291 - lookups[0] = new AbstractLookup(inst);
97.292 - ProxyLookup proxy = new ProxyLookup(lookups);
97.293 - if (reget) {
97.294 - lookups = proxy.getLookups();
97.295 - }
97.296 -
97.297 - // Performing template lookup for String object
97.298 - Lookup.Result result = proxy.lookup(new Lookup.Template(String.class, null, null));
97.299 - int stringTemplateResultSize = result.allInstances().size();
97.300 - assertEquals ("Ensure, there is only one instance of String.class in proxyLookup:", //NOI18N
97.301 - 1, stringTemplateResultSize);
97.302 -
97.303 - // Changing lookup in proxy lookup, now it will contain
97.304 - // StringBuffer Object instead of String
97.305 - InstanceContent ic2 = new InstanceContent();
97.306 - ic2.add(new Integer(1234567890));
97.307 - lookups[0] = new AbstractLookup(ic2);
97.308 - proxy.setLookups(lookups);
97.309 -
97.310 - assertEquals ("the old result is updated", 0, result.allInstances().size());
97.311 -
97.312 - // Instance of String.class should not appear in proxyLookup
97.313 - Lookup.Result r2 = proxy.lookup(new Lookup.Template(String.class, null, null));
97.314 - assertEquals ("Instance of String.class should not appear in proxyLookup:", //NOI18N
97.315 - 0, r2.allInstances().size());
97.316 -
97.317 - Lookup.Result r3 = proxy.lookup(new Lookup.Template(Integer.class, null, null));
97.318 - assertEquals ("There is only one instance of Integer.class in proxyLookup:", //NOI18N
97.319 - 1, r3.allInstances().size());
97.320 - }
97.321 -
97.322 - public void testListeningAndQueryingByTwoListenersInstancesSetLookups() {
97.323 - doListeningAndQueryingByTwoListenersSetLookups(0, 1);
97.324 - }
97.325 - public void testListeningAndQueryingByTwoListenersClassesSetLookups() {
97.326 - doListeningAndQueryingByTwoListenersSetLookups(1, 1);
97.327 - }
97.328 - public void testListeningAndQueryingByTwoListenersItemsSetLookups() {
97.329 - doListeningAndQueryingByTwoListenersSetLookups(2, 1);
97.330 - }
97.331 -
97.332 - public void testListeningAndQueryingByTwoListenersInstancesSetLookups2() {
97.333 - doListeningAndQueryingByTwoListenersSetLookups(0, 2);
97.334 - }
97.335 - public void testListeningAndQueryingByTwoListenersClassesSetLookups2() {
97.336 - doListeningAndQueryingByTwoListenersSetLookups(1, 2);
97.337 - }
97.338 - public void testListeningAndQueryingByTwoListenersItemsSetLookups2() {
97.339 - doListeningAndQueryingByTwoListenersSetLookups(2, 2);
97.340 - }
97.341 - public void testListeningAndQueryingByTwoListenersInstancesSetLookups22() {
97.342 - doListeningAndQueryingByTwoListenersSetLookups(0, 22);
97.343 - }
97.344 - public void testListeningAndQueryingByTwoListenersClassesSetLookups22() {
97.345 - doListeningAndQueryingByTwoListenersSetLookups(1, 22);
97.346 - }
97.347 - public void testListeningAndQueryingByTwoListenersItemsSetLookups22() {
97.348 - doListeningAndQueryingByTwoListenersSetLookups(2, 22);
97.349 - }
97.350 -
97.351 - private void doListeningAndQueryingByTwoListenersSetLookups(final int type, int depth) {
97.352 - ProxyLookup orig = new ProxyLookup();
97.353 - ProxyLookup on = orig;
97.354 -
97.355 - while (--depth > 0) {
97.356 - on = new ProxyLookup(new Lookup[] { on });
97.357 - }
97.358 -
97.359 -
97.360 - final ProxyLookup lookup = on;
97.361 -
97.362 - class L implements LookupListener {
97.363 - Lookup.Result integer = lookup.lookup(new Lookup.Template(Integer.class));
97.364 - Lookup.Result number = lookup.lookup(new Lookup.Template(Number.class));
97.365 - Lookup.Result serial = lookup.lookup(new Lookup.Template(Serializable.class));
97.366 -
97.367 - {
97.368 - integer.addLookupListener(this);
97.369 - number.addLookupListener(this);
97.370 - serial.addLookupListener(this);
97.371 - }
97.372 -
97.373 - int round;
97.374 -
97.375 - public void resultChanged(LookupEvent ev) {
97.376 - Collection c1 = get(type, integer);
97.377 - Collection c2 = get(type, number);
97.378 - Collection c3 = get(type, serial);
97.379 -
97.380 - assertEquals("round " + round + " c1 vs. c2", c1, c2);
97.381 - assertEquals("round " + round + " c1 vs. c3", c1, c3);
97.382 - assertEquals("round " + round + " c2 vs. c3", c2, c3);
97.383 -
97.384 - round++;
97.385 - }
97.386 -
97.387 - private Collection get(int type, Lookup.Result res) {
97.388 - Collection c;
97.389 - switch(type) {
97.390 - case 0: c = res.allInstances(); break;
97.391 - case 1: c = res.allClasses(); break;
97.392 - case 2: c = res.allItems(); break;
97.393 - default: c = null; fail("Type: " + type); break;
97.394 - }
97.395 -
97.396 - assertNotNull(c);
97.397 - return new ArrayList(c);
97.398 - }
97.399 - }
97.400 -
97.401 - L listener = new L();
97.402 - listener.resultChanged(null);
97.403 - ArrayList arr = new ArrayList();
97.404 - for(int i = 0; i < 100; i++) {
97.405 - arr.add(new Integer(i));
97.406 -
97.407 - orig.setLookups(new Lookup[] { Lookups.fixed(arr.toArray()) });
97.408 - }
97.409 -
97.410 - assertEquals("3x100+1 checks", 301, listener.round);
97.411 - }
97.412 -
97.413 - static Object holder;
97.414 -
97.415 - public void testProxyWithLiveResultCanBeCollected() {
97.416 - Lookup layer0 = Lookups.singleton("Hello");
97.417 - Lookup layer1 = new ProxyLookup(new Lookup[] { layer0 });
97.418 - Lookup layer2 = new ProxyLookup(new Lookup[] { layer1 });
97.419 - Lookup.Result result1 = layer1.lookup(new Lookup.Template(String.class));
97.420 -
97.421 - assertEquals("One instance", 1, result1.allInstances().size());
97.422 -
97.423 - // this will create ProxyLookup$R which listens on origResult
97.424 - Lookup.Result result2 = layer2.lookup(new Lookup.Template(String.class));
97.425 -
97.426 - // this line is necessary. W/o actually querying the result,
97.427 - // it will nether compute it nor attach the listener.
97.428 - assertEquals("One instance", 1, result2.allInstances().size());
97.429 -
97.430 - result2.addLookupListener(new LookupListener() {
97.431 - public void resultChanged(LookupEvent ev) {}
97.432 - });
97.433 -
97.434 - Reference ref = new WeakReference(layer2);
97.435 - layer2 = null;
97.436 - result2 = null;
97.437 - try {
97.438 - holder = result1;
97.439 - assertGC ("The proxy lookup not been garbage collected!", ref);
97.440 - } finally {
97.441 - holder = null;
97.442 - }
97.443 - }
97.444 -
97.445 - public void testArrayIndexAsInIssue119292() throws Exception {
97.446 - final ProxyLookup pl = new ProxyLookup();
97.447 - final int[] cnt = { 0 };
97.448 -
97.449 - class L extends Lookup {
97.450 - L[] set;
97.451 - Lookup l;
97.452 -
97.453 - public L(String s) {
97.454 - l = Lookups.singleton(s);
97.455 - }
97.456 -
97.457 - @Override
97.458 - public <T> T lookup(Class<T> clazz) {
97.459 - return l.lookup(clazz);
97.460 - }
97.461 -
97.462 - @Override
97.463 - public <T> Result<T> lookup(Template<T> template) {
97.464 - return l.lookup(template);
97.465 - }
97.466 -
97.467 - @Override
97.468 - @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
97.469 - public boolean equals(Object obj) {
97.470 - if (set != null) {
97.471 - cnt[0]++;
97.472 - pl.setLookups(set);
97.473 - }
97.474 - return super.equals(obj);
97.475 - }
97.476 -
97.477 - @Override
97.478 - public int hashCode() {
97.479 - int hash = 3;
97.480 - return hash;
97.481 - }
97.482 - }
97.483 -
97.484 - Result<String> res = pl.lookupResult(String.class);
97.485 - assertEquals(Collections.EMPTY_LIST, res.allItems());
97.486 -
97.487 - L[] old = { new L("A"), new L("B") };
97.488 - L[] now = { new L("C") };
97.489 -
97.490 - pl.setLookups(old);
97.491 - cnt[0] = 0;
97.492 -
97.493 - old[0].set = new L[0];
97.494 - pl.setLookups(now);
97.495 -
97.496 - assertEquals("No call to equals", 0, cnt[0]);
97.497 -
97.498 - assertEquals("Still assigned to C", Collections.singletonList("C"), res.allInstances());
97.499 - }
97.500 -
97.501 - public void testArrayIndexWithAddRemoveListenerAsInIssue119292() throws Exception {
97.502 - final ProxyLookup pl = new ProxyLookup();
97.503 - final int[] cnt = { 0 };
97.504 -
97.505 - class L extends Lookup {
97.506 - L[] set;
97.507 - Lookup l;
97.508 -
97.509 - public L(String s) {
97.510 - l = Lookups.singleton(s);
97.511 - }
97.512 -
97.513 - @Override
97.514 - public <T> T lookup(Class<T> clazz) {
97.515 - return l.lookup(clazz);
97.516 - }
97.517 -
97.518 - @Override
97.519 - public <T> Result<T> lookup(Template<T> template) {
97.520 - Result<T> r = l.lookup(template);
97.521 - return new R<T>(r);
97.522 - }
97.523 -
97.524 - final class R<T> extends Result<T> {
97.525 - private Result<T> delegate;
97.526 -
97.527 - public R(Result<T> delegate) {
97.528 - this.delegate = delegate;
97.529 - }
97.530 -
97.531 - @Override
97.532 - public void addLookupListener(LookupListener l) {
97.533 - cnt[0]++;
97.534 - if (set != null) {
97.535 - pl.setLookups(set);
97.536 - }
97.537 - delegate.addLookupListener(l);
97.538 - }
97.539 -
97.540 - @Override
97.541 - public void removeLookupListener(LookupListener l) {
97.542 - cnt[0]++;
97.543 - if (set != null) {
97.544 - pl.setLookups(set);
97.545 - }
97.546 - delegate.removeLookupListener(l);
97.547 - }
97.548 -
97.549 - @Override
97.550 - public Collection<? extends T> allInstances() {
97.551 - return delegate.allInstances();
97.552 - }
97.553 - }
97.554 - }
97.555 -
97.556 - Result<String> res = pl.lookupResult(String.class);
97.557 - assertEquals(Collections.EMPTY_LIST, res.allItems());
97.558 -
97.559 - L[] old = { new L("A"), new L("B") };
97.560 - L[] now = { new L("C") };
97.561 -
97.562 - pl.setLookups(old);
97.563 - cnt[0] = 0;
97.564 -
97.565 - old[0].set = new L[0];
97.566 - pl.setLookups(now);
97.567 -
97.568 - if (cnt[0] == 0) {
97.569 - fail("There should be calls to listeners");
97.570 - }
97.571 -
97.572 - assertEquals("C is overriden from removeLookupListener", Collections.emptyList(), res.allInstances());
97.573 - }
97.574 -
97.575 -
97.576 - public void testArrayIndexWithSetLookupAsInIssue123679() throws Exception {
97.577 - final ProxyLookup pl = new ProxyLookup();
97.578 - final int[] cnt = { 0 };
97.579 -
97.580 - class L extends Lookup {
97.581 - L[] set;
97.582 - Lookup l;
97.583 - Collection<? extends Serializable> res;
97.584 -
97.585 - public L(String s) {
97.586 - l = Lookups.singleton(s);
97.587 - }
97.588 -
97.589 - @Override
97.590 - public <T> T lookup(Class<T> clazz) {
97.591 - return l.lookup(clazz);
97.592 - }
97.593 -
97.594 - @Override
97.595 - public <T> Result<T> lookup(Template<T> template) {
97.596 - cnt[0]++;
97.597 - if (set != null) {
97.598 - pl.setLookups(set);
97.599 - res = pl.lookupAll(Serializable.class);
97.600 - }
97.601 - Result<T> r = l.lookup(template);
97.602 - return r;
97.603 - }
97.604 - }
97.605 -
97.606 - L[] now = { new L("A"), new L("B") };
97.607 - L[] old = { new L("C") };
97.608 - pl.setLookups(old);
97.609 - old[0].set = now;
97.610 -
97.611 - Result<String> res = pl.lookupResult(String.class);
97.612 - assertEquals("New items visible", 2, res.allItems().size());
97.613 -
97.614 -
97.615 - pl.setLookups(new L("X"), new L("Y"), new L("Z"));
97.616 - }
97.617 -
97.618 - public void testDuplicatedLookupArrayIndexWithSetLookupAsInIssue123679() throws Exception {
97.619 - final ProxyLookup pl = new ProxyLookup();
97.620 - final int[] cnt = { 0 };
97.621 -
97.622 - class L extends Lookup {
97.623 - L[] set;
97.624 - Lookup l;
97.625 - Collection<? extends Serializable> res;
97.626 -
97.627 - public L(String s) {
97.628 - l = Lookups.singleton(s);
97.629 - }
97.630 -
97.631 - @Override
97.632 - public <T> T lookup(Class<T> clazz) {
97.633 - return l.lookup(clazz);
97.634 - }
97.635 -
97.636 - @Override
97.637 - public <T> Result<T> lookup(Template<T> template) {
97.638 - cnt[0]++;
97.639 - if (set != null) {
97.640 - pl.setLookups(set);
97.641 - res = pl.lookupAll(Serializable.class);
97.642 - }
97.643 - Result<T> r = l.lookup(template);
97.644 - return r;
97.645 - }
97.646 - }
97.647 -
97.648 - L dupl = new L("A");
97.649 - L[] now = { dupl };
97.650 - L[] old = { new L("C") };
97.651 - pl.setLookups(old);
97.652 - old[0].set = now;
97.653 -
97.654 - Result<String> res = pl.lookupResult(String.class);
97.655 - assertEquals("New items visible", 1, res.allItems().size());
97.656 -
97.657 -
97.658 - pl.setLookups(old);
97.659 - }
97.660 -}
98.1 --- a/openide.util/apichanges.xml Wed Jan 27 17:46:23 2010 -0500
98.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
98.3 @@ -1,1492 +0,0 @@
98.4 -<?xml version="1.0" encoding="UTF-8"?>
98.5 -<!--
98.6 -DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
98.7 -
98.8 -Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
98.9 -
98.10 -
98.11 -The contents of this file are subject to the terms of either the GNU
98.12 -General Public License Version 2 only ("GPL") or the Common
98.13 -Development and Distribution License("CDDL") (collectively, the
98.14 -"License"). You may not use this file except in compliance with the
98.15 -License. You can obtain a copy of the License at
98.16 -http://www.netbeans.org/cddl-gplv2.html
98.17 -or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
98.18 -specific language governing permissions and limitations under the
98.19 -License. When distributing the software, include this License Header
98.20 -Notice in each file and include the License file at
98.21 -nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
98.22 -particular file as subject to the "Classpath" exception as provided
98.23 -by Sun in the GPL Version 2 section of the License file that
98.24 -accompanied this code. If applicable, add the following below the
98.25 -License Header, with the fields enclosed by brackets [] replaced by
98.26 -your own identifying information:
98.27 -"Portions Copyrighted [year] [name of copyright owner]"
98.28 -
98.29 -Contributor(s):
98.30 -
98.31 -The Original Software is NetBeans. The Initial Developer of the Original
98.32 -Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
98.33 -Microsystems, Inc. All Rights Reserved.
98.34 -
98.35 -If you wish your version of this file to be governed by only the CDDL
98.36 -or only the GPL Version 2, indicate your decision by adding
98.37 -"[Contributor] elects to include this software in this distribution
98.38 -under the [CDDL or GPL Version 2] license." If you do not indicate a
98.39 -single choice of license, a recipient has the option to distribute
98.40 -your version of this file under either the CDDL, the GPL Version 2 or
98.41 -to extend the choice of license to its licensees as provided above.
98.42 -However, if you add GPL Version 2 code and therefore, elected the GPL
98.43 -Version 2 license, then the option applies only if the new code is
98.44 -made subject to such option by the copyright holder.
98.45 --->
98.46 -<!DOCTYPE apichanges PUBLIC "-//NetBeans//DTD API changes list 1.0//EN" "../nbbuild/javadoctools/apichanges.dtd">
98.47 -<apichanges>
98.48 -<apidefs>
98.49 - <apidef name="util">Utilities API</apidef>
98.50 - <apidef name="xml">XML API</apidef>
98.51 - <apidef name="actions">Actions API</apidef>
98.52 -</apidefs>
98.53 -<changes>
98.54 - <change id="ActionInvoker-ActionPresenterProvider">
98.55 - <api name="actions"/>
98.56 - <summary>Action SPI interfaces added</summary>
98.57 - <version major="8" minor="1"/>
98.58 - <date day="21" month="1" year="2010"/>
98.59 - <author login="jglick"/>
98.60 - <compatibility addition="yes"/>
98.61 - <description>
98.62 - <p>
98.63 - Added some internal SPI interfaces.
98.64 - </p>
98.65 - </description>
98.66 - <class package="org.openide.util.actions" name="ActionInvoker"/>
98.67 - <class package="org.openide.util.actions" name="ActionPresenterProvider"/>
98.68 - <issue number="179289"/>
98.69 - </change>
98.70 - <change id="NbPreferences.Provider">
98.71 - <api name="util"/>
98.72 - <summary><code>NbPreferences.Provider</code> added</summary>
98.73 - <version major="8" minor="1"/>
98.74 - <date day="21" month="1" year="2010"/>
98.75 - <author login="jglick"/>
98.76 - <compatibility addition="yes"/>
98.77 - <description>
98.78 - <p>
98.79 - Added an internal SPI interface.
98.80 - </p>
98.81 - </description>
98.82 - <class package="org.openide.util" name="NbPreferences"/>
98.83 - <issue number="179289"/>
98.84 - </change>
98.85 - <change id="lookup.is.free">
98.86 - <api name="util"/>
98.87 - <summary>Lookup API extracted</summary>
98.88 - <version major="8" minor="0"/>
98.89 - <date day="20" month="12" year="2009"/>
98.90 - <author login="jtulach"/>
98.91 - <compatibility modification="yes">
98.92 - <p>
98.93 - Runtime compatibility remains, compile time compatibility is
98.94 - mostly preserved too. It is however recommended to upgrade
98.95 - dependencies of your modules. Try running
98.96 - <code>ant fix-dependencies</code> in your Ant module.
98.97 - </p>
98.98 - </compatibility>
98.99 - <description>
98.100 - <p>
98.101 - <a href="@org-openide-util-lookup@/org/openide/util/Lookup.html">Lookup</a>
98.102 - and its associated interfaces are now available as a
98.103 - <a href="@org-openide-util-lookup@/overview-summary.html">separate module</a>.
98.104 - </p>
98.105 - </description>
98.106 - <issue number="170056"/>
98.107 - </change>
98.108 - <change id="URLStreamHandlerRegistration">
98.109 - <api name="util"/>
98.110 - <summary>Added <code>@URLStreamHandlerRegistration</code></summary>
98.111 - <version major="7" minor="31"/>
98.112 - <date day="30" month="10" year="2009"/>
98.113 - <author login="jglick"/>
98.114 - <compatibility addition="yes">
98.115 - <p>
98.116 - Modules registering <code>URLStreamHandlerFactory</code>s into
98.117 - global lookup will still work but are advised to switch to this
98.118 - annotation, which is both easier to use and more efficient.
98.119 - </p>
98.120 - </compatibility>
98.121 - <description>
98.122 - <p>
98.123 - Introduced an annotation to register URL protocols.
98.124 - </p>
98.125 - </description>
98.126 - <class package="org.openide.util" name="URLStreamHandlerRegistration"/>
98.127 - <issue number="20838"/>
98.128 - </change>
98.129 - <change id="ImageUtilities.createDisabled">
98.130 - <api name="util"/>
98.131 - <summary><code>ImageUtilities.createDisabledIcon</code> and <code>ImageUtilities.createDisabledImage</code> added.</summary>
98.132 - <version major="7" minor="28"/>
98.133 - <date day="10" month="9" year="2009"/>
98.134 - <author login="t_h"/>
98.135 - <compatibility addition="yes"/>
98.136 - <description>
98.137 - <p>
98.138 - <code>ImageUtilities.createDisabledIcon</code> now can be used
98.139 - to create low color saturation icon for disabled buttons. Also
98.140 - <code>ImageUtilities.createDisabledImage</code> was added.
98.141 - </p>
98.142 - </description>
98.143 - <class package="org.openide.util" name="ImageUtilities"/>
98.144 - <issue number="171400"/>
98.145 - </change>
98.146 - <change id="NbBundle.varargs">
98.147 - <api name="util"/>
98.148 - <summary><code>NbBundle.getMessage</code> can take arbitrarily many format arguments</summary>
98.149 - <version major="7" minor="27"/>
98.150 - <date day="5" month="8" year="2009"/>
98.151 - <author login="jglick"/>
98.152 - <compatibility addition="yes"/>
98.153 - <description>
98.154 - <p>
98.155 - <code>NbBundle.getMessage</code> now has a varargs overload that
98.156 - permits you to specify four or more format arguments without
98.157 - explicitly constructing an array.
98.158 - </p>
98.159 - </description>
98.160 - <class package="org.openide.util" name="NbBundle"/>
98.161 - </change>
98.162 - <change id="EditableProperties">
98.163 - <api name="util"/>
98.164 - <summary>Copied API from <code>project.ant</code> for <code>EditableProperties</code>.</summary>
98.165 - <version major="7" minor="26"/>
98.166 - <date day="29" month="7" year="2009"/>
98.167 - <author login="jglick"/>
98.168 - <compatibility addition="yes"/>
98.169 - <description>
98.170 - <p>
98.171 - <code>EditableProperties</code> now available in Utilities API
98.172 - so it can be used more broadly.
98.173 - </p>
98.174 - </description>
98.175 - <class package="org.openide.util" name="EditableProperties"/>
98.176 - <issue number="66577"/>
98.177 - </change>
98.178 - <change id="LifecycleManager.markForRestart">
98.179 - <api name="util"/>
98.180 - <summary>Added way to request that the platform restart.</summary>
98.181 - <version major="7" minor="25"/>
98.182 - <date day="14" month="7" year="2009"/>
98.183 - <author login="jglick"/>
98.184 - <compatibility addition="yes"/>
98.185 - <description>
98.186 - <p>
98.187 - Can now use <code>LifecycleManager.markForRestart</code> to cause
98.188 - the application to restart after exiting. Formerly needed to
98.189 - create special files in the userdir or use similar tricks.
98.190 - </p>
98.191 - </description>
98.192 - <class package="org.openide" name="LifecycleManager"/>
98.193 - <issue number="168257"/>
98.194 - </change>
98.195 - <change id="enableStackTraces">
98.196 - <api name="util"/>
98.197 - <summary>Added constructor <code>RequestProcessor(String name, int throughput, boolean interruptThread, boolean enableStackTraces)</code></summary>
98.198 - <version major="7" minor="24"/>
98.199 - <date day="8" month="6" year="2009"/>
98.200 - <author login="rmichalsky"/>
98.201 - <compatibility addition="yes"/>
98.202 - <description>
98.203 - <p>
98.204 - Newly added constructor allows to disable (slow) filling stack traces before posting each task.
98.205 - </p>
98.206 - </description>
98.207 - <class package="org.openide.util" name="RequestProcessor"/>
98.208 - <issue number="165862"/>
98.209 - </change>
98.210 - <change id="ImageUtilities.loadImageIcon">
98.211 - <api name="util"/>
98.212 - <summary>Added <code>loadImageIcon(String resource, boolean localized)</code></summary>
98.213 - <version major="7" minor="22"/>
98.214 - <date day="26" month="1" year="2009"/>
98.215 - <author login="t_h"/>
98.216 - <compatibility addition="yes"/>
98.217 - <description>
98.218 - <p>
98.219 - Convenient method for loading icons.
98.220 - </p>
98.221 - </description>
98.222 - <class package="org.openide.util" name="ImageUtilities"/>
98.223 - <issue number="157254"/>
98.224 - </change>
98.225 - <change id="Utilities.keyToString">
98.226 - <api name="util"/>
98.227 - <summary>Added <code>keyToString(KeyStroke stroke, boolean portable)</code></summary>
98.228 - <version major="7" minor="21"/>
98.229 - <date day="8" month="1" year="2009"/>
98.230 - <author login="msauer"/>
98.231 - <compatibility addition="yes"/>
98.232 - <description>
98.233 - <p>
98.234 - <code>keyToString(KeyStroke stroke, boolean portable)</code>
98.235 - provides cross-platform compitable keystroke textual representation
98.236 - instead of hardcoding Ctrl, Meta or Alt key.
98.237 - </p>
98.238 - </description>
98.239 - <class package="org.openide.util" name="Utilities"/>
98.240 - <issue number="110492"/>
98.241 - </change>
98.242 - <change id="Utilities.OS_OPENBSD">
98.243 - <api name="util"/>
98.244 - <summary>Added <code>OS_OPENBSD</code> and <code>OS_UNIX_OTHER</code> fields</summary>
98.245 - <version major="7" minor="18"/>
98.246 - <date day="16" month="9" year="2008"/>
98.247 - <author login="jskrivanek"/>
98.248 - <compatibility addition="yes"/>
98.249 - <description>
98.250 - <p>
98.251 - Added a new <code>Utilities.OS_OPENBSD</code> and <code>OS_UNIX_OTHER</code>
98.252 - fields. Deprecated <code>OS_WINDOWS_MASK</code> and <code>OS_UNIX_MASK</code>.
98.253 - </p>
98.254 - </description>
98.255 - <class package="org.openide.util" name="Utilities"/>
98.256 - <issue number="145462"/>
98.257 - </change>
98.258 - <change id="Utilities.OS_WINVISTA">
98.259 - <api name="util"/>
98.260 - <summary>Added <code>OS_WINVISTA</code> field</summary>
98.261 - <version major="7" minor="17"/>
98.262 - <date day="8" month="8" year="2008"/>
98.263 - <author login="jskrivanek"/>
98.264 - <compatibility addition="yes"/>
98.265 - <description>
98.266 - <p>
98.267 - Added a new <code>Utilities.OS_WINVISTA</code> field to be able
98.268 - to recognize Windows Vista operating system.
98.269 - </p>
98.270 - </description>
98.271 - <class package="org.openide.util" name="Utilities"/>
98.272 - <issue number="142629"/>
98.273 - </change>
98.274 - <change id="XMLUtil.validate">
98.275 - <api name="xml"/>
98.276 - <summary>Added <code>XMLUtil.validate</code></summary>
98.277 - <version major="7" minor="17"/>
98.278 - <date day="11" month="7" year="2008"/>
98.279 - <author login="jglick"/>
98.280 - <compatibility addition="yes"/>
98.281 - <description>
98.282 - <p>
98.283 - Added a new method to validate XML documents against schemas.
98.284 - </p>
98.285 - </description>
98.286 - <class package="org.openide.xml" name="XMLUtil"/>
98.287 - <issue number="42686"/>
98.288 - </change>
98.289 - <change id="RequestProcessor.Executor">
98.290 - <api name="util"/>
98.291 - <summary>RequestProcessor implements Executor interface</summary>
98.292 - <version major="7" minor="16"/>
98.293 - <date day="27" month="6" year="2008"/>
98.294 - <author login="jtulach"/>
98.295 - <compatibility addition="yes"/>
98.296 - <description>
98.297 - <p>
98.298 - In order to align <code>RequestProcessor</code> closer to standard
98.299 - Java 5 concurrency utilities, the class now implements
98.300 - <a href="@JDK@/java/util/concurrent/Executor.html">Executor</a>
98.301 - interfaces and its <code>execute(Runnable)</code> method.
98.302 - </p>
98.303 - </description>
98.304 - <class package="org.openide.util" name="RequestProcessor"/>
98.305 - <issue number="134297"/>
98.306 - </change>
98.307 - <change id="Utilities.toolTips">
98.308 - <api name="util"/>
98.309 - <summary>ImageUtilities class (with additional methods) was created as
98.310 - replacement for "image methods" in Utilities. </summary>
98.311 - <version major="7" minor="15"/>
98.312 - <date day="6" month="6" year="2008"/>
98.313 - <author login="t_h"/>
98.314 - <compatibility addition="yes"/>
98.315 - <description>
98.316 - <p>
98.317 - Image methods were separated to <a href="@TOP@/org/openide/util/ImageUtilities.html">ImageUtilities</a>
98.318 - (renamed IconManager) as replacement for methods in Utilities.
98.319 - There are some additional methods for image tool tips manipulation.
98.320 - </p>
98.321 - <p>
98.322 - New methods for tool tips manipulation:
98.323 - <code>Image assignToolTipToImage(Image image, String text)</code>;
98.324 - <code>String getImageToolTip(Image image)</code>;
98.325 - <code>Image addToolTipToImage(Image image, String text)</code>;
98.326 - </p>
98.327 - <p>
98.328 - New method for conversion from Image to Icon:
98.329 - <code>Icon image2Icon(Image image)</code>;
98.330 - </p>
98.331 - <p>
98.332 - "Moved" methods from <a href="@TOP@/org/openide/util/Utilities.html">Utilities</a>:
98.333 - <code>Image icon2Image(Icon icon)</code>;
98.334 - <code>Image loadImage(String resourceID)</code>;
98.335 - <code>Image loadImage(String resource, boolean localized)</code>;
98.336 - <code>Image mergeImages(Image image1, Image image2, int x, int y)</code>;
98.337 - </p>
98.338 - </description>
98.339 - <class package="org.openide.util" name="Utilities"/>
98.340 - <class package="org.openide.util" name="ImageUtilities"/>
98.341 - <issue number="123469"/>
98.342 - </change>
98.343 - <change id="Mutex.Wrapper">
98.344 - <api name="util"/>
98.345 - <summary>Mutex made pluggable</summary>
98.346 - <version major="7" minor="12"/>
98.347 - <date day="3" month="1" year="2008"/>
98.348 - <author login="jtulach"/>
98.349 - <compatibility addition="yes"/>
98.350 - <description>
98.351 - <p>
98.352 - Added new constructor
98.353 - <a href="@TOP@/org/openide/util/Mutex.html">Mutex(Privileged, Executor)</a>
98.354 - that allows creators of the mutex to intercept and wrap all actions running
98.355 - inside the mutex with custom code.
98.356 - </p>
98.357 - </description>
98.358 - <class package="org.openide.util" name="Mutex"/>
98.359 - <issue number="123832"/>
98.360 - </change>
98.361 - <change id="Utilities.isLargeFrameIcons">
98.362 - <api name="util"/>
98.363 - <summary>Obsolete method <code>Utilities.isLargeFrameIcons</code> deprecated.</summary>
98.364 - <version major="7" minor="10"/>
98.365 - <date day="23" month="10" year="2007"/>
98.366 - <author login="mslama"/>
98.367 - <compatibility addition="no" deprecation="yes"/>
98.368 - <description>
98.369 - <p>
98.370 - Javadoc says: Test whether the operating system supports icons on frames (windows).
98.371 - But window system used this method to decide if small 16x16 or bigger 32x32 icon
98.372 - should be used for frame (main window). So usage and Javadoc is inconsistent.
98.373 - All OS support small icon in frame. From JDK 6 it is possible to set multiple size
98.374 - icons for frame so OS WM selects appropriate size.
98.375 - I removed useless usage of this method from window system code and this method is
98.376 - not used elsewhere.
98.377 - </p>
98.378 - </description>
98.379 - <class package="org.openide.util" name="Utilities"/>
98.380 - <issue number="119069"/>
98.381 - </change>
98.382 -
98.383 - <change id="ChangeSupport">
98.384 - <api name="util"/>
98.385 - <summary>Added <code>ChangeSupport</code></summary>
98.386 - <version major="7" minor="8"/>
98.387 - <date day="26" month="3" year="2007"/>
98.388 - <author login="abadea"/>
98.389 - <compatibility addition="yes"/>
98.390 - <description>
98.391 - <p>
98.392 - Added a <code>ChangeSupport</code> class to simplify
98.393 - the management of <code>ChangeListener</code>s and the
98.394 - firing of <code>ChangeEvent</code>s.
98.395 - </p>
98.396 - </description>
98.397 - <class package="org.openide.util" name="ChangeSupport"/>
98.398 - <issue number="95885"/>
98.399 - </change>
98.400 -
98.401 - <change id="Utilities.isMac">
98.402 - <api name="util"/>
98.403 - <summary>Added <code>Utilities.isMac()</code> method</summary>
98.404 - <version major="7" minor="7"/>
98.405 - <date day="11" month="1" year="2007"/>
98.406 - <author login="rkubacki"/>
98.407 - <compatibility addition="yes"/>
98.408 - <description>
98.409 - <p>
98.410 - Added a <code>Utilities.isMac()</code> method for checking
98.411 - if current platform is Mac.
98.412 - </p>
98.413 - </description>
98.414 - <class package="org.openide.util" name="Utilities"/>
98.415 - <issue number="61044"/>
98.416 - </change>
98.417 -
98.418 - <change id="Parameters">
98.419 - <api name="util"/>
98.420 - <summary>Added <code>Parameters</code></summary>
98.421 - <version major="7" minor="6"/>
98.422 - <date day="8" month="12" year="2006"/>
98.423 - <author login="abadea"/>
98.424 - <compatibility addition="yes"/>
98.425 - <description>
98.426 - <p>
98.427 - Added a <code>Parameters</code> class for checking the
98.428 - values of method parameters.
98.429 - </p>
98.430 - </description>
98.431 - <class package="org.openide.util" name="Parameters"/>
98.432 - <issue number="89768"/>
98.433 - </change>
98.434 -
98.435 - <change id="NbCollections.iterable">
98.436 - <api name="util"/>
98.437 - <summary>Added <code>NbCollections.iterable(...)</code> methods</summary>
98.438 - <version major="7" minor="5"/>
98.439 - <date day="13" month="11" year="2006"/>
98.440 - <author login="jglick"/>
98.441 - <compatibility addition="yes"/>
98.442 - <description>
98.443 - <p>
98.444 - Added two new methods to make enhanced for-loops easier to use
98.445 - with legacy APIs returning <code>Iterator</code> or <code>Enumeration</code>.
98.446 - </p>
98.447 - </description>
98.448 - <class package="org.openide.util" name="NbCollections"/>
98.449 - <issue number="88606"/>
98.450 - </change>
98.451 -
98.452 - <change id="nbpreferences">
98.453 - <api name="util"/>
98.454 - <summary>Added <code>NbPreferences.forModule(Class cls)</code> and
98.455 - <code>NbPreferences.root()</code> methods as static factory methods
98.456 - for getting preference node from NetBeans preference tree.</summary>
98.457 - <version major="7" minor="4"/>
98.458 - <date day="10" month="11" year="2006"/>
98.459 - <author login="rmatous"/>
98.460 - <compatibility addition="yes" deprecation="no"/>
98.461 - <description>
98.462 - <p>
98.463 - NetBeans preference tree is provided by NetBeans implementation of preferences
98.464 - which uses userdir as a storage. Both newly added methods return
98.465 - preferences node from NetBeans preference tree.
98.466 - Method <code>NbPreferences.root()</code> returns root preference
98.467 - node.
98.468 - Method <code>NbPreferences.forModule(Class cls)</code> returns
98.469 - preference node whose
98.470 - path depends whether class provided as a parameter
98.471 - was loaded as a part of any module or not. If so, then absolute path corresponds to slashified
98.472 - code name base of module. If not, then absolute path corresponds to class's package.
98.473 - See document
98.474 - <a href="@TOP@/org/openide/util/doc-files/preferences.html">Preferences in NetBeans</a>
98.475 - to learn more about preferences in NetBeans.
98.476 - </p>
98.477 - </description>
98.478 - <class package="org.openide.util" name="NbPreferences"/>
98.479 - <issue number="73474"/>
98.480 - </change>
98.481 -
98.482 - <change id="icon2image">
98.483 - <api name="util"/>
98.484 - <summary>Added <code>Utilities.icon2Image</code> method to perform conversion from <code>Icon</code> to Image</summary>
98.485 - <version major="7" minor="3"/>
98.486 - <date day="4" month="7" year="2006"/>
98.487 - <author login="rkubacki"/>
98.488 - <compatibility addition="yes" deprecation="no"/>
98.489 - <description>
98.490 - <p>
98.491 - Conversion from <code>Icon</code> to <code>Image</code> is done
98.492 - at various places and newly introduced method avoids the need to
98.493 - duplicate the same code.
98.494 - </p>
98.495 - </description>
98.496 - <class package="org.openide.util" name="Utilities"/>
98.497 - <issue number="52562"/>
98.498 - </change>
98.499 -
98.500 - <change id="Exceptions">
98.501 - <api name="util"/>
98.502 - <summary>Added <code>Exceptions</code> class as a replacement for <code>ErrorManager</code></summary>
98.503 - <version major="7" minor="2"/>
98.504 - <date day="20" month="6" year="2006"/>
98.505 - <author login="jtulach"/>
98.506 - <compatibility addition="yes" deprecation="yes"/>
98.507 - <description>
98.508 - <p>
98.509 - <code>ErrorManager</code> is now deprecated and its replacement
98.510 - is either <a href="@JDK@/java/util/logging/Logger.html">Logger</a>
98.511 - or <code>Exceptions</code>.
98.512 - </p>
98.513 - </description>
98.514 - <class package="org.openide.util" name="Exceptions"/>
98.515 - <issue number="35067"/>
98.516 - </change>
98.517 -
98.518 - <change id="NbCollections">
98.519 - <api name="util"/>
98.520 - <summary>Added <code>NbCollections</code> and <code>Union2</code></summary>
98.521 - <version major="7" minor="1"/>
98.522 - <date day="5" month="6" year="2006"/>
98.523 - <author login="jglick"/>
98.524 - <compatibility addition="yes"/>
98.525 - <description>
98.526 - <p>
98.527 - Added two new classes useful for transitioning to JDK 5 generics.
98.528 - </p>
98.529 - </description>
98.530 - <class package="org.openide.util" name="NbCollections"/>
98.531 - <class package="org.openide.util" name="Union2"/>
98.532 - <issue number="73637"/>
98.533 - </change>
98.534 -
98.535 - <change id="use-logging" >
98.536 - <api name="util"/>
98.537 - <summary>Do not use ErrorManager for logging</summary>
98.538 - <version major="7" minor="0"/>
98.539 - <date day="15" month="4" year="2006"/>
98.540 - <author login="jtulach"/>
98.541 - <compatibility addition="yes" modification="yes" binary="compatible" source="compatible" semantic="incompatible" deprecation="no" deletion="no"/>
98.542 - <description>
98.543 - <a href="@TOP@/org/openide/ErrorManager.html">ErrorManager</a>
98.544 - is no longer the recommended way to do logging in NetBeans based
98.545 - application. Instead NetBeans now fully support logging two JDK's
98.546 - standard <a href="@JDK@/java/util/logging/Logger.html">Logger</a>.
98.547 - See the
98.548 - <a href="@TOP@/org/openide/util/doc-files/logging.html">NetBeans logging guide</a>
98.549 - to learn the best practises for logging in NetBeans.
98.550 - <br/>
98.551 - <a href="@TOP@/org/openide/ErrorManager.html">ErrorManager</a>
98.552 - is still kept around for annotating exceptions with localized
98.553 - messages and advanced manipulation and its behaviour is fully
98.554 - backward compatible. However modules are adviced to migrate to
98.555 - <a href="@JDK@/java/util/logging/Logger.html">logging</a> whereever
98.556 - possible.
98.557 - <br/>
98.558 - To migrate your modules you can install Jackpot modules from
98.559 - autoupdate (if they are not yet part of your IDE) and apply
98.560 - precreate <a href="http://www.netbeans.org/source/browse/openide/util/Attic/ErrorManagerJackpot.rules">
98.561 - javapot error manager rule</a>.
98.562 - <br/>
98.563 - There is one possible incompatibility from end user point of view.
98.564 - The way to <em>enable logging</em> for certain components when
98.565 - running inside the whole NetBeans container has changed:
98.566 - If there is
98.567 - <a href="@JDK@/java/util/logging/Logger.html">Logger</a> or
98.568 - <a href="@TOP@/org/openide/ErrorManager.html">ErrorManager</a>
98.569 - named <q>org.mymodule.MyComponent</q> then the correct way
98.570 - to turn the logging is now to invoke NetBeans with
98.571 - <code>-J-Dorg.mymodule.MyComponent<b>.level</b>=100</code>
98.572 - (where the possible constants are taken form
98.573 - a JDK's definition of <a href="@JDK@/java/util/logging/Level.html">level</a>).
98.574 - There is however a certain benefit in this change, the value
98.575 - of the property (like <q>org.mymodule.MyComponent.level</q>)
98.576 - can be changed during runtime and thus the logging can be
98.577 - enabled or disabled dynamically (after changing the value, it is
98.578 - necessary to call
98.579 - <a href="@JDK@/java/util/logging/LogManager.html">LogManager.readConfiguration()</a>).
98.580 - </description>
98.581 - <class package="org.openide" name="ErrorManager"/>
98.582 - <issue number="56311"/>
98.583 - </change>
98.584 - <change id="rp-create-true" >
98.585 - <api name="util"/>
98.586 - <summary>Ability to create finished RequestProcessor task</summary>
98.587 - <version major="6" minor="8"/>
98.588 - <date day="22" month="11" year="2005"/>
98.589 - <author login="jtulach"/>
98.590 - <compatibility addition="yes" modification="no" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no"/>
98.591 - <description>
98.592 - <a href="@TOP@/org/openide/util/RequestProcessor.html">RequestProcessor.create(Runnable, boolean)</a>
98.593 - has been added to allow creation of
98.594 - <a href="@TOP@/org/openide/util/RequestProcessor.Task.html">Task</a>
98.595 - that has not executed its runnable yet, but looks like it is finished.
98.596 - </description>
98.597 - <class package="org.openide.util" name="RequestProcessor"/>
98.598 - <issue number="68031"/>
98.599 - </change>
98.600 -
98.601 - <change>
98.602 - <api name="util"/>
98.603 - <summary>DynamicMenuContent interface added</summary>
98.604 - <version major="6" minor="4"/>
98.605 - <date day="12" month="6" year="2005"/>
98.606 - <author login="mkleint"/>
98.607 - <compatibility addition="no" modification="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no"/>
98.608 - <description>
98.609 - In order to support MacOSX top menus and to fix problems with deprecated JInlineMenu, this new
98.610 - interface was added that allows to handle dynamic content in
98.611 -<a href="@TOP@/org/openide/util/actions/Presenter.Menu.html">Presenter.Menu</a>
98.612 - and <a href="@TOP@/org/openide/util/actions/Presenter.Popup.html">Presenter.Popup</a>.
98.613 - If the instance returned by Presenter.Menu/Popup is an instance of
98.614 -<a href="@org-openide-awt@/org/openide/awt/DynamicMenuContent.html">DynamicMenuContent</a>, it's methods are
98.615 - consulted when creating/updating the menu.
98.616 - </description>
98.617 - <class package="org.openide.util.actions" name="Presenter"/>
98.618 - <issue number="35827"/>
98.619 - </change>
98.620 -
98.621 -
98.622 -
98.623 - <change>
98.624 - <api name="util"/>
98.625 - <summary>Support for interruption of RequestProcessor tasks</summary>
98.626 - <version major="6" minor="3"/>
98.627 - <date day="10" month="6" year="2005"/>
98.628 - <author login="jtulach"/>
98.629 - <compatibility addition="yes" modification="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no"/>
98.630 - <description>
98.631 - When one calls <a href="@TOP@/org/openide/util/RequestProcessor.Task.html">RequestProcessor.Task</a>.cancel(),
98.632 - the running thread gets interrupted if the
98.633 - <a href="@TOP@/org/openide/util/RequestProcessor.html#RequestProcessor(java.lang.String,%20int,%20boolean)">
98.634 - RequestProcessor(string, int, boolean)
98.635 - </a>
98.636 - constructor is used.
98.637 - There always was a way how to cancel not yet running Task,
98.638 - but if the task was already running, one was out of luck. Since now
98.639 - the thread running the task is interrupted and the Runnable can check
98.640 - for that and terminate its execution sooner. In the runnable one shall
98.641 - check for thread interruption and
98.642 - if true, return immediatelly as in this example:
98.643 - <pre>
98.644 -public void run () {
98.645 - while (veryLongTimeLook) {
98.646 - doAPieceOfIt ();
98.647 -
98.648 - if (Thread.interrupted ()) return;
98.649 - }
98.650 -}
98.651 -</pre>
98.652 - </description>
98.653 - <class package="org.openide.util" name="RequestProcessor"/>
98.654 - <issue number="33467"/>
98.655 - </change>
98.656 - <change id="textual-icons-for-actions" >
98.657 - <api name="actions"/>
98.658 - <summary>Can create textual icons for actions</summary>
98.659 - <date day="23" month="3" year="2000"/>
98.660 - <author login="jglick"/>
98.661 - <compatibility addition="yes" modification="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no"/>
98.662 - <description>
98.663 - <code>iconResource</code> may now return <code>null</code> to indicate no
98.664 - icon. <code>getIcon(true)</code> may be used to get an icon created from
98.665 - the label if there is no icon specified.
98.666 - </description>
98.667 - <class package="org.openide.util.actions" name="SystemAction"/>
98.668 - </change>
98.669 - <change id="use-icon-instead-of-imageicon" >
98.670 - <api name="actions"/>
98.671 - <summary>
98.672 - <code>SystemAction</code> refers to <code>Icon</code> rather than <code>ImageIcon</code>
98.673 - </summary>
98.674 - <date day="11" month="4" year="2000"/>
98.675 - <author login="jglick"/>
98.676 - <compatibility modification="yes" binary="compatible" source="incompatible" semantic="compatible" deprecation="no" addition="no" deletion="no">
98.677 - First broken, later restored binary compatibility in trunk and
98.678 - <code>boston</code>. Any code explicitly using this calls before may break
98.679 - (source code may be compatible in many cases; binary compatibility has
98.680 - been preserved). These calls were known to be used only for
98.681 - <code>Actions</code> to create presenters; normal code which constructs
98.682 - <code>SystemAction</code>s and implements <code>iconResource</code> should
98.683 - be unaffected. Actions using the "grouping action" template should check
98.684 - their <code>getMenuPresenter</code> method which may be
98.685 - binary-incompatible; it is easy to replace the code with safer code such
98.686 - as:
98.687 - <pre xml:space="preserve">
98.688 -<span class="comment">// ....
98.689 -</span>
98.690 -<span class="keyword">private</span> <span class="keyword">static</span> <span class="type">Icon</span> <span class="variable-name">icon</span> = <span class="constant">null</span>;
98.691 -<span class="comment">// ....
98.692 -</span>
98.693 -<span class="keyword">public</span> <span class="type">JMenuItem</span> <span class="function-name">getMenuPresenter</span>() {
98.694 - <span class="type">JMenu</span> <span class="variable-name">menu</span> = <span class="keyword">new</span> <span class="type">JMenu</span>(getName ());
98.695 - <span class="keyword">if</span> (icon == <span class="constant">null</span>) {
98.696 - icon = <span class="keyword">new</span> <span class="type">ImageIcon</span>(MyAction.<span class="keyword">class</span>.getResource(iconResource()));
98.697 - }
98.698 - menu.setIcon(icon);
98.699 - <span class="comment">// ....</span>
98.700 -</pre>
98.701 - </compatibility>
98.702 - <description>
98.703 - <code>getIcon</code> and <code>setIcon</code> now use the interface
98.704 - <code>Icon</code> rather than the particular implementation
98.705 - <code>ImageIcon</code>. This corrects an API bug (excessive specificity).
98.706 - </description>
98.707 - <class package="org.openide.util.actions" name="SystemAction"/>
98.708 - </change>
98.709 - <change>
98.710 - <api name="actions"/>
98.711 - <summary>New Actions system - part I.</summary>
98.712 - <version major="3" minor="29"/>
98.713 - <date day="8" month="1" year="2003"/>
98.714 - <author login="jtulach"/>
98.715 - <author login="pzavadsky"/>
98.716 - <compatibility deprecation="yes" addition="yes" modification="yes" binary="compatible" source="compatible" semantic="compatible" deletion="no"/>
98.717 - <description>
98.718 - <p>
98.719 - Introduction of new action system, which generally means
98.720 - move from usage of <code>SystemAction</code> to <code>Action</code> instances.
98.721 - That document also focuses on declarative actions
98.722 - usage which is not subject of current change, it will be part of later changes.
98.723 - </p>
98.724 - </description>
98.725 - <class package="org.openide.util" name="ContextAwareAction"/>
98.726 - <class package="org.openide.util" name="Utilities"/>
98.727 - <class package="org.openide.util.actions" name="CallbackSystemAction"/>
98.728 - <issue number="27868"/>
98.729 - </change>
98.730 -
98.731 -<change id="Task-waitFinished-timeout">
98.732 - <api name="util"/>
98.733 - <summary>New method <code>task.waitFinished(timeout)</code> added</summary>
98.734 - <version major="5" minor="0"/>
98.735 - <date day="2" month="11" year="2004"/>
98.736 - <author login="jtulach"/>
98.737 - <compatibility addition="yes" binary="compatible" semantic="compatible" source="compatible" deprecation="no" deletion="no" modification="no"/>
98.738 - <description>
98.739 - <p>It is not possible to wait for a limited amount of time for
98.740 - completion of any task. The <code>RequestProcessor.Task</code>
98.741 - version is optimized, the <code>Task</code> version ensures that
98.742 - the sematics will be compatible for all subclasses, even they did
98.743 - not know about the method at all.
98.744 - </p>
98.745 - </description>
98.746 - <class package="org.openide.util" name="Task"/>
98.747 - <class package="org.openide.util" name="RequestProcessor"/>
98.748 - <issue number="16849"/>
98.749 - </change>
98.750 -<change id="add-detection-of-FreeBSD-OS">
98.751 - <api name="util"/>
98.752 - <summary>Added field <code>OS_FREEBSD</code> to <code>Utilities</code>
98.753 -</summary>
98.754 - <version major="4" minor="50"/>
98.755 - <date day="29" month="10" year="2004"/>
98.756 - <author login="jrechtacek"/>
98.757 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
98.758 - <description>
98.759 - <p>FreeBSD was not recognized as Unix OS. <code>Utilities</code> has been
98.760 - enlarged with new field <code>OS_FREEBSD</code>, part of OS Unix mask. <code>Utilities.isUnix()</code>
98.761 - now returns <code>true</code> for applications run on FreeBSD.
98.762 - </p>
98.763 - </description>
98.764 - <class package="org.openide.util" name="Utilities"/>
98.765 - </change>
98.766 - <change id="Mutex.isReadWriteAccess">
98.767 - <api name="util"/>
98.768 - <summary>Added <code>Mutex.isReadAccess()</code> and <code>Mutex.isWriteAcess()</code>
98.769 -</summary>
98.770 - <version major="4" minor="48"/>
98.771 - <date day="30" month="9" year="2004"/>
98.772 - <author login="jtulach"/>
98.773 - <compatibility addition="yes" binary="compatible" semantic="compatible" source="compatible" deprecation="no" deletion="no" modification="no"/>
98.774 - <description>
98.775 - A thread can now check whether read or write access on a <code>Mutex</code>
98.776 - has already been
98.777 - granted to it and use it to decide whether it is safe to perform
98.778 - certain operations or delay them.
98.779 - </description>
98.780 - <class package="org.openide.util" name="Mutex"/>
98.781 - <issue number="49459"/>
98.782 - </change>
98.783 -<change id="SharedClassObject.reset">
98.784 - <api name="util"/>
98.785 - <summary>Added <code>SharedClassObject.reset</code> method to allow subclasses to implement reset correctly</summary>
98.786 - <version major="4" minor="46"/>
98.787 - <date day="2" month="9" year="2004"/>
98.788 - <author login="jtulach"/>
98.789 - <compatibility addition="yes" binary="compatible" semantic="compatible" source="compatible" deprecation="no" deletion="no" modification="no"/>
98.790 - <description>
98.791 - The new <code>SharedClassObject.reset</code> method is called
98.792 - by the infrastructure in moments when an original (at the time
98.793 - of start) state of an option or any other <code>SharedClassObject</code>
98.794 - is requested. Interested subclasses are free to implement any kind of clean
98.795 - they need. The <code>SystemOption</code> provides a default
98.796 - implementation based on fired property changed events, so
98.797 - its correctly written subclasses do not need
98.798 - to do anything.
98.799 - </description>
98.800 - <class package="org.openide.util" name="SharedClassObject"/>
98.801 - <issue number="20962"/>
98.802 - </change>
98.803 -<change>
98.804 - <api name="util"/>
98.805 - <summary>enum package deprecated and replaced by Enumerations factory class</summary>
98.806 - <version major="4" minor="37"/>
98.807 - <date day="7" month="6" year="2004"/>
98.808 - <author login="jtulach"/>
98.809 - <compatibility deprecation="yes" addition="yes" binary="compatible" source="compatible" semantic="compatible" deletion="no" modification="no"/>
98.810 - <description>
98.811 - enum is a keyword in JDK 1.5 and as such it should not be used.
98.812 - That is the reason why we had to deprecated our
98.813 - <code>org.openide.util.enum</code> package. We are providing
98.814 - replacements of the original classes in form of factory methods
98.815 - <code>org.openide.util.Enumerations</code>.
98.816 - </description>
98.817 - <class package="org.openide.util" name="Enumerations"/>
98.818 - <issue number="41166"/>
98.819 - </change>
98.820 -<change>
98.821 - <api name="util"/>
98.822 - <summary>Support for complicated listeners</summary>
98.823 - <version major="4" minor="12"/>
98.824 - <date day="2" month="9" year="2003"/>
98.825 - <author login="jtulach"/>
98.826 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
98.827 - <description>
98.828 - Improved support for hierarchic listeners (aka NamingListener vs. ObjectChangeListener from
98.829 - javax.naming.event package).
98.830 - </description>
98.831 - <class package="org.openide.util" name="WeakListeners"/>
98.832 - <issue number="35726"/>
98.833 - </change>
98.834 -<change id="Utilities.actionsGlobalContext">
98.835 - <api name="util"/>
98.836 - <summary>Global action context as <code>Lookup</code>
98.837 -</summary>
98.838 - <version major="4" minor="10"/>
98.839 - <date day="12" month="8" year="2003"/>
98.840 - <author login="jtulach"/>
98.841 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
98.842 - <description>
98.843 - As part of the work on separation of openide.jar into smaller parts
98.844 - a new interface <code>ContextGlobalProvider</code> and new method
98.845 - in utilities <code>Utilities.actionsGlobalContext()</code> had to be
98.846 - added in order to separate the implementation of actions like
98.847 - <code>CallbackSystemAction</code> and <code>NodeAction</code> from
98.848 - their dependency on window system.
98.849 - </description>
98.850 - <class package="org.openide.util" name="ContextGlobalProvider"/>
98.851 - <class package="org.openide.util" name="Utilities"/>
98.852 - <issue number="34758"/>
98.853 - </change>
98.854 -<change id="WeakListeners">
98.855 - <api name="util"/>
98.856 - <summary>Old <code>WeakListener</code> replaced by <code>WeakListeners</code> class</summary>
98.857 - <version major="4" minor="10"/>
98.858 - <date day="12" month="8" year="2003"/>
98.859 - <author login="jtulach"/>
98.860 - <compatibility deprecation="yes" addition="yes" binary="compatible" source="compatible" semantic="compatible" deletion="no" modification="no"/>
98.861 - <description>
98.862 - <p>
98.863 - As part of the work on separation of openide.jar into smaller parts
98.864 - the <code>WeakListener</code> had to be deprecated as it referenced too
98.865 - many classes around and replaced by more general <code>WeakListeners</code>
98.866 - factory class that provides a generic <code>create</code> method and
98.867 - specialized factory methods just for JDK own interfaces.
98.868 - </p>
98.869 - <p>
98.870 - Also few factory methods were spread into appropriate packages like
98.871 - <code>FileUtil.weakFileChangeListener</code> and
98.872 - <code>NodeOp.weakNodeListener</code>.
98.873 - </p>
98.874 - </description>
98.875 - <class package="org.openide.util" name="WeakListeners"/>
98.876 - <issue number="34758"/>
98.877 - </change>
98.878 - <change id="HelpCtx.findHelp">
98.879 - <api name="util"/>
98.880 - <summary>New method to find HelpCtx</summary>
98.881 - <version major="4" minor="3"/>
98.882 - <date day="2" month="4" year="2003"/>
98.883 - <author login="jtulach"/>
98.884 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
98.885 - <description>
98.886 - A new method for finding HelpCtx (<code>HelpCtx.findHelp(Object)</code>)
98.887 - has been added to replace
98.888 - the old <code>InstanceSupport.findHelp</code> that has been
98.889 - separated out from the openide.jar.
98.890 - </description>
98.891 - <class package="org.openide.util" name="HelpCtx"/>
98.892 - <issue number="32143"/>
98.893 - </change>
98.894 -<change>
98.895 - <api name="util"/>
98.896 - <summary>Retrofit of interface Cancellable into RequestProcessor.Task</summary>
98.897 - <version major="4" minor="1"/>
98.898 - <date day="14" month="3" year="2003"/>
98.899 - <author login="dsimonek"/>
98.900 - <compatibility modification="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" addition="no" deletion="no"/>
98.901 - <description>
98.902 - RequestProcessor.Task was made to implement util.Cancellable interface.
98.903 - No change of implementation at all, RP.Task already had method from
98.904 - interface implemented, this is just a logical retrofit.
98.905 - </description>
98.906 - <class package="org.openide.util" name="RequestProcessor"/>
98.907 - </change>
98.908 -<change>
98.909 - <api name="util"/>
98.910 - <summary>Support for asynchronous init of UI components</summary>
98.911 - <version major="3" minor="36"/>
98.912 - <date day="5" month="2" year="2003"/>
98.913 - <author login="dsimonek"/>
98.914 - <compatibility deprecation="no" addition="yes" binary="compatible" source="compatible" semantic="compatible" deletion="no" modification="no"/>
98.915 - <description>
98.916 - <p>
98.917 - Performance related API addition, allows clients to write asynchronous
98.918 - initialization of UI components easily by providing <code>AsyncGUIJob</code>
98.919 - implementation. Also introduced <code>Cancellable</code> ability.
98.920 - <code>Utilities.attachInitJob</code> couples init job with target
98.921 - UI component.
98.922 - </p>
98.923 - </description>
98.924 - <class package="org.openide.util" name="AsyncGUIJob"/>
98.925 - <class package="org.openide.util" name="Cancellable"/>
98.926 - <class package="org.openide.util" name="Utilities"/>
98.927 - <issue number="30604"/>
98.928 - </change>
98.929 -<change>
98.930 - <api name="util"/>
98.931 - <summary>org.openide.util.Utilities.createProgressCursor added</summary>
98.932 - <version major="3" minor="23"/>
98.933 - <date day="2" month="12" year="2002"/>
98.934 - <author login="dsimonek"/>
98.935 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
98.936 - <description>
98.937 - Method java.awt.Cursor createProgressCursor(java.awt.Component comp) was
98.938 - added into Utilities class. Method creates mouse cursor suitable for
98.939 - components which are busy, but still reacts to the input events. (don't
98.940 - block UI).
98.941 - </description>
98.942 - <class package="org.openide.util" name="Utilities"/>
98.943 - </change>
98.944 -<change>
98.945 - <api name="util"/>
98.946 - <summary>Added interface HelpCtx.Provider</summary>
98.947 - <version major="3" minor="20"/>
98.948 - <date day="11" month="11" year="2002"/>
98.949 - <author login="pnejedly"/>
98.950 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
98.951 - <description>
98.952 - An interface HelpCtx.Provider with one method getHelpCtx was added
98.953 - and the logic in HelpCtx.findHelp and InstanceSupport.findHelp
98.954 - was extended to take this interface into accout.
98.955 - Various classes with existing getHelpCtx method were retrofitted
98.956 - to implement this interface.
98.957 - </description>
98.958 - <class package="org.openide.util" name="HelpCtx"/>
98.959 - <class package="org.openide" name="ServiceType"/>
98.960 - <class package="org.openide.util.actions" name="SystemAction"/>
98.961 - <class package="org.openide.util.datatransfer" name="NewType"/>
98.962 - <class package="org.openide.util.datatransfer" name="PasteType"/>
98.963 - </change>
98.964 -<change>
98.965 - <api name="util"/>
98.966 - <summary>Can load localized cached images</summary>
98.967 - <version major="3" minor="24"/>
98.968 - <date day="15" month="12" year="2002"/>
98.969 - <author login="jglick"/>
98.970 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
98.971 - <description>
98.972 - Added method <code>Utilities.loadImage(String, boolean)</code>
98.973 - which works like <code>Utilities.loadImage(String)</code> except
98.974 - that it will search for localized images. Also
98.975 - <code>SystemAction.getIcon()</code> will load a localized image now
98.976 - if there is one.
98.977 - </description>
98.978 - <class package="org.openide.util" name="Utilities"/>
98.979 - <class package="org.openide.util.actions" name="SystemAction"/>
98.980 - <issue number="22156"/>
98.981 - </change>
98.982 -<change>
98.983 - <api name="util"/>
98.984 - <summary>Utilities.activeReferenceQueue()</summary>
98.985 - <version major="3" minor="11"/>
98.986 - <date day="7" month="10" year="2002"/>
98.987 - <author login="jtulach"/>
98.988 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
98.989 - <description>
98.990 - Active java.util.ref.ReferenceQueue that polls for all
98.991 - enqued instances (that should implement Runnable) and
98.992 - invokes their run method to do actual cleanup.
98.993 - </description>
98.994 - <class package="org.openide.util" name="Utilities"/>
98.995 - <issue number="27238"/>
98.996 - </change>
98.997 -<change>
98.998 - <api name="util"/>
98.999 - <summary>Deprecation of parts of MouseUtils.PopupMenuAdapter</summary>
98.1000 - <version major="3" minor="4"/>
98.1001 - <date day="6" month="8" year="2002"/>
98.1002 - <author login="dsimonek"/>
98.1003 - <compatibility deprecation="yes" binary="compatible" source="compatible" semantic="compatible" addition="no" deletion="no" modification="no"/>
98.1004 - <description>
98.1005 - Constructor MouseUtils.PopupMenuAdapter(int) and public static field
98.1006 - DEFAULT_THESHOLD are now obsoleted, performs no action.
98.1007 - PopupMenuAdapter now delegates to isPopupTrigger crossplatform call,
98.1008 - should be constructed via default constructor.
98.1009 - </description>
98.1010 - </change>
98.1011 -<change>
98.1012 - <api name="util"/>
98.1013 - <summary>
98.1014 -<code>Utilities.toFile</code> and <code>toURL</code> added</summary>
98.1015 - <version major="3" minor="26"/>
98.1016 - <date day="24" month="12" year="2002"/>
98.1017 - <author login="jglick"/>
98.1018 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no">
98.1019 - Existing code which uses the JDK 1.3 method <code>File.toURL</code> should be
98.1020 - examined, as it may be better to call <code>Utilities.toURL</code>.
98.1021 - Similarly, code which gets the path from a URL and calls the <code>File</code>
98.1022 - constructor may need to be changed to call <code>Utilities.toFile</code>.
98.1023 - Such changes should improve robustness of code when used in strangely
98.1024 - named directories.
98.1025 - </compatibility>
98.1026 - <description>
98.1027 - Two new utility methods were added which permit easy interconversion between
98.1028 - files and URLs using the <code>file</code> protocol. This task is easy and
98.1029 - safe under JDK 1.4, yet JDK 1.3 lacks a single call to do these tasks which
98.1030 - will handle unusual characters in file names, especially hash marks. The
98.1031 - utility methods use the JDK 1.4 variants when possible, else use specially
98.1032 - coded versions of the JDK 1.3 variants which handle hash marks.
98.1033 - </description>
98.1034 - <class package="org.openide.util" name="Utilities"/>
98.1035 - <issue number="29711"/>
98.1036 - </change>
98.1037 -<change>
98.1038 - <api name="util"/>
98.1039 - <summary>Added RequestProcessor.getDefault(), deprecated static methods in RequestProcessor</summary>
98.1040 - <version major="2" minor="12"/>
98.1041 - <date day="15" month="4" year="2002"/>
98.1042 - <author login="pnejedly"/>
98.1043 - <compatibility addition="yes" deprecation="yes" binary="compatible" source="compatible" semantic="compatible" deletion="no" modification="no"/>
98.1044 - <description>Sharing of singlethreaded
98.1045 - <code>RequestProcessor.DEFAULT</code>
98.1046 - through the static methods is inherently deadlock-prone,
98.1047 - so the methods are deprecated and their usage should phase out
98.1048 - in the favor of using private <code>RequestProcessor</code>s
98.1049 - or the shared multithreaded instance available through the new
98.1050 - static method <code>RequestProcessor.getDefault()</code>.
98.1051 - </description>
98.1052 - <class package="org.openide.util" name="RequestProcessor"/>
98.1053 - </change>
98.1054 -<change>
98.1055 - <api name="util"/>
98.1056 - <summary>Added helper methods to aid module developers to write code which works correctly with multiple monitors</summary>
98.1057 - <version major="2" minor="5"/>
98.1058 - <date day="26" month="2" year="2002"/>
98.1059 - <author login="ttran"/>
98.1060 - <compatibility addition="yes" deprecation="yes" binary="compatible" source="compatible" semantic="compatible" deletion="no" modification="no"/>
98.1061 - <description>
98.1062 - The added methods are
98.1063 - <pre xml:space="preserve">
98.1064 -<span class="keyword">public</span> <span class="keyword">static</span> <span class="type">Rectangle</span> <span class="function-name">getUsableScreenBounds</span>();
98.1065 -<span class="keyword">public</span> <span class="keyword">static</span> <span class="type">Rectangle</span> <span class="function-name">getUsableScreenBounds</span>(<span class="type">GraphicsConfiguration</span> <span class="variable-name">gconf</span>);
98.1066 -<span class="keyword">public</span> <span class="keyword">static</span> <span class="type">Rectangle</span> <span class="function-name">findCenterBounds</span>(<span class="type">Dimension</span> <span class="variable-name">componentSize</span>);
98.1067 -</pre>
98.1068 - One should use these methods instead of calling
98.1069 - <code>Toolkit.getScreenSize()</code>. For the same reason
98.1070 - <code>Utilities.getScreenSize()</code> is now deprecated.
98.1071 - </description>
98.1072 - <class package="org.openide.util" name="Utilities"/>
98.1073 - <issue number="20882"/>
98.1074 - </change>
98.1075 -<change id="ErrorManager.getDefault">
98.1076 - <api name="util"/>
98.1077 - <summary>Added accessibility method ErrorManager.getDefault () that always returns non-null values</summary>
98.1078 - <version major="2" minor="1"/>
98.1079 - <date day="17" month="1" year="2002"/>
98.1080 - <author login="jtulach"/>
98.1081 - <compatibility addition="yes" modification="yes" deprecation="yes" binary="compatible" source="compatible" semantic="compatible" deletion="no"/>
98.1082 - <description>
98.1083 - <p>
98.1084 - This method allows independent libraries (nodes, filesystems, utilities) to use the ErrorManager without
98.1085 - testing if it is really present. Just call <code>ErrorManager.getDefault ()</code> and you can be sure
98.1086 - that a valid instance will be returned.
98.1087 - </p>
98.1088 - <p>
98.1089 - Also <code>TopManager.getErrorManager</code> is no longer useful (<a href="#ErrorManager.getDefault" shape="rect">see change</a>) and is now deprecated.
98.1090 - It is also not abstract as it just delegates.
98.1091 - <code>notifyException</code> is similarly deprecated.
98.1092 - </p>
98.1093 - </description>
98.1094 - <class package="org.openide" name="ErrorManager"/>
98.1095 - <issue number="16854"/>
98.1096 - </change>
98.1097 - <change id="logging-added-to-error-manager" >
98.1098 - <api name="util"/>
98.1099 - <summary>
98.1100 -<code>ErrorManager.isLoggable</code> added</summary>
98.1101 - <date day="2" month="12" year="2000"/>
98.1102 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
98.1103 - <description>
98.1104 - <code>isLoggable(int severity)</code> added to <code>ErrorManager</code>.
98.1105 - </description>
98.1106 - <class package="org.openide" name="ErrorManager"/>
98.1107 - </change>
98.1108 -<change>
98.1109 - <api name="util"/>
98.1110 - <summary>Logging and hierarchy support added to <code>ErrorManager</code>
98.1111 -</summary>
98.1112 - <date day="18" month="8" year="2000"/>
98.1113 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
98.1114 - <description>
98.1115 - <code>getInstance(String name)</code>, <code>log(int severity, String s)</code>, and
98.1116 - <code>log(String s)</code> added to <code>ErrorManager</code>.
98.1117 - </description>
98.1118 - <class package="org.openide" name="ErrorManager"/>
98.1119 - </change>
98.1120 - <change>
98.1121 - <api name="xml"/>
98.1122 - <summary>Can register entity resolvers</summary>
98.1123 - <date day="20" month="12" year="2000"/>
98.1124 - <compatibility addition="yes" deprecation="yes" binary="compatible" source="compatible" semantic="compatible" deletion="no" modification="no">
98.1125 - Subsequently deprecated on <date day="3" month="3" year="2001"/> by
98.1126 - <a href="#created-XMLUtil" shape="rect">
98.1127 -<code>EntityCatalog</code>
98.1128 -</a>.
98.1129 - </compatibility>
98.1130 - <description>
98.1131 - <code>addEntityResolver</code> and <code>removeEntityResolver</code>
98.1132 - added. These methods allow a user to develop own implementation of
98.1133 - functionality similar to <code>registerCatalogEntry</code>. E.g. a user
98.1134 - can register <code>EntityResolver</code> that reads data from persistent
98.1135 - catalog avoiding bunch of calls to the register method in module
98.1136 - <code>restore</code> code.
98.1137 - </description>
98.1138 - <class package="org.openide.xml" name="EntityCatalog"/>
98.1139 - </change>
98.1140 -<change>
98.1141 - <api name="xml"/>
98.1142 - <summary>Updated DOM to level 2 and added document writability</summary>
98.1143 - <date day="26" month="1" year="2001"/>
98.1144 - <author login="pkuzel"/>
98.1145 - <compatibility modification="yes" binary="incompatible" source="incompatible" deprecation="yes" semantic="compatible" addition="no" deletion="no">
98.1146 - Any code implementing DOM interfaces could be broken by the level 2
98.1147 - interfaces. Clients of the DOM API should be unaffected.
98.1148 - </compatibility>
98.1149 - <description>
98.1150 - <ul>
98.1151 - <li>All level 1 <code>Document</code>s interfaces became level 2 ones.</li>
98.1152 - <li>Deprecated <code>write(Document, Writer)</code>
98.1153 - <p>A conflict between encoding declared in document and
98.1154 - actual Writer encoding can cause data loss. Suitable
98.1155 - just for UTF-8 and UTF-16 writers.
98.1156 - </p>
98.1157 - </li>
98.1158 - <li>introduced <code>write(Document, OutputStream, String encoding)</code>
98.1159 - <p>
98.1160 - The write method is supposed to be used as an implementation
98.1161 - independent way for writing DOM documents until self-writable
98.1162 - documents specification will be introduced. The self-writability
98.1163 - is considered to be a part of DOM level 3 specs.
98.1164 - </p>
98.1165 - <p>
98.1166 - Nowadays it is implemented that it can handle following DOM implementations:
98.1167 - </p>
98.1168 - <ul>
98.1169 - <li>Crimson</li>
98.1170 - <li>JAXP 1.0 reference implementation</li>
98.1171 - <li>All others using Apache's serializers if available.</li>
98.1172 - </ul>
98.1173 - </li>
98.1174 - </ul>
98.1175 - </description>
98.1176 - <class package="org.openide.xml" name="XMLUtil"/>
98.1177 - </change>
98.1178 -<change id="Utilities.topologicalSort">
98.1179 - <api name="util"/>
98.1180 - <summary>Improved method for topological sort</summary>
98.1181 - <version major="3" minor="30"/>
98.1182 - <date day="10" month="1" year="2003"/>
98.1183 - <author login="jglick"/>
98.1184 - <compatibility deprecation="yes" addition="yes" binary="compatible" source="compatible" semantic="compatible" deletion="no" modification="no"/>
98.1185 - <description>
98.1186 - The method <code>Utilities.topologicalSort</code> was added. It should be
98.1187 - faster and probably more robust than the older <code>partialSort</code>
98.1188 - method, which required a <code>Comparator</code>; the new method requires
98.1189 - a list of ordering constraints, which should be <i>O(n + m)</i>
98.1190 - rather than <i>O(n<sup>2</sup>)</i> (where <i>n</i> is the number of
98.1191 - nodes to sort and <i>m</i> the number of edges). If the graph is
98.1192 - not a DAG a <code>TopologicalSortException</code> is thrown containing
98.1193 - description of unsortable parts of the graph and the best partitial sort
98.1194 - that fullfils as much of ordering constraints as possible. These
98.1195 - information can be used for error reporting and recovery.
98.1196 - </description>
98.1197 - <class package="org.openide.util" name="Utilities"/>
98.1198 - <class package="org.openide.util" name="TopologicalSortException"/>
98.1199 - <issue number="27286"/>
98.1200 - </change>
98.1201 -<change>
98.1202 - <api name="xml"/>
98.1203 - <summary>Moved XML static methods into separate inner class</summary>
98.1204 - <date day="16" month="2" year="2001"/>
98.1205 - <author login="pkuzel"/>
98.1206 - <compatibility addition="yes" deprecation="yes" binary="compatible" source="compatible" semantic="compatible" deletion="no" modification="no">
98.1207 - <code>XMLDataObject.Util</code> itself deprecated on
98.1208 - <date day="3" month="3" year="2001"/> in favor of
98.1209 - <a href="#created-XMLUtil" shape="rect">
98.1210 -<code>XMLUtil</code>
98.1211 -</a>.
98.1212 - </compatibility>
98.1213 - <description>
98.1214 - <ul>
98.1215 - <li>
98.1216 - Deprecated all static: <code>write()</code>s, <code>parse()</code>s,
98.1217 - <code>createDocument()</code>, <code>createInputSource()</code> and
98.1218 - <code>createParser()</code>s methods.
98.1219 - </li>
98.1220 - <li>
98.1221 - Introduced public static inner class named <code>Util</code> providing
98.1222 - utility methods replacing deprecated ones.
98.1223 - </li>
98.1224 - </ul>
98.1225 - </description>
98.1226 - <class package="org.openide.xml" name="XMLUtil"/>
98.1227 - </change>
98.1228 - <change id="Mutex.Privileged">
98.1229 - <api name="util"/>
98.1230 - <summary>Permit privileged access to mutexes to avoid inner classes</summary>
98.1231 - <version major="1" minor="17"/>
98.1232 - <date day="27" month="6" year="2001"/>
98.1233 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
98.1234 - <description>
98.1235 - Added a new inner class and a constructor that takes an instance of that
98.1236 - inner class as a parameter. The inner class is <code>Privileged</code>.
98.1237 - Through its public methods one can enter internal states of the
98.1238 - <code>Mutex</code> to which it was passed.
98.1239 - </description>
98.1240 - <class package="org.openide.util" name="Mutex"/>
98.1241 - </change>
98.1242 -<change id="Task.notifyRunning">
98.1243 - <api name="util"/>
98.1244 - <summary>More flexibility in controlling running of tasks</summary>
98.1245 - <version major="1" minor="5"/>
98.1246 - <date day="27" month="4" year="2001"/>
98.1247 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
98.1248 - <description>
98.1249 - <code>Task</code> has new protected constructor for subclasses and
98.1250 - methods <code>notifyRunning ()</code> and also non-final version of
98.1251 - <code>waitFinished ()</code>.
98.1252 - </description>
98.1253 - <class package="org.openide.util" name="Task"/>
98.1254 - </change>
98.1255 - <change>
98.1256 - <api name="util"/>
98.1257 - <summary>
98.1258 - <code>ErrorManager.isNotifiable</code> added</summary>
98.1259 - <version major="3" minor="18"/>
98.1260 - <date day="3" month="11" year="2002"/>
98.1261 - <author login="jglick"/>
98.1262 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no">
98.1263 - Existing code which assumes (incorrectly) that <code>isLoggable</code>
98.1264 - can be used for this purpose, or which calls <code>notify</code> at a low
98.1265 - level such as <code>INFORMATIONAL</code> without first checking
98.1266 - <code>isNotifiable</code> for efficiency, should be revised.
98.1267 - </compatibility>
98.1268 - <description>
98.1269 - The method <code>ErrorManager.isNotifiable</code> was added to capture
98.1270 - the fact that an error manager implementation might be more aggressive
98.1271 - about displaying stack traces than log messages.
98.1272 - </description>
98.1273 - <class package="org.openide" name="ErrorManager"/>
98.1274 - <issue number="24056"/>
98.1275 - </change>
98.1276 - <change id="clone-service-type" >
98.1277 - <api name="util"/>
98.1278 - <summary>
98.1279 - <code>ServiceType.createClone</code> added</summary>
98.1280 - <date day="30" month="11" year="2000"/>
98.1281 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no">Subclasses are encouraged to implement <code>Cloneable</code>.</compatibility>
98.1282 - <description>
98.1283 - <code>public final ServiceType createClone()</code> added.
98.1284 - </description>
98.1285 - <class package="org.openide" name="ServiceType"/>
98.1286 - </change>
98.1287 -<change>
98.1288 - <api name="util"/>
98.1289 - <summary>Icon & image cache manager added</summary>
98.1290 - <date day="9" month="3" year="2001"/>
98.1291 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
98.1292 - <description>
98.1293 - Loading icons and images can be done through
98.1294 - <code>Utilities.loadImage()</code> that uses cache to avoid duplicate
98.1295 - loading of images. <code>mergeImages</code> uses the cache, too, for the
98.1296 - results of merge.
98.1297 - </description>
98.1298 - <class package="org.openide.util" name="Utilities"/>
98.1299 - </change>
98.1300 -<change>
98.1301 - <api name="util"/>
98.1302 - <summary>Updated DEC -> Compaq OS names</summary>
98.1303 - <date day="15" month="12" year="2000"/>
98.1304 - <compatibility modification="yes" deprecation="yes" binary="compatible" source="compatible" semantic="compatible" addition="no" deletion="no"/>
98.1305 - <description>
98.1306 - Operating system <code>OS_DEC</code> changed to <code>OS_TRU64</code>,
98.1307 - and added <code>OS_VMS</code>.
98.1308 - </description>
98.1309 - <class package="org.openide.util" name="Utilities"/>
98.1310 - </change>
98.1311 -<change>
98.1312 - <api name="util"/>
98.1313 - <summary>Proper break iterators used when wrapping text strings</summary>
98.1314 - <date day="11" month="8" year="2000"/>
98.1315 - <compatibility modification="yes" deprecation="yes" binary="compatible" source="compatible" semantic="compatible" addition="no" deletion="no">
98.1316 - Deprecated version first removed, later re-added with deprecation in the
98.1317 - trunk.
98.1318 - </compatibility>
98.1319 - <description>
98.1320 - Added method <code>wrapString</code> which uses
98.1321 - <code>BreakIterator</code> instead of a flag and a heuristic solution.
98.1322 - <code>wrapString(String,int,boolean,boolean)</code> deprecated.
98.1323 - </description>
98.1324 - <class package="org.openide.util" name="Utilities"/>
98.1325 - </change>
98.1326 -<change>
98.1327 - <api name="util"/>
98.1328 - <summary>Support for merging icons added</summary>
98.1329 - <date day="25" month="1" year="2001"/>
98.1330 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
98.1331 - <description>
98.1332 - Added method <code>mergeImages(Image image1, Image image2, int x, int
98.1333 - y)</code> for merging images.
98.1334 - </description>
98.1335 - <class package="org.openide.util" name="Utilities"/>
98.1336 - </change>
98.1337 -<change>
98.1338 - <api name="util"/>
98.1339 - <summary>Can get a list of localizing suffixes</summary>
98.1340 - <date day="1" month="1" year="2001"/>
98.1341 - <author login="jglick"/>
98.1342 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
98.1343 - <description>
98.1344 - <code>getLocalizingSuffixes</code> added.
98.1345 - </description>
98.1346 - <class package="org.openide.util" name="NbBundle"/>
98.1347 - </change>
98.1348 -<change>
98.1349 - <api name="util"/>
98.1350 - <summary>Can find localized variants of extensionless resources</summary>
98.1351 - <date day="6" month="10" year="2000"/>
98.1352 - <author login="jglick"/>
98.1353 - <compatibility modification="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" addition="no" deletion="no"/>
98.1354 - <description>
98.1355 - <code>getLocalizedFile</code> now accepts <code>null</code> extensions
98.1356 - to suppress the addition of a dot to the resource name.
98.1357 - </description>
98.1358 - <class package="org.openide.util" name="NbBundle"/>
98.1359 - </change>
98.1360 -<change>
98.1361 - <api name="util"/>
98.1362 - <summary>Added search for branded variants as part of locale lookup</summary>
98.1363 - <date day="20" month="7" year="2000"/>
98.1364 - <author login="jglick"/>
98.1365 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
98.1366 - <description>
98.1367 - Added methods <code>getBranding</code> and <code>setBranding</code>.
98.1368 - Normally these should only be called by the core implementation during
98.1369 - startup, not module authors. All methods to look up localized objects
98.1370 - may now also search for branded variants, if applicable.
98.1371 - </description>
98.1372 - <class package="org.openide.util" name="NbBundle"/>
98.1373 - </change>
98.1374 -<change>
98.1375 - <api name="util"/>
98.1376 - <summary>Classloader finder for <code>NbBundle</code> is obsolete</summary>
98.1377 - <date day="11" month="4" year="2000"/>
98.1378 - <compatibility deletion="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" addition="no" modification="no">
98.1379 - First removed, later re-added but deprecated in trunk and
98.1380 - <code>boston</code>. No one outside of <code>NbBundle</code> and the
98.1381 - core implementation should have been using these classes to begin with.
98.1382 - </compatibility>
98.1383 - <description>
98.1384 - <code>NbBundle.ClassLoaderFinder</code> and
98.1385 - <code>NbBundle.setClassLoaderFinder</code> have been deprecated; they
98.1386 - were quite obsolete.
98.1387 - </description>
98.1388 - <class package="org.openide.util" name="NbBundle"/>
98.1389 - </change>
98.1390 -<change>
98.1391 - <api name="util"/>
98.1392 - <summary>Special exception thrown to request interaction with user</summary>
98.1393 - <date day="5" month="3" year="2001"/>
98.1394 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
98.1395 - <description>
98.1396 - Added the first revision. This exception is thrown when a process is
98.1397 - about to perform some action that requires user confirmation.
98.1398 - </description>
98.1399 - <class package="org.openide.util" name="UserQuestionException"/>
98.1400 - </change>
98.1401 -<change>
98.1402 - <api name="util"/>
98.1403 - <summary>
98.1404 -<code>SafeException</code> is a <code>FoldingIOException</code>
98.1405 -</summary>
98.1406 - <date day="9" month="3" year="2000"/>
98.1407 - <compatibility modification="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" addition="no" deletion="no"/>
98.1408 - <description>
98.1409 - Now extends <code>FoldingIOException</code>, meaning that it should
98.1410 - delegate the detail message, etc. to the original.
98.1411 - </description>
98.1412 - <class package="org.openide.util.io" name="SafeException"/>
98.1413 - </change>
98.1414 - <change id="created-XMLUtil">
98.1415 - <api name="xml"/>
98.1416 - <summary>Independent XML API created</summary>
98.1417 - <date day="3" month="3" year="2001"/>
98.1418 - <author login="pkuzel"/>
98.1419 - <compatibility addition="yes" deprecation="yes" binary="compatible" source="compatible" semantic="compatible" deletion="no" modification="no"/>
98.1420 - <description>
98.1421 - <code>XMLUtil</code> utility class introduced. The class provides set of
98.1422 - static methods useful for XML processing. <code>EntityCatalog</code>
98.1423 - class introduced. It provides access to entity mapping registrations
98.1424 - provided by installed modules.
98.1425 - </description>
98.1426 - <class package="org.openide.xml" name="XMLUtil"/>
98.1427 - <class package="org.openide.xml" name="EntityCatalog"/>
98.1428 - <package name="org.openide.xml"/>
98.1429 - </change>
98.1430 - <change id="XMLUtil-1.29">
98.1431 - <api name="xml"/>
98.1432 - <summary>XML attribute and hexadecimal utilities added</summary>
98.1433 - <version major="1" minor="29"/>
98.1434 - <date day="8" month="8" year="2001"/>
98.1435 - <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
98.1436 - <description>
98.1437 - <code>toAttribute(String, char, boolean)</code>, <code>toContent(String,
98.1438 - boolean)</code>, <code>toHex(byte[], int, int)</code> and
98.1439 - <code>fromHex(char[], int, int)</code> methods added.
98.1440 - </description>
98.1441 - <class package="org.openide.xml" name="XMLUtil"/>
98.1442 - </change>
98.1443 - <change>
98.1444 - <api name="xml"/>
98.1445 - <summary>XML attribute and hexadecimal utilities modified</summary>
98.1446 - <version major="1" minor="40"/>
98.1447 - <date day="18" month="10" year="2001"/>
98.1448 - <compatibility binary="incompatible" source="incompatible" modification="yes" semantic="compatible" deprecation="no" addition="no" deletion="no">
98.1449 - The original versions of these methods were not in any public release.
98.1450 - </compatibility>
98.1451 - <description>
98.1452 - <code>toAttribute(String, char, boolean)</code> method replaced by
98.1453 - <code>toAttributeValue(String)</code>
98.1454 - and
98.1455 - <code>toContent(String, boolean)</code> method replaced by
98.1456 - <code>toElementContent(String)</code>. These new simplified
98.1457 - signatures and particular semantics should cover 99% usage of
98.1458 - previous ones. See the original <a href="#XMLUtil-1.29" shape="rect">additions</a>.
98.1459 - </description>
98.1460 - <class package="org.openide.xml" name="XMLUtil"/>
98.1461 - <issue number="16629"/>
98.1462 - </change>
98.1463 -</changes>
98.1464 -<htmlcontents>
98.1465 -<head>
98.1466 -<title>Change History for the Utilities API</title>
98.1467 -<link rel="stylesheet" href="prose.css" type="text/css"/>
98.1468 -</head>
98.1469 -<body>
98.1470 -<p class="overviewlink">
98.1471 -<a href="overview-summary.html">Overview</a>
98.1472 -</p>
98.1473 -<h1>Introduction</h1>
98.1474 -<h2>What do the Dates Mean?</h2>
98.1475 -<p>The supplied dates indicate when the API change was made, on the CVS
98.1476 -trunk. From this you can generally tell whether the change should be
98.1477 -present in a given build or not; for trunk builds, simply whether it
98.1478 -was made before or after the change; for builds on a stabilization
98.1479 -branch, whether the branch was made before or after the given date. In
98.1480 -some cases corresponding API changes have been made both in the trunk
98.1481 -and in an in-progress stabilization branch, if they were needed for a
98.1482 -bug fix; this ought to be marked in this list.</p>
98.1483 -<ul>
98.1484 -<li>The <code>release41</code> branch was made on Apr 03 '05 for use in the NetBeans 4.1 release.
98.1485 -Specification versions: 6.0 begins after this point.</li>
98.1486 -<li>The <code>release40</code> branch was made on Nov 01 '04 for use in the NetBeans 4.0 release.
98.1487 -Specification versions: 5.0 begins after this point.</li>
98.1488 -</ul>
98.1489 -<hr/>
98.1490 -<standard-changelists module-code-name="$codebase"/>
98.1491 -<hr/>
98.1492 -<p>@FOOTER@</p>
98.1493 -</body>
98.1494 -</htmlcontents>
98.1495 -</apichanges>
99.1 --- a/openide.util/manifest.mf Wed Jan 27 17:46:23 2010 -0500
99.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
99.3 @@ -1,5 +0,0 @@
99.4 -Manifest-Version: 1.0
99.5 -OpenIDE-Module: org.openide.util
99.6 -OpenIDE-Module-Localizing-Bundle: org/openide/util/Bundle.properties
99.7 -OpenIDE-Module-Specification-Version: 8.1
99.8 -
100.1 --- a/openide.util/nbproject/project.properties Wed Jan 27 17:46:23 2010 -0500
100.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
100.3 @@ -1,49 +0,0 @@
100.4 -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
100.5 -#
100.6 -# Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
100.7 -#
100.8 -# The contents of this file are subject to the terms of either the GNU
100.9 -# General Public License Version 2 only ("GPL") or the Common
100.10 -# Development and Distribution License("CDDL") (collectively, the
100.11 -# "License"). You may not use this file except in compliance with the
100.12 -# License. You can obtain a copy of the License at
100.13 -# http://www.netbeans.org/cddl-gplv2.html
100.14 -# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
100.15 -# specific language governing permissions and limitations under the
100.16 -# License. When distributing the software, include this License Header
100.17 -# Notice in each file and include the License file at
100.18 -# nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
100.19 -# particular file as subject to the "Classpath" exception as provided
100.20 -# by Sun in the GPL Version 2 section of the License file that
100.21 -# accompanied this code. If applicable, add the following below the
100.22 -# License Header, with the fields enclosed by brackets [] replaced by
100.23 -# your own identifying information:
100.24 -# "Portions Copyrighted [year] [name of copyright owner]"
100.25 -#
100.26 -# Contributor(s):
100.27 -#
100.28 -# The Original Software is NetBeans. The Initial Developer of the Original
100.29 -# Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
100.30 -# Microsystems, Inc. All Rights Reserved.
100.31 -#
100.32 -# If you wish your version of this file to be governed by only the CDDL
100.33 -# or only the GPL Version 2, indicate your decision by adding
100.34 -# "[Contributor] elects to include this software in this distribution
100.35 -# under the [CDDL or GPL Version 2] license." If you do not indicate a
100.36 -# single choice of license, a recipient has the option to distribute
100.37 -# your version of this file under either the CDDL, the GPL Version 2 or
100.38 -# to extend the choice of license to its licensees as provided above.
100.39 -# However, if you add GPL Version 2 code and therefore, elected the GPL
100.40 -# Version 2 license, then the option applies only if the new code is
100.41 -# made subject to such option by the copyright holder.
100.42 -
100.43 -javac.compilerargs=-Xlint -Xlint:-serial
100.44 -javac.source=1.6
100.45 -module.jar.dir=lib
100.46 -
100.47 -
100.48 -# For XMLSerializer, needed for XMLUtil.write to work w/ namespaces under JDK 1.4:
100.49 -
100.50 -javadoc.main.page=org/openide/util/doc-files/api.html
100.51 -javadoc.arch=${basedir}/arch.xml
100.52 -javadoc.apichanges=${basedir}/apichanges.xml
101.1 --- a/openide.util/nbproject/project.xml Wed Jan 27 17:46:23 2010 -0500
101.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
101.3 @@ -1,87 +0,0 @@
101.4 -<?xml version="1.0" encoding="UTF-8"?>
101.5 -<!--
101.6 -DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
101.7 -
101.8 -Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
101.9 -
101.10 -
101.11 -The contents of this file are subject to the terms of either the GNU
101.12 -General Public License Version 2 only ("GPL") or the Common
101.13 -Development and Distribution License("CDDL") (collectively, the
101.14 -"License"). You may not use this file except in compliance with the
101.15 -License. You can obtain a copy of the License at
101.16 -http://www.netbeans.org/cddl-gplv2.html
101.17 -or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
101.18 -specific language governing permissions and limitations under the
101.19 -License. When distributing the software, include this License Header
101.20 -Notice in each file and include the License file at
101.21 -nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
101.22 -particular file as subject to the "Classpath" exception as provided
101.23 -by Sun in the GPL Version 2 section of the License file that
101.24 -accompanied this code. If applicable, add the following below the
101.25 -License Header, with the fields enclosed by brackets [] replaced by
101.26 -your own identifying information:
101.27 -"Portions Copyrighted [year] [name of copyright owner]"
101.28 -
101.29 -Contributor(s):
101.30 -
101.31 -The Original Software is NetBeans. The Initial Developer of the Original
101.32 -Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
101.33 -Microsystems, Inc. All Rights Reserved.
101.34 -
101.35 -If you wish your version of this file to be governed by only the CDDL
101.36 -or only the GPL Version 2, indicate your decision by adding
101.37 -"[Contributor] elects to include this software in this distribution
101.38 -under the [CDDL or GPL Version 2] license." If you do not indicate a
101.39 -single choice of license, a recipient has the option to distribute
101.40 -your version of this file under either the CDDL, the GPL Version 2 or
101.41 -to extend the choice of license to its licensees as provided above.
101.42 -However, if you add GPL Version 2 code and therefore, elected the GPL
101.43 -Version 2 license, then the option applies only if the new code is
101.44 -made subject to such option by the copyright holder.
101.45 --->
101.46 -<project xmlns="http://www.netbeans.org/ns/project/1">
101.47 - <type>org.netbeans.modules.apisupport.project</type>
101.48 - <configuration>
101.49 - <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
101.50 - <code-name-base>org.openide.util</code-name-base>
101.51 - <module-dependencies>
101.52 - <dependency>
101.53 - <code-name-base>org.openide.util.lookup</code-name-base>
101.54 - <build-prerequisite/>
101.55 - <compile-dependency/>
101.56 - <run-dependency>
101.57 - <specification-version>8.1</specification-version>
101.58 - </run-dependency>
101.59 - </dependency>
101.60 - </module-dependencies>
101.61 - <test-dependencies>
101.62 - <test-type>
101.63 - <name>unit</name>
101.64 - <test-dependency>
101.65 - <code-name-base>org.netbeans.libs.junit4</code-name-base>
101.66 - <compile-dependency/>
101.67 - </test-dependency>
101.68 - <test-dependency>
101.69 - <code-name-base>org.netbeans.modules.nbjunit</code-name-base>
101.70 - <recursive/>
101.71 - <compile-dependency/>
101.72 - </test-dependency>
101.73 - <test-dependency>
101.74 - <code-name-base>org.openide.util.lookup</code-name-base>
101.75 - <compile-dependency/>
101.76 - <test/>
101.77 - </test-dependency>
101.78 - </test-type>
101.79 - </test-dependencies>
101.80 - <public-packages>
101.81 - <package>org.openide</package>
101.82 - <package>org.openide.util</package>
101.83 - <package>org.openide.util.actions</package>
101.84 - <package>org.openide.util.datatransfer</package>
101.85 - <package>org.openide.util.io</package>
101.86 - <package>org.openide.xml</package>
101.87 - </public-packages>
101.88 - </data>
101.89 - </configuration>
101.90 -</project>
102.1 --- a/openide.util/src/org/netbeans/modules/openide/util/URLStreamHandlerRegistrationProcessor.java Wed Jan 27 17:46:23 2010 -0500
102.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
102.3 @@ -1,80 +0,0 @@
102.4 -/*
102.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
102.6 - *
102.7 - * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
102.8 - *
102.9 - * The contents of this file are subject to the terms of either the GNU
102.10 - * General Public License Version 2 only ("GPL") or the Common
102.11 - * Development and Distribution License("CDDL") (collectively, the
102.12 - * "License"). You may not use this file except in compliance with the
102.13 - * License. You can obtain a copy of the License at
102.14 - * http://www.netbeans.org/cddl-gplv2.html
102.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
102.16 - * specific language governing permissions and limitations under the
102.17 - * License. When distributing the software, include this License Header
102.18 - * Notice in each file and include the License file at
102.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
102.20 - * particular file as subject to the "Classpath" exception as provided
102.21 - * by Sun in the GPL Version 2 section of the License file that
102.22 - * accompanied this code. If applicable, add the following below the
102.23 - * License Header, with the fields enclosed by brackets [] replaced by
102.24 - * your own identifying information:
102.25 - * "Portions Copyrighted [year] [name of copyright owner]"
102.26 - *
102.27 - * If you wish your version of this file to be governed by only the CDDL
102.28 - * or only the GPL Version 2, indicate your decision by adding
102.29 - * "[Contributor] elects to include this software in this distribution
102.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
102.31 - * single choice of license, a recipient has the option to distribute
102.32 - * your version of this file under either the CDDL, the GPL Version 2 or
102.33 - * to extend the choice of license to its licensees as provided above.
102.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
102.35 - * Version 2 license, then the option applies only if the new code is
102.36 - * made subject to such option by the copyright holder.
102.37 - *
102.38 - * Contributor(s):
102.39 - *
102.40 - * Portions Copyrighted 2009 Sun Microsystems, Inc.
102.41 - */
102.42 -
102.43 -package org.netbeans.modules.openide.util;
102.44 -
102.45 -import java.net.URLStreamHandler;
102.46 -import java.util.Collections;
102.47 -import java.util.Set;
102.48 -import javax.annotation.processing.RoundEnvironment;
102.49 -import javax.annotation.processing.SupportedSourceVersion;
102.50 -import javax.lang.model.SourceVersion;
102.51 -import javax.lang.model.element.Element;
102.52 -import javax.lang.model.element.TypeElement;
102.53 -import javax.lang.model.type.TypeMirror;
102.54 -import org.openide.util.URLStreamHandlerRegistration;
102.55 -import org.openide.util.lookup.implspi.AbstractServiceProviderProcessor;
102.56 -
102.57 -@SupportedSourceVersion(SourceVersion.RELEASE_6)
102.58 -public class URLStreamHandlerRegistrationProcessor extends AbstractServiceProviderProcessor {
102.59 -
102.60 - public @Override Set<String> getSupportedAnnotationTypes() {
102.61 - return Collections.singleton(URLStreamHandlerRegistration.class.getCanonicalName());
102.62 - }
102.63 -
102.64 - public static final String REGISTRATION_PREFIX = "URLStreamHandler/"; // NOI18N
102.65 -
102.66 - /** public for ServiceLoader */
102.67 - public URLStreamHandlerRegistrationProcessor() {}
102.68 -
102.69 - protected boolean handleProcess(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
102.70 - for (Element el : roundEnv.getElementsAnnotatedWith(URLStreamHandlerRegistration.class)) {
102.71 - TypeElement clazz = (TypeElement) el;
102.72 - URLStreamHandlerRegistration r = clazz.getAnnotation(URLStreamHandlerRegistration.class);
102.73 - TypeMirror type = processingEnv.getTypeUtils().getDeclaredType(
102.74 - processingEnv.getElementUtils().getTypeElement(URLStreamHandler.class.getName()));
102.75 - for (String protocol : r.protocol()) {
102.76 - register(clazz, URLStreamHandlerRegistration.class, type,
102.77 - REGISTRATION_PREFIX + protocol, r.position(), new String[0]);
102.78 - }
102.79 - }
102.80 - return true;
102.81 - }
102.82 -
102.83 -}
103.1 --- a/openide.util/src/org/openide/util/Enumerations.java Wed Jan 27 17:46:23 2010 -0500
103.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
103.3 @@ -1,601 +0,0 @@
103.4 -/*
103.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
103.6 - *
103.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
103.8 - *
103.9 - * The contents of this file are subject to the terms of either the GNU
103.10 - * General Public License Version 2 only ("GPL") or the Common
103.11 - * Development and Distribution License("CDDL") (collectively, the
103.12 - * "License"). You may not use this file except in compliance with the
103.13 - * License. You can obtain a copy of the License at
103.14 - * http://www.netbeans.org/cddl-gplv2.html
103.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
103.16 - * specific language governing permissions and limitations under the
103.17 - * License. When distributing the software, include this License Header
103.18 - * Notice in each file and include the License file at
103.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
103.20 - * particular file as subject to the "Classpath" exception as provided
103.21 - * by Sun in the GPL Version 2 section of the License file that
103.22 - * accompanied this code. If applicable, add the following below the
103.23 - * License Header, with the fields enclosed by brackets [] replaced by
103.24 - * your own identifying information:
103.25 - * "Portions Copyrighted [year] [name of copyright owner]"
103.26 - *
103.27 - * Contributor(s):
103.28 - *
103.29 - * The Original Software is NetBeans. The Initial Developer of the Original
103.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
103.31 - * Microsystems, Inc. All Rights Reserved.
103.32 - *
103.33 - * If you wish your version of this file to be governed by only the CDDL
103.34 - * or only the GPL Version 2, indicate your decision by adding
103.35 - * "[Contributor] elects to include this software in this distribution
103.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
103.37 - * single choice of license, a recipient has the option to distribute
103.38 - * your version of this file under either the CDDL, the GPL Version 2 or
103.39 - * to extend the choice of license to its licensees as provided above.
103.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
103.41 - * Version 2 license, then the option applies only if the new code is
103.42 - * made subject to such option by the copyright holder.
103.43 - */
103.44 -
103.45 -package org.openide.util;
103.46 -
103.47 -import java.util.ArrayList;
103.48 -import java.util.Arrays;
103.49 -import java.util.Collection;
103.50 -import java.util.Collections;
103.51 -import java.util.Enumeration;
103.52 -import java.util.HashSet;
103.53 -import java.util.Iterator;
103.54 -import java.util.NoSuchElementException;
103.55 -import java.util.Set;
103.56 -
103.57 -/**
103.58 - * Factory methods for various types of {@link Enumeration}.
103.59 - * Allows composition of existing enumerations, filtering their contents, and/or modifying them.
103.60 - * All of this is designed to be done lazily, i.e. elements created on demand.
103.61 - * @since 4.37
103.62 - * @author Jaroslav Tulach
103.63 - * @see NbCollections#checkedEnumerationByFilter
103.64 - * @see NbCollections#iterable(Enumeration)
103.65 - */
103.66 -public final class Enumerations extends Object {
103.67 - /** No instances */
103.68 - private Enumerations() {
103.69 - }
103.70 -
103.71 - /**
103.72 - * An empty enumeration.
103.73 - * Always returns <code>false</code> from
103.74 - * <code>empty().hasMoreElements()</code> and throws <code>NoSuchElementException</code>
103.75 - * from <code>empty().nextElement()</code>.
103.76 - * @return the enumeration
103.77 - */
103.78 - public static final <T> Enumeration<T> empty() {
103.79 - Collection<T> emptyL = Collections.emptyList();
103.80 - return Collections.enumeration(emptyL);
103.81 - }
103.82 -
103.83 - /**
103.84 - * Creates an enumeration with one element.
103.85 - * @param obj the element to be present in the enumeration.
103.86 - * @return enumeration
103.87 - */
103.88 - public static <T> Enumeration<T> singleton(T obj) {
103.89 - return Collections.enumeration(Collections.singleton(obj));
103.90 - }
103.91 -
103.92 - /**
103.93 - * Concatenates the content of two enumerations into one.
103.94 - * Until the
103.95 - * end of <code>en1</code> is reached its elements are being served.
103.96 - * As soon as the <code>en1</code> has no more elements, the content
103.97 - * of <code>en2</code> is being returned.
103.98 - *
103.99 - * @param en1 first enumeration
103.100 - * @param en2 second enumeration
103.101 - * @return enumeration
103.102 - */
103.103 - public static <T> Enumeration<T> concat(Enumeration<? extends T> en1, Enumeration<? extends T> en2) {
103.104 - ArrayList<Enumeration<? extends T>> two = new ArrayList<Enumeration<? extends T>>();
103.105 - two.add(en1);
103.106 - two.add(en2);
103.107 - return new SeqEn<T>(Collections.enumeration(two));
103.108 - }
103.109 -
103.110 - /**
103.111 - * Concatenates the content of many enumerations.
103.112 - * The input value
103.113 - * is enumeration of Enumeration elements and the result is composed
103.114 - * all their content. Each of the provided enumeration is fully read
103.115 - * and their content returned before the next enumeration is asked for
103.116 - * their elements.
103.117 - *
103.118 - * @param enumOfEnums Enumeration of Enumeration elements
103.119 - * @return enumeration
103.120 - */
103.121 - public static <T> Enumeration<T> concat(Enumeration<? extends Enumeration<? extends T>> enumOfEnums) {
103.122 - return new SeqEn<T>(enumOfEnums);
103.123 - }
103.124 -
103.125 - /**
103.126 - * Filters the input enumeration to new one that should contain
103.127 - * each of the provided elements just once.
103.128 - * The elements are compared
103.129 - * using their default <code>equals</code> and <code>hashCode</code> methods.
103.130 - *
103.131 - * @param en enumeration to filter
103.132 - * @return enumeration without duplicated items
103.133 - */
103.134 - public static <T> Enumeration<T> removeDuplicates(Enumeration<T> en) {
103.135 - class RDupls implements Processor<T,T> {
103.136 - private Set<T> set = new HashSet<T>();
103.137 -
103.138 - public T process(T o, Collection<T> nothing) {
103.139 - return set.add(o) ? o : null;
103.140 - }
103.141 - }
103.142 -
103.143 - return filter(en, new RDupls());
103.144 - }
103.145 -
103.146 - /**
103.147 - * Returns an enumeration that iterates over provided array.
103.148 - * @param arr the array of object
103.149 - * @return enumeration of those objects
103.150 - */
103.151 - public static <T> Enumeration<T> array(T... arr) {
103.152 - return Collections.enumeration(Arrays.asList(arr));
103.153 - }
103.154 -
103.155 - /**
103.156 - * Removes all <code>null</code>s from the input enumeration.
103.157 - * @param en enumeration that can contain nulls
103.158 - * @return new enumeration without null values
103.159 - */
103.160 - public static <T> Enumeration<T> removeNulls(Enumeration<T> en) {
103.161 - return filter(en, new RNulls<T>());
103.162 - }
103.163 -
103.164 - /**
103.165 - * For each element of the input enumeration <code>en</code> asks the
103.166 - * {@link Processor} to provide a replacement.
103.167 - * The <code>toAdd</code> argument of the processor is always null.
103.168 - * <p>
103.169 - * Example to convert any objects into strings:
103.170 - * <pre>
103.171 - * Processor convertToString = new Processor() {
103.172 - * public Object process(Object obj, Collection alwaysNull) {
103.173 - * return obj.toString(); // converts to string
103.174 - * }
103.175 - * };
103.176 - * Enumeration strings = Enumerations.convert(elems, convertToString);
103.177 - * </pre>
103.178 - *
103.179 - * @param en enumeration of any objects
103.180 - * @param processor a callback processor for the elements (its toAdd arguments is always null)
103.181 - * @return new enumeration where all elements has been processed
103.182 - */
103.183 - public static <T,R> Enumeration<R> convert(Enumeration<? extends T> en, Processor<T,R> processor) {
103.184 - return new AltEn<T,R>(en, processor);
103.185 - }
103.186 -
103.187 - /**
103.188 - * Filters some elements out from the input enumeration.
103.189 - * Just make the
103.190 - * {@link Processor} return <code>null</code>. Please notice the <code>toAdd</code>
103.191 - * argument of the processor is always <code>null</code>.
103.192 - * <p>
103.193 - * Example to remove all objects that are not strings:
103.194 - * <pre>
103.195 - * Processor onlyString = new Processor() {
103.196 - * public Object process(Object obj, Collection alwaysNull) {
103.197 - * if (obj instanceof String) {
103.198 - * return obj;
103.199 - * } else {
103.200 - * return null;
103.201 - * }
103.202 - * }
103.203 - * };
103.204 - * Enumeration strings = Enumerations.filter(elems, onlyString);
103.205 - * </pre>
103.206 - *
103.207 - * @param en enumeration of any objects
103.208 - * @param filter a callback processor for the elements (its toAdd arguments is always null)
103.209 - * @return new enumeration which does not include non-processed (returned null from processor) elements
103.210 - * @see NbCollections#checkedEnumerationByFilter
103.211 - */
103.212 - public static <T,R> Enumeration<R> filter(Enumeration<? extends T> en, Processor<T,R> filter) {
103.213 - Parameters.notNull("en", en);
103.214 - Parameters.notNull("filter", filter);
103.215 - return new FilEn<T,R>(en, filter);
103.216 - }
103.217 -
103.218 - /**
103.219 - * Support for breadth-first enumerating.
103.220 - * Before any element is returned
103.221 - * for the resulting enumeration it is processed in the {@link Processor} and
103.222 - * the processor is allowed to modify it and also add additional elements
103.223 - * at the (current) end of the <q>queue</q> by calling <code>toAdd.add</code>
103.224 - * or <code>toAdd.addAll</code>. No other methods can be called on the
103.225 - * provided <code>toAdd</code> collection.
103.226 - * <p>
103.227 - * Example of doing breadth-first walk through a tree:
103.228 - * <pre>
103.229 - * Processor queueSubnodes = new Processor() {
103.230 - * public Object process(Object obj, Collection toAdd) {
103.231 - * Node n = (Node)obj;
103.232 - * toAdd.addAll (n.getChildrenList());
103.233 - * return n;
103.234 - * }
103.235 - * };
103.236 - * Enumeration strings = Enumerations.queue(elems, queueSubnodes);
103.237 - * </pre>
103.238 - *
103.239 - * @param en initial content of the resulting enumeration
103.240 - * @param filter the processor that is called for each element and can
103.241 - * add and addAll elements to its toAdd Collection argument and
103.242 - * also change the value to be returned
103.243 - * @return enumeration with the initial and queued content (it can contain
103.244 - * <code>null</code> if the filter returned <code>null</code> from its
103.245 - * {@link Processor#process} method.
103.246 - */
103.247 - public static <T,R> Enumeration<R> queue(Enumeration<? extends T> en, Processor<T,R> filter) {
103.248 - QEn<T,R> q = new QEn<T,R>(filter);
103.249 -
103.250 - while (en.hasMoreElements()) {
103.251 - q.put(en.nextElement());
103.252 - }
103.253 -
103.254 - return q;
103.255 - }
103.256 -
103.257 - /**
103.258 - * Processor interface that can filter out objects from the enumeration,
103.259 - * change them or add aditional objects to the end of the current enumeration.
103.260 - */
103.261 - public static interface Processor<T,R> {
103.262 - /** @param original the object that is going to be returned from the enumeration right now
103.263 - * @return a replacement for this object
103.264 - * @param toAdd can be non-null if one can add new objects at the end of the enumeration
103.265 - */
103.266 - public R process(T original, Collection<T> toAdd);
103.267 - }
103.268 -
103.269 - /** Altering enumeration implementation */
103.270 - private static final class AltEn<T,R> extends Object implements Enumeration<R> {
103.271 - /** enumeration to filter */
103.272 - private Enumeration<? extends T> en;
103.273 -
103.274 - /** map to alter */
103.275 - private Processor<T,R> process;
103.276 -
103.277 - /**
103.278 - * @param en enumeration to filter
103.279 - */
103.280 - public AltEn(Enumeration<? extends T> en, Processor<T,R> process) {
103.281 - this.en = en;
103.282 - this.process = process;
103.283 - }
103.284 -
103.285 - /** @return true if there is more elements in the enumeration
103.286 - */
103.287 - public boolean hasMoreElements() {
103.288 - return en.hasMoreElements();
103.289 - }
103.290 -
103.291 - /** @return next object in the enumeration
103.292 - * @exception NoSuchElementException can be thrown if there is no next object
103.293 - * in the enumeration
103.294 - */
103.295 - public R nextElement() {
103.296 - return process.process(en.nextElement(), null);
103.297 - }
103.298 - }
103.299 - // end of AltEn
103.300 -
103.301 - /** Sequence of enumerations */
103.302 - private static final class SeqEn<T> extends Object implements Enumeration<T> {
103.303 - /** enumeration of Enumerations */
103.304 - private Enumeration<? extends Enumeration<? extends T>> en;
103.305 -
103.306 - /** current enumeration */
103.307 - private Enumeration<? extends T> current;
103.308 -
103.309 - /** is {@link #current} up-to-date and has more elements?
103.310 - * The combination <CODE>current == null</CODE> and
103.311 - * <CODE>checked == true means there are no more elements
103.312 - * in this enumeration.
103.313 - */
103.314 - private boolean checked = false;
103.315 -
103.316 - /** Constructs new enumeration from already existing. The elements
103.317 - * of <CODE>en</CODE> should be also enumerations. The resulting
103.318 - * enumeration contains elements of such enumerations.
103.319 - *
103.320 - * @param en enumeration of Enumerations that should be sequenced
103.321 - */
103.322 - public SeqEn(Enumeration<? extends Enumeration <? extends T>> en) {
103.323 - this.en = en;
103.324 - }
103.325 -
103.326 - /** Ensures that current enumeration is set. If there aren't more
103.327 - * elements in the Enumerations, sets the field <CODE>current</CODE> to null.
103.328 - */
103.329 - private void ensureCurrent() {
103.330 - while ((current == null) || !current.hasMoreElements()) {
103.331 - if (en.hasMoreElements()) {
103.332 - current = en.nextElement();
103.333 - } else {
103.334 - // no next valid enumeration
103.335 - current = null;
103.336 -
103.337 - return;
103.338 - }
103.339 - }
103.340 - }
103.341 -
103.342 - /** @return true if we have more elements */
103.343 - public boolean hasMoreElements() {
103.344 - if (!checked) {
103.345 - ensureCurrent();
103.346 - checked = true;
103.347 - }
103.348 -
103.349 - return current != null;
103.350 - }
103.351 -
103.352 - /** @return next element
103.353 - * @exception NoSuchElementException if there is no next element
103.354 - */
103.355 - public T nextElement() {
103.356 - if (!checked) {
103.357 - ensureCurrent();
103.358 - }
103.359 -
103.360 - if (current != null) {
103.361 - checked = false;
103.362 -
103.363 - return current.nextElement();
103.364 - } else {
103.365 - checked = true;
103.366 - throw new java.util.NoSuchElementException();
103.367 - }
103.368 - }
103.369 - }
103.370 - // end of SeqEn
103.371 -
103.372 - /** QueueEnumeration
103.373 - */
103.374 - private static class QEn<T,R> extends Object implements Enumeration<R> {
103.375 - /** next object to be returned */
103.376 - private ListItem<T> next = null;
103.377 -
103.378 - /** last object in the queue */
103.379 - private ListItem<T> last = null;
103.380 -
103.381 - /** processor to use */
103.382 - private Processor<T,R> processor;
103.383 -
103.384 - public QEn(Processor<T,R> p) {
103.385 - this.processor = p;
103.386 - }
103.387 -
103.388 - /** Put adds new object to the end of queue.
103.389 - * @param o the object to add
103.390 - */
103.391 - public void put(T o) {
103.392 - if (last != null) {
103.393 - ListItem<T> li = new ListItem<T>(o);
103.394 - last.next = li;
103.395 - last = li;
103.396 - } else {
103.397 - next = last = new ListItem<T>(o);
103.398 - }
103.399 - }
103.400 -
103.401 - /** Adds array of objects into the queue.
103.402 - * @param arr array of objects to put into the queue
103.403 - */
103.404 - public void put(Collection<? extends T> arr) {
103.405 - for (T e : arr) {
103.406 - put(e);
103.407 - }
103.408 - }
103.409 -
103.410 - /** Is there any next object?
103.411 - * @return true if there is next object, false otherwise
103.412 - */
103.413 - public boolean hasMoreElements() {
103.414 - return next != null;
103.415 - }
103.416 -
103.417 - /** @return next object in enumeration
103.418 - * @exception NoSuchElementException if there is no next object
103.419 - */
103.420 - public R nextElement() {
103.421 - if (next == null) {
103.422 - throw new NoSuchElementException();
103.423 - }
103.424 -
103.425 - T res = next.object;
103.426 -
103.427 - if ((next = next.next) == null) {
103.428 - last = null;
103.429 - }
103.430 -
103.431 - ;
103.432 -
103.433 - ToAdd<T,R> toAdd = new ToAdd<T,R>(this);
103.434 - R out = processor.process(res, toAdd);
103.435 - toAdd.finish();
103.436 -
103.437 - return out;
103.438 - }
103.439 -
103.440 - /** item in linked list of Objects */
103.441 - private static final class ListItem<T> {
103.442 - T object;
103.443 - ListItem<T> next;
103.444 -
103.445 - /** @param o the object for this item */
103.446 - ListItem(T o) {
103.447 - object = o;
103.448 - }
103.449 - }
103.450 -
103.451 - /** Temporary collection that supports only add and addAll operations*/
103.452 - private static final class ToAdd<T,R> extends Object implements Collection<T> {
103.453 - private QEn<T,R> q;
103.454 -
103.455 - public ToAdd(QEn<T,R> q) {
103.456 - this.q = q;
103.457 - }
103.458 -
103.459 - public void finish() {
103.460 - this.q = null;
103.461 - }
103.462 -
103.463 - public boolean add(T o) {
103.464 - q.put(o);
103.465 -
103.466 - return true;
103.467 - }
103.468 -
103.469 - public boolean addAll(Collection<? extends T> c) {
103.470 - q.put(c);
103.471 -
103.472 - return true;
103.473 - }
103.474 -
103.475 - private String msg() {
103.476 - return "Only add and addAll are implemented"; // NOI18N
103.477 - }
103.478 -
103.479 - public void clear() {
103.480 - throw new UnsupportedOperationException(msg());
103.481 - }
103.482 -
103.483 - public boolean contains(Object o) {
103.484 - throw new UnsupportedOperationException(msg());
103.485 - }
103.486 -
103.487 - public boolean containsAll(Collection c) {
103.488 - throw new UnsupportedOperationException(msg());
103.489 - }
103.490 -
103.491 - public boolean isEmpty() {
103.492 - throw new UnsupportedOperationException(msg());
103.493 - }
103.494 -
103.495 - public Iterator<T> iterator() {
103.496 - throw new UnsupportedOperationException(msg());
103.497 - }
103.498 -
103.499 - public boolean remove(Object o) {
103.500 - throw new UnsupportedOperationException(msg());
103.501 - }
103.502 -
103.503 - public boolean removeAll(Collection c) {
103.504 - throw new UnsupportedOperationException(msg());
103.505 - }
103.506 -
103.507 - public boolean retainAll(Collection c) {
103.508 - throw new UnsupportedOperationException(msg());
103.509 - }
103.510 -
103.511 - public int size() {
103.512 - throw new UnsupportedOperationException(msg());
103.513 - }
103.514 -
103.515 - public Object[] toArray() {
103.516 - throw new UnsupportedOperationException(msg());
103.517 - }
103.518 -
103.519 - public<X> X[] toArray(X[] a) {
103.520 - throw new UnsupportedOperationException(msg());
103.521 - }
103.522 - }
103.523 - // end of ToAdd
103.524 - }
103.525 - // end of QEn
103.526 -
103.527 - /** Filtering enumeration */
103.528 - private static final class FilEn<T,R> extends Object implements Enumeration<R> {
103.529 - /** marker object stating there is no nexte element prepared */
103.530 - private static final Object EMPTY = new Object();
103.531 -
103.532 - /** enumeration to filter */
103.533 - private Enumeration<? extends T> en;
103.534 -
103.535 - /** element to be returned next time or {@link #EMPTY} if there is
103.536 - * no such element prepared */
103.537 - private R next = empty();
103.538 -
103.539 - /** the set to use as filter */
103.540 - private Processor<T,R> filter;
103.541 -
103.542 - /**
103.543 - * @param en enumeration to filter
103.544 - */
103.545 - public FilEn(Enumeration<? extends T> en, Processor<T,R> filter) {
103.546 - this.en = en;
103.547 - this.filter = filter;
103.548 - }
103.549 -
103.550 - /** @return true if there is more elements in the enumeration
103.551 - */
103.552 - public boolean hasMoreElements() {
103.553 - if (next != empty()) {
103.554 - // there is a object already prepared
103.555 - return true;
103.556 - }
103.557 -
103.558 - while (en.hasMoreElements()) {
103.559 - // read next
103.560 - next = filter.process(en.nextElement(), null);
103.561 -
103.562 - if (next != null) {
103.563 - // if the object is accepted
103.564 - return true;
103.565 - }
103.566 -
103.567 - ;
103.568 - }
103.569 -
103.570 - next = empty();
103.571 -
103.572 - return false;
103.573 - }
103.574 -
103.575 - /** @return next object in the enumeration
103.576 - * @exception NoSuchElementException can be thrown if there is no next object
103.577 - * in the enumeration
103.578 - */
103.579 - public R nextElement() {
103.580 - if ((next == EMPTY) && !hasMoreElements()) {
103.581 - throw new NoSuchElementException();
103.582 - }
103.583 -
103.584 - R res = next;
103.585 - next = empty();
103.586 -
103.587 - return res;
103.588 - }
103.589 -
103.590 - @SuppressWarnings("unchecked")
103.591 - private R empty() {
103.592 - return (R)EMPTY;
103.593 - }
103.594 - }
103.595 - // end of FilEn
103.596 -
103.597 - /** Returns true from contains if object is not null */
103.598 - private static class RNulls<T> implements Processor<T,T> {
103.599 - public T process(T original, Collection<T> toAdd) {
103.600 - return original;
103.601 - }
103.602 - }
103.603 - // end of RNulls
103.604 -}
104.1 --- a/openide.util/src/org/openide/util/NbPreferences.java Wed Jan 27 17:46:23 2010 -0500
104.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
104.3 @@ -1,140 +0,0 @@
104.4 -/*
104.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
104.6 - *
104.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
104.8 - *
104.9 - * The contents of this file are subject to the terms of either the GNU
104.10 - * General Public License Version 2 only ("GPL") or the Common
104.11 - * Development and Distribution License("CDDL") (collectively, the
104.12 - * "License"). You may not use this file except in compliance with the
104.13 - * License. You can obtain a copy of the License at
104.14 - * http://www.netbeans.org/cddl-gplv2.html
104.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
104.16 - * specific language governing permissions and limitations under the
104.17 - * License. When distributing the software, include this License Header
104.18 - * Notice in each file and include the License file at
104.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
104.20 - * particular file as subject to the "Classpath" exception as provided
104.21 - * by Sun in the GPL Version 2 section of the License file that
104.22 - * accompanied this code. If applicable, add the following below the
104.23 - * License Header, with the fields enclosed by brackets [] replaced by
104.24 - * your own identifying information:
104.25 - * "Portions Copyrighted [year] [name of copyright owner]"
104.26 - *
104.27 - * Contributor(s):
104.28 - *
104.29 - * The Original Software is NetBeans. The Initial Developer of the Original
104.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
104.31 - * Microsystems, Inc. All Rights Reserved.
104.32 - *
104.33 - * If you wish your version of this file to be governed by only the CDDL
104.34 - * or only the GPL Version 2, indicate your decision by adding
104.35 - * "[Contributor] elects to include this software in this distribution
104.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
104.37 - * single choice of license, a recipient has the option to distribute
104.38 - * your version of this file under either the CDDL, the GPL Version 2 or
104.39 - * to extend the choice of license to its licensees as provided above.
104.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
104.41 - * Version 2 license, then the option applies only if the new code is
104.42 - * made subject to such option by the copyright holder.
104.43 - */
104.44 -
104.45 -package org.openide.util;
104.46 -
104.47 -import java.io.ByteArrayOutputStream;
104.48 -import java.io.PrintStream;
104.49 -import java.util.logging.Level;
104.50 -import java.util.logging.Logger;
104.51 -import java.util.prefs.Preferences;
104.52 -
104.53 -/**
104.54 - * Provides an implementation of the Preferences API which may be backed by
104.55 - * a NetBeans-specific implementation.
104.56 - * @see <a href="doc-files/preferences.html">Preferences API in NetBeans</a>
104.57 - * @since org.openide.util 7.4
104.58 - * @author Radek Matous
104.59 - */
104.60 -public final class NbPreferences {
104.61 - private static Provider PREFS_IMPL;
104.62 -
104.63 - private NbPreferences() {}
104.64 -
104.65 - /**
104.66 - * Returns user preference node . {@link Preferences#absolutePath} of such
104.67 - * a node depends whether class provided as a parameter was loaded as a part of any module
104.68 - * or not. If so, then absolute path corresponds to slashified code name base of module.
104.69 - * If not, then absolute path corresponds to class's package.
104.70 - *
104.71 - * @param cls the class for which a user preference node is desired.
104.72 - * @return the user preference node
104.73 - */
104.74 - public static Preferences forModule(Class cls) {
104.75 - if (PREFS_IMPL == null) {
104.76 - PREFS_IMPL = getPreferencesProvider();
104.77 - }
104.78 - return PREFS_IMPL.preferencesForModule(cls);
104.79 - }
104.80 -
104.81 - /**
104.82 - * Returns the root preference node.
104.83 - *
104.84 - * @return the root preference node.
104.85 - */
104.86 - public static Preferences root() {
104.87 - if (PREFS_IMPL == null) {
104.88 - PREFS_IMPL = getPreferencesProvider();
104.89 - }
104.90 - return PREFS_IMPL.preferencesRoot();
104.91 - }
104.92 -
104.93 - private static Provider getPreferencesProvider() {
104.94 - Provider retval = Lookup.getDefault().lookup(Provider.class);
104.95 - if (retval == null) {
104.96 - retval = new Provider() {
104.97 - public Preferences preferencesForModule(Class cls) {
104.98 - return Preferences.userNodeForPackage(cls);
104.99 - }
104.100 -
104.101 - public Preferences preferencesRoot() {
104.102 - return Preferences.userRoot();
104.103 - }
104.104 - };
104.105 - // Avoided warning in case it is set
104.106 - //(e.g. from NbTestCase - org.netbeans.junit.internal.MemoryPreferencesFactory).
104.107 - String prefsFactory = System.getProperty("java.util.prefs.PreferencesFactory");//NOI18N
104.108 - if (!"org.netbeans.junit.internal.MemoryPreferencesFactory".equals(prefsFactory)) {//NOI18N
104.109 - Logger logger = Logger.getLogger(NbPreferences.class.getName());
104.110 - ByteArrayOutputStream bos = new ByteArrayOutputStream();
104.111 - new Exception().printStackTrace(new PrintStream(bos));
104.112 - logger.log(prefsFactory == null ? Level.WARNING : Level.FINE,
104.113 - "NetBeans implementation of Preferences not found: " + bos.toString() );//NOI18N
104.114 - }
104.115 - }
104.116 - return retval;
104.117 - }
104.118 -
104.119 - /**
104.120 - * Implementation of {@link NbPreferences} methods.
104.121 - * Not intended for use outside the NetBeans Platform.
104.122 - * @since org.openide.util 8.1
104.123 - */
104.124 - public interface Provider {
104.125 - /**
104.126 - * Returns user preference node. {@link Preferences#absolutePath} of such
104.127 - * a node depends whether class provided as a parameter was loaded as a part of any module
104.128 - * or not. If so, then absolute path corresponds to slashified code name base of module.
104.129 - * If not, then absolute path corresponds to class's package.
104.130 - *
104.131 - * @param cls the class for which a user preference node is desired.
104.132 - * @return the user preference node
104.133 - */
104.134 - Preferences preferencesForModule(Class cls);
104.135 - /**
104.136 - * Returns the root preference node.
104.137 - *
104.138 - * @return the root preference node.
104.139 - */
104.140 - Preferences preferencesRoot();
104.141 - }
104.142 -
104.143 -}
105.1 --- a/openide.util/src/org/openide/util/Utilities.java Wed Jan 27 17:46:23 2010 -0500
105.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
105.3 @@ -1,3115 +0,0 @@
105.4 -/*
105.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
105.6 - *
105.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
105.8 - *
105.9 - * The contents of this file are subject to the terms of either the GNU
105.10 - * General Public License Version 2 only ("GPL") or the Common
105.11 - * Development and Distribution License("CDDL") (collectively, the
105.12 - * "License"). You may not use this file except in compliance with the
105.13 - * License. You can obtain a copy of the License at
105.14 - * http://www.netbeans.org/cddl-gplv2.html
105.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
105.16 - * specific language governing permissions and limitations under the
105.17 - * License. When distributing the software, include this License Header
105.18 - * Notice in each file and include the License file at
105.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
105.20 - * particular file as subject to the "Classpath" exception as provided
105.21 - * by Sun in the GPL Version 2 section of the License file that
105.22 - * accompanied this code. If applicable, add the following below the
105.23 - * License Header, with the fields enclosed by brackets [] replaced by
105.24 - * your own identifying information:
105.25 - * "Portions Copyrighted [year] [name of copyright owner]"
105.26 - *
105.27 - * Contributor(s):
105.28 - *
105.29 - * The Original Software is NetBeans. The Initial Developer of the Original
105.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
105.31 - * Microsystems, Inc. All Rights Reserved.
105.32 - *
105.33 - * If you wish your version of this file to be governed by only the CDDL
105.34 - * or only the GPL Version 2, indicate your decision by adding
105.35 - * "[Contributor] elects to include this software in this distribution
105.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
105.37 - * single choice of license, a recipient has the option to distribute
105.38 - * your version of this file under either the CDDL, the GPL Version 2 or
105.39 - * to extend the choice of license to its licensees as provided above.
105.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
105.41 - * Version 2 license, then the option applies only if the new code is
105.42 - * made subject to such option by the copyright holder.
105.43 - */
105.44 -
105.45 -package org.openide.util;
105.46 -
105.47 -import java.awt.BorderLayout;
105.48 -import java.awt.Component;
105.49 -import java.awt.Container;
105.50 -import java.awt.Cursor;
105.51 -import java.awt.Dialog;
105.52 -import java.awt.Dimension;
105.53 -import java.awt.Event;
105.54 -import java.awt.Frame;
105.55 -import java.awt.GraphicsConfiguration;
105.56 -import java.awt.GraphicsEnvironment;
105.57 -import java.awt.Image;
105.58 -import java.awt.Insets;
105.59 -import java.awt.KeyboardFocusManager;
105.60 -import java.awt.Point;
105.61 -import java.awt.Rectangle;
105.62 -import java.awt.Toolkit;
105.63 -import java.awt.Window;
105.64 -import java.awt.event.ActionEvent;
105.65 -import java.awt.event.ActionListener;
105.66 -import java.awt.event.KeyEvent;
105.67 -import java.io.BufferedReader;
105.68 -import java.io.File;
105.69 -import java.io.IOException;
105.70 -import java.io.InputStreamReader;
105.71 -import java.lang.ref.Reference;
105.72 -import java.lang.ref.ReferenceQueue;
105.73 -import java.lang.ref.SoftReference;
105.74 -import java.lang.reflect.Field;
105.75 -import java.lang.reflect.Method;
105.76 -import java.lang.reflect.Modifier;
105.77 -import java.net.MalformedURLException;
105.78 -import java.net.URI;
105.79 -import java.net.URISyntaxException;
105.80 -import java.net.URL;
105.81 -import java.text.BreakIterator;
105.82 -import java.util.ArrayList;
105.83 -import java.util.Arrays;
105.84 -import java.util.Collection;
105.85 -import java.util.Collections;
105.86 -import java.util.Comparator;
105.87 -import java.util.Enumeration;
105.88 -import java.util.HashMap;
105.89 -import java.util.HashSet;
105.90 -import java.util.Iterator;
105.91 -import java.util.LinkedList;
105.92 -import java.util.List;
105.93 -import java.util.Locale;
105.94 -import java.util.Map;
105.95 -import java.util.NoSuchElementException;
105.96 -import java.util.Set;
105.97 -import java.util.StringTokenizer;
105.98 -import java.util.TreeSet;
105.99 -import java.util.Vector;
105.100 -import java.util.logging.Level;
105.101 -import java.util.logging.Logger;
105.102 -import javax.swing.Action;
105.103 -import javax.swing.Icon;
105.104 -import javax.swing.JMenuItem;
105.105 -import javax.swing.JPopupMenu;
105.106 -import javax.swing.JSeparator;
105.107 -import javax.swing.KeyStroke;
105.108 -import javax.swing.SwingUtilities;
105.109 -import javax.swing.Timer;
105.110 -import org.openide.util.actions.Presenter;
105.111 -import org.openide.util.lookup.Lookups;
105.112 -import org.openide.util.lookup.implspi.ActiveQueue;
105.113 -import org.openide.util.actions.ActionPresenterProvider;
105.114 -
105.115 -/** Otherwise uncategorized useful static methods.
105.116 -*
105.117 -* @author Jan Palka, Ian Formanek, Jaroslav Tulach
105.118 -*/
105.119 -public final class Utilities {
105.120 -
105.121 - private static final Logger LOG = Logger.getLogger(Utilities.class.getName());
105.122 -
105.123 - /** Operating system is Windows NT. */
105.124 - public static final int OS_WINNT = 1 << 0;
105.125 -
105.126 - /** Operating system is Windows 95. */
105.127 - public static final int OS_WIN95 = OS_WINNT << 1;
105.128 -
105.129 - /** Operating system is Windows 98. */
105.130 - public static final int OS_WIN98 = OS_WIN95 << 1;
105.131 -
105.132 - /** Operating system is Solaris. */
105.133 - public static final int OS_SOLARIS = OS_WIN98 << 1;
105.134 -
105.135 - /** Operating system is Linux. */
105.136 - public static final int OS_LINUX = OS_SOLARIS << 1;
105.137 -
105.138 - /** Operating system is HP-UX. */
105.139 - public static final int OS_HP = OS_LINUX << 1;
105.140 -
105.141 - /** Operating system is IBM AIX. */
105.142 - public static final int OS_AIX = OS_HP << 1;
105.143 -
105.144 - /** Operating system is SGI IRIX. */
105.145 - public static final int OS_IRIX = OS_AIX << 1;
105.146 -
105.147 - /** Operating system is Sun OS. */
105.148 - public static final int OS_SUNOS = OS_IRIX << 1;
105.149 -
105.150 - /** Operating system is Compaq TRU64 Unix */
105.151 - public static final int OS_TRU64 = OS_SUNOS << 1;
105.152 -
105.153 - /** @deprecated please use OS_TRU64 instead */
105.154 - @Deprecated
105.155 - public static final int OS_DEC = OS_TRU64 << 1;
105.156 -
105.157 - /** Operating system is OS/2. */
105.158 - public static final int OS_OS2 = OS_DEC << 1;
105.159 -
105.160 - /** Operating system is Mac. */
105.161 - public static final int OS_MAC = OS_OS2 << 1;
105.162 -
105.163 - /** Operating system is Windows 2000. */
105.164 - public static final int OS_WIN2000 = OS_MAC << 1;
105.165 -
105.166 - /** Operating system is Compaq OpenVMS */
105.167 - public static final int OS_VMS = OS_WIN2000 << 1;
105.168 -
105.169 - /**
105.170 - *Operating system is one of the Windows variants but we don't know which
105.171 - *one it is
105.172 - */
105.173 - public static final int OS_WIN_OTHER = OS_VMS << 1;
105.174 -
105.175 - /** Operating system is unknown. */
105.176 - public static final int OS_OTHER = OS_WIN_OTHER << 1;
105.177 -
105.178 - /** Operating system is FreeBSD
105.179 - * @since 4.50
105.180 - */
105.181 - public static final int OS_FREEBSD = OS_OTHER << 1;
105.182 -
105.183 - /** Operating system is Windows Vista.
105.184 - * @since 7.17
105.185 - */
105.186 - public static final int OS_WINVISTA = OS_FREEBSD << 1;
105.187 -
105.188 - /** Operating system is one of the Unix variants but we don't know which
105.189 - * one it is.
105.190 - * @since 7.18
105.191 - */
105.192 - public static final int OS_UNIX_OTHER = OS_WINVISTA << 1;
105.193 -
105.194 - /** Operating system is OpenBSD.
105.195 - * @since 7.18
105.196 - */
105.197 - public static final int OS_OPENBSD = OS_UNIX_OTHER << 1;
105.198 -
105.199 - /** A mask for Windows platforms.
105.200 - * @deprecated Use {@link #isWindows()} instead.
105.201 - */
105.202 - @Deprecated
105.203 - public static final int OS_WINDOWS_MASK = OS_WINNT | OS_WIN95 | OS_WIN98 | OS_WIN2000 | OS_WINVISTA | OS_WIN_OTHER;
105.204 -
105.205 - /** A mask for Unix platforms.
105.206 - * @deprecated Use {@link #isUnix()} instead.
105.207 - */
105.208 - @Deprecated
105.209 - public static final int OS_UNIX_MASK = OS_SOLARIS | OS_LINUX | OS_HP | OS_AIX | OS_IRIX | OS_SUNOS | OS_TRU64 |
105.210 - OS_MAC | OS_FREEBSD | OS_OPENBSD | OS_UNIX_OTHER;
105.211 -
105.212 - /** A height of the windows's taskbar */
105.213 - public static final int TYPICAL_WINDOWS_TASKBAR_HEIGHT = 27;
105.214 -
105.215 - /** A height of the Mac OS X's menu */
105.216 - private static final int TYPICAL_MACOSX_MENU_HEIGHT = 24;
105.217 -
105.218 - /** The operating system on which NetBeans runs*/
105.219 - private static int operatingSystem = -1;
105.220 - private static final String[] keywords = new String[] {
105.221 -
105.222 - //If adding to this, insert in alphabetical order!
105.223 - "abstract", "assert", "boolean", "break", "byte", "case", //NOI18N
105.224 - "catch", "char", "class", "const", "continue", "default", //NOI18N
105.225 - "do", "double", "else", "enum", "extends", "false", "final", //NOI18N
105.226 - "finally", "float", "for", "goto", "if", "implements", //NOI18N
105.227 - "import", "instanceof", "int", "interface", "long", //NOI18N
105.228 - "native", "new", "null", "package", "private", //NOI18N
105.229 - "protected", "public", "return", "short", "static", //NOI18N
105.230 - "strictfp", "super", "switch", "synchronized", "this", //NOI18N
105.231 - "throw", "throws", "transient", "true", "try", "void", //NOI18N
105.232 - "volatile", "while" //NOI18N
105.233 - };
105.234 - private static Timer clearIntrospector;
105.235 - private static ActionListener doClear;
105.236 - private static final int CTRL_WILDCARD_MASK = 32768;
105.237 - private static final int ALT_WILDCARD_MASK = CTRL_WILDCARD_MASK * 2;
105.238 -
105.239 - // Package retranslation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
105.240 - private static final String TRANS_LOCK = "TRANS_LOCK";
105.241 -
105.242 - /** last used classloader or if run in test mode the TRANS_LOCK */
105.243 - private static Object transLoader;
105.244 -
105.245 - /** regular expression to with all changes */
105.246 - private static RE transExp;
105.247 -
105.248 - //
105.249 - // Support for work with actions
105.250 - //
105.251 -
105.252 - /** the found actionsGlobalContext */
105.253 - private static Lookup global;
105.254 -
105.255 - private Utilities() {
105.256 - }
105.257 -
105.258 - /**
105.259 - * Useful queue for all parts of system that use <code>java.lang.ref.Reference</code>s
105.260 - * together with some <code>ReferenceQueue</code> and need to do some clean up
105.261 - * when the reference is enqueued. Usually, in order to be notified about that, one
105.262 - * needs to either create a dedicated thread that blocks on the queue and is
105.263 - * <code>Object.notify</code>-ed, which is the right approach but consumes
105.264 - * valuable system resources (threads) or one can periodically check the content
105.265 - * of the queue by <code>RequestProcessor.Task.schedule</code> which is
105.266 - * completely wrong, because it wakes up the system every (say) 15 seconds.
105.267 - * In order to provide useful support for this problem, this queue has been
105.268 - * provided.
105.269 - * <P>
105.270 - * If you have a reference that needs cleanup, make it implement <link>Runnable</link>
105.271 - * and register it with the queue:
105.272 - * <PRE>
105.273 - * class MyReference extends WeakReference<Thing> implements Runnable {
105.274 - * private final OtherInfo dataToCleanUp;
105.275 - * public MyReference(Thing ref, OtherInfo data) {
105.276 - * super(ref, Utilities.queue());
105.277 - * dataToCleanUp = data;
105.278 - * }
105.279 - * public void run() {
105.280 - * dataToCleanUp.releaseOrWhateverYouNeed();
105.281 - * }
105.282 - * }
105.283 - * </PRE>
105.284 - * When the <code>ref</code> object is garbage collected, your run method
105.285 - * will be invoked by calling
105.286 - * <code>((Runnable) reference).run()</code>
105.287 - * and you can perform whatever cleanup is necessary. Be sure not to block
105.288 - * in such cleanup for a long time as this prevents other waiting references
105.289 - * from cleaning themselves up.
105.290 - * <P>
105.291 - * Do not call any <code>ReferenceQueue</code> methods. They
105.292 - * will throw exceptions. You may only enqueue a reference.
105.293 - * <p>
105.294 - * Be sure to call this method anew for each reference.
105.295 - * Do not attempt to cache the return value.
105.296 - * @since 3.11
105.297 - */
105.298 - public static ReferenceQueue<Object> activeReferenceQueue() {
105.299 - return ActiveQueue.queue();
105.300 - }
105.301 -
105.302 - /** Get the operating system on which NetBeans is running.
105.303 - * @return one of the <code>OS_*</code> constants (such as {@link #OS_WINNT})
105.304 - */
105.305 - public static final int getOperatingSystem() {
105.306 - if (operatingSystem == -1) {
105.307 - String osName = System.getProperty("os.name");
105.308 -
105.309 - if ("Windows NT".equals(osName)) { // NOI18N
105.310 - operatingSystem = OS_WINNT;
105.311 - } else if ("Windows 95".equals(osName)) { // NOI18N
105.312 - operatingSystem = OS_WIN95;
105.313 - } else if ("Windows 98".equals(osName)) { // NOI18N
105.314 - operatingSystem = OS_WIN98;
105.315 - } else if ("Windows 2000".equals(osName)) { // NOI18N
105.316 - operatingSystem = OS_WIN2000;
105.317 - } else if ("Windows Vista".equals(osName)) { // NOI18N
105.318 - operatingSystem = OS_WINVISTA;
105.319 - } else if (osName.startsWith("Windows ")) { // NOI18N
105.320 - operatingSystem = OS_WIN_OTHER;
105.321 - } else if ("Solaris".equals(osName)) { // NOI18N
105.322 - operatingSystem = OS_SOLARIS;
105.323 - } else if (osName.startsWith("SunOS")) { // NOI18N
105.324 - operatingSystem = OS_SOLARIS;
105.325 - }
105.326 - // JDK 1.4 b2 defines os.name for me as "Redhat Linux" -jglick
105.327 - else if (osName.endsWith("Linux")) { // NOI18N
105.328 - operatingSystem = OS_LINUX;
105.329 - } else if ("HP-UX".equals(osName)) { // NOI18N
105.330 - operatingSystem = OS_HP;
105.331 - } else if ("AIX".equals(osName)) { // NOI18N
105.332 - operatingSystem = OS_AIX;
105.333 - } else if ("Irix".equals(osName)) { // NOI18N
105.334 - operatingSystem = OS_IRIX;
105.335 - } else if ("SunOS".equals(osName)) { // NOI18N
105.336 - operatingSystem = OS_SUNOS;
105.337 - } else if ("Digital UNIX".equals(osName)) { // NOI18N
105.338 - operatingSystem = OS_TRU64;
105.339 - } else if ("OS/2".equals(osName)) { // NOI18N
105.340 - operatingSystem = OS_OS2;
105.341 - } else if ("OpenVMS".equals(osName)) { // NOI18N
105.342 - operatingSystem = OS_VMS;
105.343 - } else if (osName.equals("Mac OS X")) { // NOI18N
105.344 - operatingSystem = OS_MAC;
105.345 - } else if (osName.startsWith("Darwin")) { // NOI18N
105.346 - operatingSystem = OS_MAC;
105.347 - } else if (osName.toLowerCase(Locale.US).startsWith("freebsd")) { // NOI18N
105.348 - operatingSystem = OS_FREEBSD;
105.349 - } else if ("OpenBSD".equals(osName)) { // NOI18N
105.350 - operatingSystem = OS_OPENBSD;
105.351 - } else if (File.pathSeparatorChar == ':') { // NOI18N
105.352 - operatingSystem = OS_UNIX_OTHER;
105.353 - } else {
105.354 - operatingSystem = OS_OTHER;
105.355 - }
105.356 - }
105.357 -
105.358 - return operatingSystem;
105.359 - }
105.360 -
105.361 - /** Test whether NetBeans is running on some variant of Windows.
105.362 - * @return <code>true</code> if Windows, <code>false</code> if some other manner of operating system
105.363 - */
105.364 - public static final boolean isWindows() {
105.365 - return (getOperatingSystem() & OS_WINDOWS_MASK) != 0;
105.366 - }
105.367 -
105.368 - /** Test whether NetBeans is running on MacOS.
105.369 - * @since 7.7
105.370 - * @return <code>true</code> if Mac, <code>false</code> if some other manner of operating system
105.371 - */
105.372 - public static final boolean isMac() {
105.373 - return (getOperatingSystem() & OS_MAC) != 0;
105.374 - }
105.375 -
105.376 - /** Test whether NetBeans is running on some variant of Unix.
105.377 - * Linux is included as well as the commercial vendors.
105.378 - * @return <code>true</code> some sort of Unix, <code>false</code> if some other manner of operating system
105.379 - */
105.380 - public static final boolean isUnix() {
105.381 - return (getOperatingSystem() & OS_UNIX_MASK) != 0;
105.382 - }
105.383 -
105.384 - // only for UtilitiesTest purposes
105.385 - final static void resetOperatingSystem() {
105.386 - operatingSystem = -1;
105.387 - }
105.388 -
105.389 - /** Test whether a given string is a valid Java identifier.
105.390 - * @param id string which should be checked
105.391 - * @return <code>true</code> if a valid identifier
105.392 - */
105.393 - public static final boolean isJavaIdentifier(String id) {
105.394 - if (id == null) {
105.395 - return false;
105.396 - }
105.397 -
105.398 - if (id.equals("")) {
105.399 - return false;
105.400 - }
105.401 -
105.402 - if (!(java.lang.Character.isJavaIdentifierStart(id.charAt(0)))) {
105.403 - return false;
105.404 - }
105.405 -
105.406 - for (int i = 1; i < id.length(); i++) {
105.407 - if (!(java.lang.Character.isJavaIdentifierPart(id.charAt(i)))) {
105.408 - return false;
105.409 - }
105.410 - }
105.411 -
105.412 - return Arrays.binarySearch(keywords, id) < 0;
105.413 - }
105.414 -
105.415 - /** Central method for obtaining <code>BeanInfo</code> for potential JavaBean classes.
105.416 - * @param clazz class of the bean to provide the <code>BeanInfo</code> for
105.417 - * @return the bean info
105.418 - * @throws java.beans.IntrospectionException for the usual reasons
105.419 - * @see java.beans.Introspector#getBeanInfo(Class)
105.420 - */
105.421 - public static java.beans.BeanInfo getBeanInfo(Class clazz)
105.422 - throws java.beans.IntrospectionException {
105.423 - java.beans.BeanInfo bi;
105.424 -
105.425 - try {
105.426 - bi = java.beans.Introspector.getBeanInfo(clazz);
105.427 - } catch (java.beans.IntrospectionException ie) {
105.428 - Exceptions.attachMessage(ie,
105.429 - "Encountered while introspecting " +
105.430 - clazz.getName()); // NOI18N
105.431 - throw ie;
105.432 - } catch (Error e) {
105.433 - // Could be a bug in Introspector triggered by NB code.
105.434 - Exceptions.attachMessage(e,
105.435 - "Encountered while introspecting " +
105.436 - clazz.getName()); // NOI18N
105.437 - throw e;
105.438 - }
105.439 -
105.440 - if (java.awt.Component.class.isAssignableFrom(clazz)) {
105.441 - java.beans.PropertyDescriptor[] pds = bi.getPropertyDescriptors();
105.442 -
105.443 - for (int i = 0; i < pds.length; i++) {
105.444 - if (pds[i].getName().equals("cursor")) { // NOI18N
105.445 -
105.446 - try {
105.447 - Method getter = Component.class.getDeclaredMethod("getCursor", new Class[0]); // NOI18N
105.448 - Method setter = Component.class.getDeclaredMethod("setCursor", new Class[] { Cursor.class }); // NOI18N
105.449 - pds[i] = new java.beans.PropertyDescriptor("cursor", getter, setter); // NOI18N
105.450 - } catch (NoSuchMethodException e) {
105.451 - e.printStackTrace();
105.452 - }
105.453 -
105.454 - break;
105.455 - }
105.456 - }
105.457 - }
105.458 -
105.459 - // clears about 1000 instances of Method
105.460 - if (bi != null) {
105.461 - if (clearIntrospector == null) {
105.462 - doClear = new ActionListener() {
105.463 - public void actionPerformed(ActionEvent ev) {
105.464 - java.beans.Introspector.flushCaches();
105.465 - }
105.466 - };
105.467 - clearIntrospector = new Timer(15000, doClear);
105.468 - clearIntrospector.setRepeats(false);
105.469 - }
105.470 -
105.471 - clearIntrospector.restart();
105.472 - }
105.473 -
105.474 - return bi;
105.475 - }
105.476 -
105.477 - /** Central method for obtaining <code>BeanInfo</code> for potential JavaBean classes, with a stop class.
105.478 - * @param clazz class of the bean to provide the <code>BeanInfo</code> for
105.479 - * @param stopClass the stop class
105.480 - * @return the bean info
105.481 - * @throws java.beans.IntrospectionException for the usual reasons
105.482 - * @see java.beans.Introspector#getBeanInfo(Class, Class)
105.483 - */
105.484 - public static java.beans.BeanInfo getBeanInfo(Class clazz, Class stopClass)
105.485 - throws java.beans.IntrospectionException {
105.486 - return java.beans.Introspector.getBeanInfo(clazz, stopClass);
105.487 - }
105.488 -
105.489 - /** Wrap multi-line strings (and get the individual lines).
105.490 - * @param original the original string to wrap
105.491 - * @param width the maximum width of lines
105.492 - * @param wrapWords if <code>true</code>, the lines are wrapped on word boundaries (if possible);
105.493 - * if <code>false</code>, character boundaries are used
105.494 - * @param removeNewLines if <code>true</code>, any newlines in the original string are ignored
105.495 - * @return the lines after wrapping
105.496 - * @deprecated use {@link #wrapStringToArray(String, int, BreakIterator, boolean)} since it is better for I18N
105.497 - */
105.498 - @Deprecated
105.499 - public static String[] wrapStringToArray(String original, int width, boolean wrapWords, boolean removeNewLines) {
105.500 - BreakIterator bi = (wrapWords ? BreakIterator.getWordInstance() : BreakIterator.getCharacterInstance());
105.501 -
105.502 - return wrapStringToArray(original, width, bi, removeNewLines);
105.503 - }
105.504 -
105.505 - /** Wrap multi-line strings (and get the individual lines).
105.506 - * @param original the original string to wrap
105.507 - * @param width the maximum width of lines
105.508 - * @param breakIterator breaks original to chars, words, sentences, depending on what instance you provide.
105.509 - * @param removeNewLines if <code>true</code>, any newlines in the original string are ignored
105.510 - * @return the lines after wrapping
105.511 - */
105.512 - public static String[] wrapStringToArray(
105.513 - String original, int width, BreakIterator breakIterator, boolean removeNewLines
105.514 - ) {
105.515 - if (original.length() == 0) {
105.516 - return new String[] { original };
105.517 - }
105.518 -
105.519 - String[] workingSet;
105.520 -
105.521 - // substitute original newlines with spaces,
105.522 - // remove newlines from head and tail
105.523 - if (removeNewLines) {
105.524 - original = trimString(original);
105.525 - original = original.replace('\n', ' ');
105.526 - workingSet = new String[] { original };
105.527 - } else {
105.528 - StringTokenizer tokens = new StringTokenizer(original, "\n"); // NOI18N
105.529 - int len = tokens.countTokens();
105.530 - workingSet = new String[len];
105.531 -
105.532 - for (int i = 0; i < len; i++) {
105.533 - workingSet[i] = tokens.nextToken();
105.534 - }
105.535 - }
105.536 -
105.537 - if (width < 1) {
105.538 - width = 1;
105.539 - }
105.540 -
105.541 - if (original.length() <= width) {
105.542 - return workingSet;
105.543 - }
105.544 -
105.545 -widthcheck: {
105.546 - boolean ok = true;
105.547 -
105.548 - for (int i = 0; i < workingSet.length; i++) {
105.549 - ok = ok && (workingSet[i].length() < width);
105.550 -
105.551 - if (!ok) {
105.552 - break widthcheck;
105.553 - }
105.554 - }
105.555 -
105.556 - return workingSet;
105.557 - }
105.558 -
105.559 - java.util.ArrayList<String> lines = new java.util.ArrayList<String>();
105.560 -
105.561 - int lineStart = 0; // the position of start of currently processed line in the original string
105.562 -
105.563 - for (int i = 0; i < workingSet.length; i++) {
105.564 - if (workingSet[i].length() < width) {
105.565 - lines.add(workingSet[i]);
105.566 - } else {
105.567 - breakIterator.setText(workingSet[i]);
105.568 -
105.569 - int nextStart = breakIterator.next();
105.570 - int prevStart = 0;
105.571 -
105.572 - do {
105.573 - while (((nextStart - lineStart) < width) && (nextStart != BreakIterator.DONE)) {
105.574 - prevStart = nextStart;
105.575 - nextStart = breakIterator.next();
105.576 - }
105.577 -
105.578 - if (nextStart == BreakIterator.DONE) {
105.579 - nextStart = prevStart = workingSet[i].length();
105.580 - }
105.581 -
105.582 - if (prevStart == 0) {
105.583 - prevStart = nextStart;
105.584 - }
105.585 -
105.586 - lines.add(workingSet[i].substring(lineStart, prevStart));
105.587 -
105.588 - lineStart = prevStart;
105.589 - prevStart = 0;
105.590 - } while (lineStart < workingSet[i].length());
105.591 -
105.592 - lineStart = 0;
105.593 - }
105.594 - }
105.595 -
105.596 - String[] s = new String[lines.size()];
105.597 -
105.598 - return lines.toArray(s);
105.599 - }
105.600 -
105.601 - /** trims String
105.602 - * @param s a String to trim
105.603 - * @return trimmed String
105.604 - */
105.605 - private static String trimString(String s) {
105.606 - int idx = 0;
105.607 - char c;
105.608 - final int slen = s.length();
105.609 -
105.610 - if (slen == 0) {
105.611 - return s;
105.612 - }
105.613 -
105.614 - do {
105.615 - c = s.charAt(idx++);
105.616 - } while (((c == '\n') || (c == '\r')) && (idx < slen));
105.617 -
105.618 - s = s.substring(--idx);
105.619 - idx = s.length() - 1;
105.620 -
105.621 - if (idx < 0) {
105.622 - return s;
105.623 - }
105.624 -
105.625 - do {
105.626 - c = s.charAt(idx--);
105.627 - } while (((c == '\n') || (c == '\r')) && (idx >= 0));
105.628 -
105.629 - return s.substring(0, idx + 2);
105.630 - }
105.631 -
105.632 - /** Wrap multi-line strings.
105.633 - * @param original the original string to wrap
105.634 - * @param width the maximum width of lines
105.635 - * @param breakIterator algorithm for breaking lines
105.636 - * @param removeNewLines if <code>true</code>, any newlines in the original string are ignored
105.637 - * @return the whole string with embedded newlines
105.638 - */
105.639 - public static String wrapString(String original, int width, BreakIterator breakIterator, boolean removeNewLines) {
105.640 - String[] sarray = wrapStringToArray(original, width, breakIterator, removeNewLines);
105.641 - StringBuffer retBuf = new StringBuffer();
105.642 -
105.643 - for (int i = 0; i < sarray.length; i++) {
105.644 - retBuf.append(sarray[i]);
105.645 - retBuf.append('\n');
105.646 - }
105.647 -
105.648 - return retBuf.toString();
105.649 - }
105.650 -
105.651 - /** Wrap multi-line strings.
105.652 - * @param original the original string to wrap
105.653 - * @param width the maximum width of lines
105.654 - * @param wrapWords if <code>true</code>, the lines are wrapped on word boundaries (if possible);
105.655 - * if <code>false</code>, character boundaries are used
105.656 - * @param removeNewLines if <code>true</code>, any newlines in the original string are ignored
105.657 - * @return the whole string with embedded newlines
105.658 - * @deprecated Use {@link #wrapString (String, int, BreakIterator, boolean)} as it is friendlier to I18N.
105.659 - */
105.660 - @Deprecated
105.661 - public static String wrapString(String original, int width, boolean wrapWords, boolean removeNewLines) {
105.662 - // substitute original newlines with spaces,
105.663 - // remove newlines from head and tail
105.664 - if (removeNewLines) {
105.665 - while (original.startsWith("\n")) // NOI18N
105.666 -
105.667 - original = original.substring(1);
105.668 -
105.669 - while (original.endsWith("\n")) // NOI18N
105.670 -
105.671 - original = original.substring(0, original.length() - 1);
105.672 -
105.673 - original = original.replace('\n', ' ');
105.674 - }
105.675 -
105.676 - if (width < 1) {
105.677 - width = 1;
105.678 - }
105.679 -
105.680 - if (original.length() <= width) {
105.681 - return original;
105.682 - }
105.683 -
105.684 - java.util.Vector<String> lines = new java.util.Vector<String>();
105.685 - int lineStart = 0; // the position of start of currently processed line in the original string
105.686 - int lastSpacePos = -1;
105.687 -
105.688 - for (int i = 0; i < original.length(); i++) {
105.689 - if (lineStart >= (original.length() - 1)) {
105.690 - break;
105.691 - }
105.692 -
105.693 - // newline in the original string
105.694 - if (original.charAt(i) == '\n') {
105.695 - lines.addElement(original.substring(lineStart, i));
105.696 - lineStart = i + 1;
105.697 - lastSpacePos = -1;
105.698 -
105.699 - continue;
105.700 - }
105.701 -
105.702 - // remember last space position
105.703 - if (Character.isSpaceChar(original.charAt(i))) {
105.704 - lastSpacePos = i;
105.705 - }
105.706 -
105.707 - // last position in the original string
105.708 - if (i == (original.length() - 1)) {
105.709 - lines.addElement(original.substring(lineStart));
105.710 -
105.711 - break;
105.712 - }
105.713 -
105.714 - // reached width
105.715 - if ((i - lineStart) == width) {
105.716 - if (wrapWords && (lastSpacePos != -1)) {
105.717 - lines.addElement(original.substring(lineStart, lastSpacePos));
105.718 - lineStart = lastSpacePos + 1; // the space is consumed for the newline
105.719 - lastSpacePos = -1;
105.720 - } else {
105.721 - lines.addElement(original.substring(lineStart, i));
105.722 - lineStart = i;
105.723 - lastSpacePos = -1;
105.724 - }
105.725 - }
105.726 - }
105.727 -
105.728 - StringBuffer retBuf = new StringBuffer();
105.729 -
105.730 - for (java.util.Enumeration e = lines.elements(); e.hasMoreElements();) {
105.731 - retBuf.append((String) e.nextElement());
105.732 - retBuf.append('\n');
105.733 - }
105.734 -
105.735 - return retBuf.toString();
105.736 - }
105.737 -
105.738 - /** Search-and-replace fixed string matches within a string.
105.739 - * @param original the original string
105.740 - * @param replaceFrom the substring to be find
105.741 - * @param replaceTo the substring to replace it with
105.742 - * @return a new string with all occurrences replaced
105.743 - * @deprecated Use {@link String#replace(CharSequence,CharSequence)} instead
105.744 - */
105.745 - @Deprecated
105.746 - public static String replaceString(String original, String replaceFrom, String replaceTo) {
105.747 - int index = 0;
105.748 -
105.749 - if ("".equals(replaceFrom)) {
105.750 - return original; // NOI18N
105.751 - }
105.752 -
105.753 - StringBuffer buf = new StringBuffer();
105.754 -
105.755 - while (true) {
105.756 - int pos = original.indexOf(replaceFrom, index);
105.757 -
105.758 - if (pos == -1) {
105.759 - buf.append(original.substring(index));
105.760 -
105.761 - return buf.toString();
105.762 - }
105.763 -
105.764 - buf.append(original.substring(index, pos));
105.765 - buf.append(replaceTo);
105.766 - index = pos + replaceFrom.length();
105.767 -
105.768 - if (index == original.length()) {
105.769 - return buf.toString();
105.770 - }
105.771 - }
105.772 - }
105.773 -
105.774 - /** Turn full name of an inner class into its pure form.
105.775 - * @param fullName e.g. <code>some.pkg.SomeClass$Inner</code>
105.776 - * @return e.g. <code>Inner</code>
105.777 - */
105.778 - public static final String pureClassName(final String fullName) {
105.779 - final int index = fullName.indexOf('$');
105.780 -
105.781 - if ((index >= 0) && (index < fullName.length())) {
105.782 - return fullName.substring(index + 1, fullName.length());
105.783 - }
105.784 -
105.785 - return fullName;
105.786 - }
105.787 -
105.788 - /** Test whether the operating system supports icons on frames (windows).
105.789 - * @return <code>true</code> if it does <em>not</em>
105.790 - * @deprecated Obsolete, useless method, no replacement.
105.791 - */
105.792 - @Deprecated public static final boolean isLargeFrameIcons() {
105.793 - return (getOperatingSystem() == OS_SOLARIS) || (getOperatingSystem() == OS_HP);
105.794 - }
105.795 -
105.796 - /** Compute hash code of array.
105.797 - * Asks all elements for their own code and composes the
105.798 - * values.
105.799 - * @param arr array of objects, can contain <code>null</code>s
105.800 - * @return the hash code
105.801 - * @see Object#hashCode
105.802 - */
105.803 - public static int arrayHashCode(Object[] arr) {
105.804 - int c = 0;
105.805 - int len = arr.length;
105.806 -
105.807 - for (int i = 0; i < len; i++) {
105.808 - Object o = arr[i];
105.809 - int v = (o == null) ? 1 : o.hashCode();
105.810 - c += (v ^ i);
105.811 - }
105.812 -
105.813 - return c;
105.814 - }
105.815 -
105.816 - /** Safe equality check.
105.817 - * The supplied objects are equal if: <UL>
105.818 - * <LI> both are <code>null</code>
105.819 - * <LI> both are arrays with same length and equal items (if the items are arrays,
105.820 - * they are <em>not</em> checked the same way again)
105.821 - * <LI> the two objects are {@link Object#equals}
105.822 - * </UL>
105.823 - * This method is <code>null</code>-safe, so if one of the parameters is true and the second not,
105.824 - * it returns <code>false</code>.
105.825 - * @param o1 the first object to compare
105.826 - * @param o2 the second object to compare
105.827 - * @return <code>true</code> if the objects are equal
105.828 - */
105.829 - public static boolean compareObjects(Object o1, Object o2) {
105.830 - return compareObjectsImpl(o1, o2, 1);
105.831 - }
105.832 -
105.833 - /** Safe equality check with array recursion.
105.834 - * @param o1 the first object to compare
105.835 - * @param o2 the second object to compare
105.836 - * @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.)
105.837 - * @return <code>true</code> if the objects are equal
105.838 - * @see #compareObjects(Object, Object)
105.839 - */
105.840 - public static boolean compareObjectsImpl(Object o1, Object o2, int checkArraysDepth) {
105.841 - // handle null values
105.842 - if (o1 == null) {
105.843 - return (o2 == null);
105.844 - } else if (o2 == null) {
105.845 - return false;
105.846 - }
105.847 -
105.848 - // handle arrays
105.849 - if (checkArraysDepth > 0) {
105.850 - if ((o1 instanceof Object[]) && (o2 instanceof Object[])) {
105.851 - // Note: also handles multidimensional arrays of primitive types correctly.
105.852 - // I.e. new int[0][] instanceof Object[]
105.853 - Object[] o1a = (Object[]) o1;
105.854 - Object[] o2a = (Object[]) o2;
105.855 - int l1 = o1a.length;
105.856 - int l2 = o2a.length;
105.857 -
105.858 - if (l1 != l2) {
105.859 - return false;
105.860 - }
105.861 -
105.862 - for (int i = 0; i < l1; i++) {
105.863 - if (!compareObjectsImpl(o1a[i], o2a[i], checkArraysDepth - 1)) {
105.864 - return false;
105.865 - }
105.866 - }
105.867 -
105.868 - return true;
105.869 - } else if ((o1 instanceof byte[]) && (o2 instanceof byte[])) {
105.870 - byte[] o1a = (byte[]) o1;
105.871 - byte[] o2a = (byte[]) o2;
105.872 - int l1 = o1a.length;
105.873 - int l2 = o2a.length;
105.874 -
105.875 - if (l1 != l2) {
105.876 - return false;
105.877 - }
105.878 -
105.879 - for (int i = 0; i < l1; i++)
105.880 - if (o1a[i] != o2a[i]) {
105.881 - return false;
105.882 - }
105.883 -
105.884 - return true;
105.885 - } else if ((o1 instanceof short[]) && (o2 instanceof short[])) {
105.886 - short[] o1a = (short[]) o1;
105.887 - short[] o2a = (short[]) o2;
105.888 - int l1 = o1a.length;
105.889 - int l2 = o2a.length;
105.890 -
105.891 - if (l1 != l2) {
105.892 - return false;
105.893 - }
105.894 -
105.895 - for (int i = 0; i < l1; i++)
105.896 - if (o1a[i] != o2a[i]) {
105.897 - return false;
105.898 - }
105.899 -
105.900 - return true;
105.901 - } else if ((o1 instanceof int[]) && (o2 instanceof int[])) {
105.902 - int[] o1a = (int[]) o1;
105.903 - int[] o2a = (int[]) o2;
105.904 - int l1 = o1a.length;
105.905 - int l2 = o2a.length;
105.906 -
105.907 - if (l1 != l2) {
105.908 - return false;
105.909 - }
105.910 -
105.911 - for (int i = 0; i < l1; i++)
105.912 - if (o1a[i] != o2a[i]) {
105.913 - return false;
105.914 - }
105.915 -
105.916 - return true;
105.917 - } else if ((o1 instanceof long[]) && (o2 instanceof long[])) {
105.918 - long[] o1a = (long[]) o1;
105.919 - long[] o2a = (long[]) o2;
105.920 - int l1 = o1a.length;
105.921 - int l2 = o2a.length;
105.922 -
105.923 - if (l1 != l2) {
105.924 - return false;
105.925 - }
105.926 -
105.927 - for (int i = 0; i < l1; i++)
105.928 - if (o1a[i] != o2a[i]) {
105.929 - return false;
105.930 - }
105.931 -
105.932 - return true;
105.933 - } else if ((o1 instanceof float[]) && (o2 instanceof float[])) {
105.934 - float[] o1a = (float[]) o1;
105.935 - float[] o2a = (float[]) o2;
105.936 - int l1 = o1a.length;
105.937 - int l2 = o2a.length;
105.938 -
105.939 - if (l1 != l2) {
105.940 - return false;
105.941 - }
105.942 -
105.943 - for (int i = 0; i < l1; i++)
105.944 - if (o1a[i] != o2a[i]) {
105.945 - return false;
105.946 - }
105.947 -
105.948 - return true;
105.949 - } else if ((o1 instanceof double[]) && (o2 instanceof double[])) {
105.950 - double[] o1a = (double[]) o1;
105.951 - double[] o2a = (double[]) o2;
105.952 - int l1 = o1a.length;
105.953 - int l2 = o2a.length;
105.954 -
105.955 - if (l1 != l2) {
105.956 - return false;
105.957 - }
105.958 -
105.959 - for (int i = 0; i < l1; i++)
105.960 - if (o1a[i] != o2a[i]) {
105.961 - return false;
105.962 - }
105.963 -
105.964 - return true;
105.965 - } else if ((o1 instanceof char[]) && (o2 instanceof char[])) {
105.966 - char[] o1a = (char[]) o1;
105.967 - char[] o2a = (char[]) o2;
105.968 - int l1 = o1a.length;
105.969 - int l2 = o2a.length;
105.970 -
105.971 - if (l1 != l2) {
105.972 - return false;
105.973 - }
105.974 -
105.975 - for (int i = 0; i < l1; i++)
105.976 - if (o1a[i] != o2a[i]) {
105.977 - return false;
105.978 - }
105.979 -
105.980 - return true;
105.981 - } else if ((o1 instanceof boolean[]) && (o2 instanceof boolean[])) {
105.982 - boolean[] o1a = (boolean[]) o1;
105.983 - boolean[] o2a = (boolean[]) o2;
105.984 - int l1 = o1a.length;
105.985 - int l2 = o2a.length;
105.986 -
105.987 - if (l1 != l2) {
105.988 - return false;
105.989 - }
105.990 -
105.991 - for (int i = 0; i < l1; i++)
105.992 - if (o1a[i] != o2a[i]) {
105.993 - return false;
105.994 - }
105.995 -
105.996 - return true;
105.997 - }
105.998 -
105.999 - // else not array type
105.1000 - }
105.1001 -
105.1002 - // handle common objects--non-arrays, or arrays when depth == 0
105.1003 - return o1.equals(o2);
105.1004 - }
105.1005 -
105.1006 - /** Assemble a human-presentable class name for a specified class.
105.1007 - * Arrays are represented as e.g. <code>java.lang.String[]</code>.
105.1008 - * @param clazz the class to name
105.1009 - * @return the human-presentable name
105.1010 - */
105.1011 - public static String getClassName(Class clazz) {
105.1012 - // if it is an array, get short name of element type and append []
105.1013 - if (clazz.isArray()) {
105.1014 - return getClassName(clazz.getComponentType()) + "[]"; // NOI18N
105.1015 - } else {
105.1016 - return clazz.getName();
105.1017 - }
105.1018 - }
105.1019 -
105.1020 - /** Assemble a human-presentable class name for a specified class (omitting the package).
105.1021 - * Arrays are represented as e.g. <code>String[]</code>.
105.1022 - * @param clazz the class to name
105.1023 - * @return the human-presentable name
105.1024 - */
105.1025 - public static String getShortClassName(Class clazz) {
105.1026 - // if it is an array, get short name of element type and append []
105.1027 - if (clazz.isArray()) {
105.1028 - return getShortClassName(clazz.getComponentType()) + "[]"; // NOI18N
105.1029 - }
105.1030 -
105.1031 - String name = clazz.getName().replace('$', '.');
105.1032 -
105.1033 - return name.substring(name.lastIndexOf(".") + 1, name.length()); // NOI18N
105.1034 - }
105.1035 -
105.1036 - /**
105.1037 - * Convert an array of objects to an array of primitive types.
105.1038 - * E.g. an <code>Integer[]</code> would be changed to an <code>int[]</code>.
105.1039 - * @param array the wrapper array
105.1040 - * @return a primitive array
105.1041 - * @throws IllegalArgumentException if the array element type is not a primitive wrapper
105.1042 - */
105.1043 - public static Object toPrimitiveArray(Object[] array) {
105.1044 - if (array instanceof Integer[]) {
105.1045 - int[] r = new int[array.length];
105.1046 - int i;
105.1047 - int k = array.length;
105.1048 -
105.1049 - for (i = 0; i < k; i++)
105.1050 - r[i] = (((Integer) array[i]) == null) ? 0 : ((Integer) array[i]).intValue();
105.1051 -
105.1052 - return r;
105.1053 - }
105.1054 -
105.1055 - if (array instanceof Boolean[]) {
105.1056 - boolean[] r = new boolean[array.length];
105.1057 - int i;
105.1058 - int k = array.length;
105.1059 -
105.1060 - for (i = 0; i < k; i++)
105.1061 - r[i] = (((Boolean) array[i]) == null) ? false : ((Boolean) array[i]).booleanValue();
105.1062 -
105.1063 - return r;
105.1064 - }
105.1065 -
105.1066 - if (array instanceof Byte[]) {
105.1067 - byte[] r = new byte[array.length];
105.1068 - int i;
105.1069 - int k = array.length;
105.1070 -
105.1071 - for (i = 0; i < k; i++)
105.1072 - r[i] = (((Byte) array[i]) == null) ? 0 : ((Byte) array[i]).byteValue();
105.1073 -
105.1074 - return r;
105.1075 - }
105.1076 -
105.1077 - if (array instanceof Character[]) {
105.1078 - char[] r = new char[array.length];
105.1079 - int i;
105.1080 - int k = array.length;
105.1081 -
105.1082 - for (i = 0; i < k; i++)
105.1083 - r[i] = (((Character) array[i]) == null) ? 0 : ((Character) array[i]).charValue();
105.1084 -
105.1085 - return r;
105.1086 - }
105.1087 -
105.1088 - if (array instanceof Double[]) {
105.1089 - double[] r = new double[array.length];
105.1090 - int i;
105.1091 - int k = array.length;
105.1092 -
105.1093 - for (i = 0; i < k; i++)
105.1094 - r[i] = (((Double) array[i]) == null) ? 0 : ((Double) array[i]).doubleValue();
105.1095 -
105.1096 - return r;
105.1097 - }
105.1098 -
105.1099 - if (array instanceof Float[]) {
105.1100 - float[] r = new float[array.length];
105.1101 - int i;
105.1102 - int k = array.length;
105.1103 -
105.1104 - for (i = 0; i < k; i++)
105.1105 - r[i] = (((Float) array[i]) == null) ? 0 : ((Float) array[i]).floatValue();
105.1106 -
105.1107 - return r;
105.1108 - }
105.1109 -
105.1110 - if (array instanceof Long[]) {
105.1111 - long[] r = new long[array.length];
105.1112 - int i;
105.1113 - int k = array.length;
105.1114 -
105.1115 - for (i = 0; i < k; i++)
105.1116 - r[i] = (((Long) array[i]) == null) ? 0 : ((Long) array[i]).longValue();
105.1117 -
105.1118 - return r;
105.1119 - }
105.1120 -
105.1121 - if (array instanceof Short[]) {
105.1122 - short[] r = new short[array.length];
105.1123 - int i;
105.1124 - int k = array.length;
105.1125 -
105.1126 - for (i = 0; i < k; i++)
105.1127 - r[i] = (((Short) array[i]) == null) ? 0 : ((Short) array[i]).shortValue();
105.1128 -
105.1129 - return r;
105.1130 - }
105.1131 -
105.1132 - throw new IllegalArgumentException();
105.1133 - }
105.1134 -
105.1135 - /**
105.1136 - * Convert an array of primitive types to an array of objects.
105.1137 - * E.g. an <code>int[]</code> would be turned into an <code>Integer[]</code>.
105.1138 - * @param array the primitive array
105.1139 - * @return a wrapper array
105.1140 - * @throws IllegalArgumentException if the array element type is not primitive
105.1141 - */
105.1142 - public static Object[] toObjectArray(Object array) {
105.1143 - if (array instanceof Object[]) {
105.1144 - return (Object[]) array;
105.1145 - }
105.1146 -
105.1147 - if (array instanceof int[]) {
105.1148 - int i;
105.1149 - int k = ((int[]) array).length;
105.1150 - Integer[] r = new Integer[k];
105.1151 -
105.1152 - for (i = 0; i < k; i++)
105.1153 - r[i] = new Integer(((int[]) array)[i]);
105.1154 -
105.1155 - return r;
105.1156 - }
105.1157 -
105.1158 - if (array instanceof boolean[]) {
105.1159 - int i;
105.1160 - int k = ((boolean[]) array).length;
105.1161 - Boolean[] r = new Boolean[k];
105.1162 -
105.1163 - for (i = 0; i < k; i++)
105.1164 - r[i] = ((boolean[]) array)[i] ? Boolean.TRUE : Boolean.FALSE;
105.1165 -
105.1166 - return r;
105.1167 - }
105.1168 -
105.1169 - if (array instanceof byte[]) {
105.1170 - int i;
105.1171 - int k = ((byte[]) array).length;
105.1172 - Byte[] r = new Byte[k];
105.1173 -
105.1174 - for (i = 0; i < k; i++)
105.1175 - r[i] = new Byte(((byte[]) array)[i]);
105.1176 -
105.1177 - return r;
105.1178 - }
105.1179 -
105.1180 - if (array instanceof char[]) {
105.1181 - int i;
105.1182 - int k = ((char[]) array).length;
105.1183 - Character[] r = new Character[k];
105.1184 -
105.1185 - for (i = 0; i < k; i++)
105.1186 - r[i] = new Character(((char[]) array)[i]);
105.1187 -
105.1188 - return r;
105.1189 - }
105.1190 -
105.1191 - if (array instanceof double[]) {
105.1192 - int i;
105.1193 - int k = ((double[]) array).length;
105.1194 - Double[] r = new Double[k];
105.1195 -
105.1196 - for (i = 0; i < k; i++)
105.1197 - r[i] = new Double(((double[]) array)[i]);
105.1198 -
105.1199 - return r;
105.1200 - }
105.1201 -
105.1202 - if (array instanceof float[]) {
105.1203 - int i;
105.1204 - int k = ((float[]) array).length;
105.1205 - Float[] r = new Float[k];
105.1206 -
105.1207 - for (i = 0; i < k; i++)
105.1208 - r[i] = new Float(((float[]) array)[i]);
105.1209 -
105.1210 - return r;
105.1211 - }
105.1212 -
105.1213 - if (array instanceof long[]) {
105.1214 - int i;
105.1215 - int k = ((long[]) array).length;
105.1216 - Long[] r = new Long[k];
105.1217 -
105.1218 - for (i = 0; i < k; i++)
105.1219 - r[i] = new Long(((long[]) array)[i]);
105.1220 -
105.1221 - return r;
105.1222 - }
105.1223 -
105.1224 - if (array instanceof short[]) {
105.1225 - int i;
105.1226 - int k = ((short[]) array).length;
105.1227 - Short[] r = new Short[k];
105.1228 -
105.1229 - for (i = 0; i < k; i++)
105.1230 - r[i] = new Short(((short[]) array)[i]);
105.1231 -
105.1232 - return r;
105.1233 - }
105.1234 -
105.1235 - throw new IllegalArgumentException();
105.1236 - }
105.1237 -
105.1238 - /**
105.1239 - * Get the object type for given primitive type.
105.1240 - *
105.1241 - * @param c primitive type (e.g. <code>int</code>)
105.1242 - * @return object type (e.g. <code>Integer</code>)
105.1243 - */
105.1244 - public static Class getObjectType(Class c) {
105.1245 - if (!c.isPrimitive()) {
105.1246 - return c;
105.1247 - }
105.1248 -
105.1249 - if (c == Integer.TYPE) {
105.1250 - return Integer.class;
105.1251 - }
105.1252 -
105.1253 - if (c == Boolean.TYPE) {
105.1254 - return Boolean.class;
105.1255 - }
105.1256 -
105.1257 - if (c == Byte.TYPE) {
105.1258 - return Byte.class;
105.1259 - }
105.1260 -
105.1261 - if (c == Character.TYPE) {
105.1262 - return Character.class;
105.1263 - }
105.1264 -
105.1265 - if (c == Double.TYPE) {
105.1266 - return Double.class;
105.1267 - }
105.1268 -
105.1269 - if (c == Float.TYPE) {
105.1270 - return Float.class;
105.1271 - }
105.1272 -
105.1273 - if (c == Long.TYPE) {
105.1274 - return Long.class;
105.1275 - }
105.1276 -
105.1277 - if (c == Short.TYPE) {
105.1278 - return Short.class;
105.1279 - }
105.1280 -
105.1281 - throw new IllegalArgumentException();
105.1282 - }
105.1283 -
105.1284 - /**
105.1285 - * Get the primitive type for given object type.
105.1286 - *
105.1287 - * @param c object type (e.g. <code>Integer</code>)
105.1288 - * @return primitive type (e.g. <code>int</code>)
105.1289 - */
105.1290 - public static Class getPrimitiveType(Class c) {
105.1291 - if (!c.isPrimitive()) {
105.1292 - return c;
105.1293 - }
105.1294 -
105.1295 - if (c == Integer.class) {
105.1296 - return Integer.TYPE;
105.1297 - }
105.1298 -
105.1299 - if (c == Boolean.class) {
105.1300 - return Boolean.TYPE;
105.1301 - }
105.1302 -
105.1303 - if (c == Byte.class) {
105.1304 - return Byte.TYPE;
105.1305 - }
105.1306 -
105.1307 - if (c == Character.class) {
105.1308 - return Character.TYPE;
105.1309 - }
105.1310 -
105.1311 - if (c == Double.class) {
105.1312 - return Double.TYPE;
105.1313 - }
105.1314 -
105.1315 - if (c == Float.class) {
105.1316 - return Float.TYPE;
105.1317 - }
105.1318 -
105.1319 - if (c == Long.class) {
105.1320 - return Long.TYPE;
105.1321 - }
105.1322 -
105.1323 - if (c == Short.class) {
105.1324 - return Short.TYPE;
105.1325 - }
105.1326 -
105.1327 - throw new IllegalArgumentException();
105.1328 - }
105.1329 -
105.1330 - /** Find a focus-traverable component.
105.1331 - * @param c the component to look in
105.1332 - * @return the same component if traversable, else a child component if present, else <code>null</code>
105.1333 - * @see Component#isFocusTraversable
105.1334 - */
105.1335 - public static Component getFocusTraversableComponent(Component c) {
105.1336 - if (c.isFocusable()) {
105.1337 - return c;
105.1338 - }
105.1339 -
105.1340 - if (!(c instanceof Container)) {
105.1341 - return null;
105.1342 - }
105.1343 -
105.1344 - int i;
105.1345 - int k = ((Container) c).getComponentCount();
105.1346 -
105.1347 - for (i = 0; i < k; i++) {
105.1348 - Component v = ((Container) c).getComponent(i);
105.1349 -
105.1350 - if (v != null) {
105.1351 - return v;
105.1352 - }
105.1353 - }
105.1354 -
105.1355 - return null;
105.1356 - }
105.1357 -
105.1358 - /** Parses parameters from a given string in shell-like manner.
105.1359 - * Users of the Bourne shell (e.g. on Unix) will already be familiar with the behavior.
105.1360 - * For example, when using <code>org.openide.execution.NbProcessDescriptor</code> (Execution API)
105.1361 - * you should be able to:
105.1362 - * <ul>
105.1363 - * <li>Include command names with embedded spaces, such as <code>c:\Program Files\jdk\bin\javac</code>.
105.1364 - * <li>Include extra command arguments, such as <code>-Dname=value</code>.
105.1365 - * <li>Do anything else which might require unusual characters or processing. For example:
105.1366 - * <p><code><pre>
105.1367 - * "c:\program files\jdk\bin\java" -Dmessage="Hello /\\/\\ there!" -Xmx128m
105.1368 - * </pre></code>
105.1369 - * <p>This example would create the following executable name and arguments:
105.1370 - * <ol>
105.1371 - * <li> <code>c:\program files\jdk\bin\java</code>
105.1372 - * <li> <code>-Dmessage=Hello /\/\ there!</code>
105.1373 - * <li> <code>-Xmx128m</code>
105.1374 - * </ol>
105.1375 - * Note that the command string does not escape its backslashes--under the assumption
105.1376 - * that Windows users will not think to do this, meaningless escapes are just left
105.1377 - * as backslashes plus following character.
105.1378 - * </ul>
105.1379 - * <em>Caveat</em>: even after parsing, Windows programs (such as the Java launcher)
105.1380 - * may not fully honor certain
105.1381 - * characters, such as quotes, in command names or arguments. This is because programs
105.1382 - * under Windows frequently perform their own parsing and unescaping (since the shell
105.1383 - * cannot be relied on to do this). On Unix, this problem should not occur.
105.1384 - * @param s a string to parse
105.1385 - * @return an array of parameters
105.1386 - */
105.1387 - public static String[] parseParameters(String s) {
105.1388 - int NULL = 0x0; // STICK + whitespace or NULL + non_"
105.1389 - int INPARAM = 0x1; // NULL + " or STICK + " or INPARAMPENDING + "\ // NOI18N
105.1390 - int INPARAMPENDING = 0x2; // INPARAM + \
105.1391 - int STICK = 0x4; // INPARAM + " or STICK + non_" // NOI18N
105.1392 - int STICKPENDING = 0x8; // STICK + \
105.1393 - Vector<String> params = new Vector<String>(5, 5);
105.1394 - char c;
105.1395 -
105.1396 - int state = NULL;
105.1397 - StringBuffer buff = new StringBuffer(20);
105.1398 - int slength = s.length();
105.1399 -
105.1400 - for (int i = 0; i < slength; i++) {
105.1401 - c = s.charAt(i);
105.1402 -
105.1403 - if (Character.isWhitespace(c)) {
105.1404 - if (state == NULL) {
105.1405 - if (buff.length() > 0) {
105.1406 - params.addElement(buff.toString());
105.1407 - buff.setLength(0);
105.1408 - }
105.1409 - } else if (state == STICK) {
105.1410 - params.addElement(buff.toString());
105.1411 - buff.setLength(0);
105.1412 - state = NULL;
105.1413 - } else if (state == STICKPENDING) {
105.1414 - buff.append('\\');
105.1415 - params.addElement(buff.toString());
105.1416 - buff.setLength(0);
105.1417 - state = NULL;
105.1418 - } else if (state == INPARAMPENDING) {
105.1419 - state = INPARAM;
105.1420 - buff.append('\\');
105.1421 - buff.append(c);
105.1422 - } else { // INPARAM
105.1423 - buff.append(c);
105.1424 - }
105.1425 -
105.1426 - continue;
105.1427 - }
105.1428 -
105.1429 - if (c == '\\') {
105.1430 - if (state == NULL) {
105.1431 - ++i;
105.1432 -
105.1433 - if (i < slength) {
105.1434 - char cc = s.charAt(i);
105.1435 -
105.1436 - if ((cc == '"') || (cc == '\\')) {
105.1437 - buff.append(cc);
105.1438 - } else if (Character.isWhitespace(cc)) {
105.1439 - buff.append(c);
105.1440 - --i;
105.1441 - } else {
105.1442 - buff.append(c);
105.1443 - buff.append(cc);
105.1444 - }
105.1445 - } else {
105.1446 - buff.append('\\');
105.1447 -
105.1448 - break;
105.1449 - }
105.1450 -
105.1451 - continue;
105.1452 - } else if (state == INPARAM) {
105.1453 - state = INPARAMPENDING;
105.1454 - } else if (state == INPARAMPENDING) {
105.1455 - buff.append('\\');
105.1456 - state = INPARAM;
105.1457 - } else if (state == STICK) {
105.1458 - state = STICKPENDING;
105.1459 - } else if (state == STICKPENDING) {
105.1460 - buff.append('\\');
105.1461 - state = STICK;
105.1462 - }
105.1463 -
105.1464 - continue;
105.1465 - }
105.1466 -
105.1467 - if (c == '"') {
105.1468 - if (state == NULL) {
105.1469 - state = INPARAM;
105.1470 - } else if (state == INPARAM) {
105.1471 - state = STICK;
105.1472 - } else if (state == STICK) {
105.1473 - state = INPARAM;
105.1474 - } else if (state == STICKPENDING) {
105.1475 - buff.append('"');
105.1476 - state = STICK;
105.1477 - } else { // INPARAMPENDING
105.1478 - buff.append('"');
105.1479 - state = INPARAM;
105.1480 - }
105.1481 -
105.1482 - continue;
105.1483 - }
105.1484 -
105.1485 - if (state == INPARAMPENDING) {
105.1486 - buff.append('\\');
105.1487 - state = INPARAM;
105.1488 - } else if (state == STICKPENDING) {
105.1489 - buff.append('\\');
105.1490 - state = STICK;
105.1491 - }
105.1492 -
105.1493 - buff.append(c);
105.1494 - }
105.1495 -
105.1496 - // collect
105.1497 - if (state == INPARAM) {
105.1498 - params.addElement(buff.toString());
105.1499 - } else if ((state & (INPARAMPENDING | STICKPENDING)) != 0) {
105.1500 - buff.append('\\');
105.1501 - params.addElement(buff.toString());
105.1502 - } else { // NULL or STICK
105.1503 -
105.1504 - if (buff.length() != 0) {
105.1505 - params.addElement(buff.toString());
105.1506 - }
105.1507 - }
105.1508 -
105.1509 - String[] ret = new String[params.size()];
105.1510 - params.copyInto(ret);
105.1511 -
105.1512 - return ret;
105.1513 - }
105.1514 -
105.1515 - /** Complementary method to parseParameters
105.1516 - * @see #parseParameters
105.1517 - */
105.1518 - public static String escapeParameters(String[] params) {
105.1519 - StringBuffer sb = new StringBuffer();
105.1520 -
105.1521 - for (int i = 0; i < params.length; i++) {
105.1522 - escapeString(params[i], sb);
105.1523 - sb.append(' ');
105.1524 - }
105.1525 -
105.1526 - final int len = sb.length();
105.1527 -
105.1528 - if (len > 0) {
105.1529 - sb.setLength(len - 1);
105.1530 - }
105.1531 -
105.1532 - return sb.toString().trim();
105.1533 - }
105.1534 -
105.1535 - /** Escapes one string
105.1536 - * @see #escapeParameters
105.1537 - */
105.1538 - private static void escapeString(String s, StringBuffer sb) {
105.1539 - if (s.length() == 0) {
105.1540 - sb.append("\"\"");
105.1541 -
105.1542 - return;
105.1543 - }
105.1544 -
105.1545 - boolean hasSpace = false;
105.1546 - final int sz = sb.length();
105.1547 - final int slen = s.length();
105.1548 - char c;
105.1549 -
105.1550 - for (int i = 0; i < slen; i++) {
105.1551 - c = s.charAt(i);
105.1552 -
105.1553 - if (Character.isWhitespace(c)) {
105.1554 - hasSpace = true;
105.1555 - sb.append(c);
105.1556 -
105.1557 - continue;
105.1558 - }
105.1559 -
105.1560 - if (c == '\\') {
105.1561 - sb.append('\\').append('\\');
105.1562 -
105.1563 - continue;
105.1564 - }
105.1565 -
105.1566 - if (c == '"') {
105.1567 - sb.append('\\').append('"');
105.1568 -
105.1569 - continue;
105.1570 - }
105.1571 -
105.1572 - sb.append(c);
105.1573 - }
105.1574 -
105.1575 - if (hasSpace) {
105.1576 - sb.insert(sz, '"');
105.1577 - sb.append('"');
105.1578 - }
105.1579 - }
105.1580 -
105.1581 - //
105.1582 - // Key conversions
105.1583 - //
105.1584 -
105.1585 - private static final class NamesAndValues {
105.1586 - final Map<Integer,String> keyToString;
105.1587 - final Map<String,Integer> stringToKey;
105.1588 - NamesAndValues(Map<Integer,String> keyToString, Map<String,Integer> stringToKey) {
105.1589 - this.keyToString = keyToString;
105.1590 - this.stringToKey = stringToKey;
105.1591 - }
105.1592 - }
105.1593 -
105.1594 - private static Reference<NamesAndValues> namesAndValues;
105.1595 -
105.1596 - private static synchronized NamesAndValues initNameAndValues() {
105.1597 - if (namesAndValues != null) {
105.1598 - NamesAndValues nav = namesAndValues.get();
105.1599 - if (nav != null) {
105.1600 - return nav;
105.1601 - }
105.1602 - }
105.1603 -
105.1604 - Field[] fields = KeyEvent.class.getDeclaredFields();
105.1605 -
105.1606 - Map<String,Integer> names = new HashMap<String,Integer>(fields.length * 4 / 3 + 5, 0.75f);
105.1607 - Map<Integer,String> values = new HashMap<Integer,String>(fields.length * 4 / 3 + 5, 0.75f);
105.1608 -
105.1609 - for (Field f : fields) {
105.1610 - if (Modifier.isStatic(f.getModifiers())) {
105.1611 - String name = f.getName();
105.1612 - if (name.startsWith("VK_")) { // NOI18N
105.1613 - // exclude VK
105.1614 - name = name.substring(3);
105.1615 - try {
105.1616 - int numb = f.getInt(null);
105.1617 - names.put(name, numb);
105.1618 - values.put(numb, name);
105.1619 - } catch (IllegalArgumentException ex) {
105.1620 - } catch (IllegalAccessException ex) {
105.1621 - }
105.1622 - }
105.1623 - }
105.1624 - }
105.1625 -
105.1626 - if (names.get("CONTEXT_MENU") == null) { // NOI18N
105.1627 - names.put("CONTEXT_MENU", 0x20C); // NOI18N
105.1628 - values.put(0x20C, "CONTEXT_MENU"); // NOI18N
105.1629 - names.put("WINDOWS", 0x20D); // NOI18N
105.1630 - values.put(0x20D, "WINDOWS"); // NOI18N
105.1631 - }
105.1632 -
105.1633 - NamesAndValues nav = new NamesAndValues(values, names);
105.1634 - namesAndValues = new SoftReference<NamesAndValues>(nav);
105.1635 - return nav;
105.1636 - }
105.1637 -
105.1638 - /** Converts a Swing key stroke descriptor to a familiar Emacs-like name.
105.1639 - * @param stroke key description
105.1640 - * @return name of the key (e.g. <code>CS-F1</code> for control-shift-function key one)
105.1641 - * @see #stringToKey
105.1642 - */
105.1643 - public static String keyToString(KeyStroke stroke) {
105.1644 - StringBuilder sb = new StringBuilder();
105.1645 -
105.1646 - // add modifiers that must be pressed
105.1647 - if (addModifiers(sb, stroke.getModifiers())) {
105.1648 - sb.append('-');
105.1649 - }
105.1650 -
105.1651 - appendRest(sb, stroke);
105.1652 - return sb.toString();
105.1653 - }
105.1654 -
105.1655 - private static void appendRest(StringBuilder sb, KeyStroke stroke) {
105.1656 - String c = initNameAndValues().keyToString.get(Integer.valueOf(stroke.getKeyCode()));
105.1657 -
105.1658 - if (c == null) {
105.1659 - sb.append(stroke.getKeyChar());
105.1660 - } else {
105.1661 - sb.append(c);
105.1662 - }
105.1663 - }
105.1664 -
105.1665 - /**
105.1666 - * Converts a Swing key stroke descriptor to a familiar Emacs-like name,
105.1667 - * but in a portable way, ie. <code>Meta-C</code> on Mac => <code>D-C</code>
105.1668 - * @param stroke key description
105.1669 - * @return name of the key (e.g. <code>CS-F1</code> for control-shift-function key one)
105.1670 - * @see #stringToKey
105.1671 - */
105.1672 - public static String keyToString(KeyStroke stroke, boolean portable) {
105.1673 - if (portable) {
105.1674 - StringBuilder sb = new StringBuilder();
105.1675 -
105.1676 - // add modifiers that must be pressed
105.1677 - if (addModifiersPortable(sb, stroke.getModifiers())) {
105.1678 - sb.append('-');
105.1679 - }
105.1680 -
105.1681 - appendRest(sb, stroke);
105.1682 - return sb.toString();
105.1683 - }
105.1684 - return keyToString(stroke);
105.1685 - }
105.1686 -
105.1687 - /** Construct a new key description from a given universal string
105.1688 - * description.
105.1689 - * Provides mapping between Emacs-like textual key descriptions and the
105.1690 - * <code>KeyStroke</code> object used in Swing.
105.1691 - * <P>
105.1692 - * This format has following form:
105.1693 - * <P><code>[C][A][S][M]-<em>identifier</em></code>
105.1694 - * <p>Where:
105.1695 - * <UL>
105.1696 - * <LI> <code>C</code> stands for the Control key
105.1697 - * <LI> <code>A</code> stands for the Alt key
105.1698 - * <LI> <code>S</code> stands for the Shift key
105.1699 - * <LI> <code>M</code> stands for the Meta key
105.1700 - * </UL>
105.1701 - * The format also supports two wildcard codes, to support differences in
105.1702 - * platforms. These are the preferred choices for registering keystrokes,
105.1703 - * since platform conflicts will automatically be handled:
105.1704 - * <UL>
105.1705 - * <LI> <code>D</code> stands for the default menu accelerator - the Control
105.1706 - * key on most platforms, the Command (meta) key on Macintosh</LI>
105.1707 - * <LI> <code>O</code> stands for the alternate accelerator - the Alt key on
105.1708 - * most platforms, the Ctrl key on Macintosh (Macintosh uses Alt as a
105.1709 - * secondary shift key for composing international characters - if you bind
105.1710 - * Alt-8 to an action, a mac user with a French keyboard will not be able
105.1711 - * to type the <code>[</code> character, which is a significant handicap</LI>
105.1712 - * </UL>
105.1713 - * If you use the wildcard characters, and specify a key which will conflict
105.1714 - * with keys the operating system consumes, it will be mapped to whichever
105.1715 - * choice can work - for example, on Macintosh, Command-Q is always consumed
105.1716 - * by the operating system, so <code>D-Q</code> will always map to Control-Q.
105.1717 - * <p>
105.1718 - * Every modifier before the hyphen must be pressed.
105.1719 - * <em>identifier</EM> can be any text constant from {@link KeyEvent} but
105.1720 - * without the leading <code>VK_</code> characters. So {@link KeyEvent#VK_ENTER} is described as
105.1721 - * <code>ENTER</code>.
105.1722 - *
105.1723 - * @param s the string with the description of the key
105.1724 - * @return key description object, or <code>null</code> if the string does not represent any valid key
105.1725 - */
105.1726 - public static KeyStroke stringToKey(String s) {
105.1727 - StringTokenizer st = new StringTokenizer(s.toUpperCase(Locale.ENGLISH), "-", true); // NOI18N
105.1728 -
105.1729 - int needed = 0;
105.1730 -
105.1731 - Map<String,Integer> names = initNameAndValues().stringToKey;
105.1732 -
105.1733 - int lastModif = -1;
105.1734 -
105.1735 - try {
105.1736 - for (;;) {
105.1737 - String el = st.nextToken();
105.1738 -
105.1739 - // required key
105.1740 - if (el.equals("-")) { // NOI18N
105.1741 -
105.1742 - if (lastModif != -1) {
105.1743 - needed |= lastModif;
105.1744 - lastModif = -1;
105.1745 - }
105.1746 -
105.1747 - continue;
105.1748 - }
105.1749 -
105.1750 - // if there is more elements
105.1751 - if (st.hasMoreElements()) {
105.1752 - // the text should describe modifiers
105.1753 - lastModif = readModifiers(el);
105.1754 - } else {
105.1755 - // last text must be the key code
105.1756 - Integer i = names.get(el);
105.1757 - boolean wildcard = (needed & CTRL_WILDCARD_MASK) != 0;
105.1758 -
105.1759 - //Strip out the explicit mask - KeyStroke won't know
105.1760 - //what to do with it
105.1761 - needed = needed & ~CTRL_WILDCARD_MASK;
105.1762 -
105.1763 - boolean macAlt = (needed & ALT_WILDCARD_MASK) != 0;
105.1764 - needed = needed & ~ALT_WILDCARD_MASK;
105.1765 -
105.1766 - if (i != null) {
105.1767 - //#26854 - Default accelerator should be Command on mac
105.1768 - if (wildcard) {
105.1769 - needed |= getMenuShortcutKeyMask();
105.1770 -
105.1771 - if (isMac()) {
105.1772 - if (!usableKeyOnMac(i, needed)) {
105.1773 - needed &= ~getMenuShortcutKeyMask();
105.1774 - needed |= KeyEvent.CTRL_MASK;
105.1775 - }
105.1776 - }
105.1777 - }
105.1778 -
105.1779 - if (macAlt) {
105.1780 - if (getOperatingSystem() == OS_MAC) {
105.1781 - needed |= KeyEvent.CTRL_MASK;
105.1782 - } else {
105.1783 - needed |= KeyEvent.ALT_MASK;
105.1784 - }
105.1785 - }
105.1786 -
105.1787 - return KeyStroke.getKeyStroke(i, needed);
105.1788 - } else {
105.1789 - return null;
105.1790 - }
105.1791 - }
105.1792 - }
105.1793 - } catch (NoSuchElementException ex) {
105.1794 - return null;
105.1795 - }
105.1796 - }
105.1797 -
105.1798 - private static final boolean usableKeyOnMac(int key, int mask) {
105.1799 - //All permutations fail for Q except ctrl
105.1800 - if (key == KeyEvent.VK_Q) {
105.1801 - return false;
105.1802 - }
105.1803 -
105.1804 - boolean isMeta = ((mask & KeyEvent.META_MASK) != 0) || ((mask & KeyEvent.CTRL_DOWN_MASK) != 0);
105.1805 -
105.1806 - boolean isAlt = ((mask & KeyEvent.ALT_MASK) != 0) || ((mask & KeyEvent.ALT_DOWN_MASK) != 0);
105.1807 -
105.1808 - boolean isOnlyMeta = isMeta && ((mask & ~(KeyEvent.META_DOWN_MASK | KeyEvent.META_MASK)) == 0);
105.1809 -
105.1810 - //Mac OS consumes keys Command+ these keys - the app will never see
105.1811 - //them, so CTRL should not be remapped for these
105.1812 - if (isOnlyMeta) {
105.1813 - return (key != KeyEvent.VK_H) && (key != KeyEvent.VK_SPACE) && (key != KeyEvent.VK_TAB);
105.1814 - } else if ((key == KeyEvent.VK_D) && isMeta && isAlt) {
105.1815 - return false;
105.1816 - } else {
105.1817 - return true;
105.1818 - }
105.1819 - }
105.1820 -
105.1821 - private static final int getMenuShortcutKeyMask() {
105.1822 - // #152050 - work in headless environment too
105.1823 - if (GraphicsEnvironment.isHeadless()) {
105.1824 - return Event.CTRL_MASK;
105.1825 - }
105.1826 - return Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
105.1827 - }
105.1828 -
105.1829 - /** Convert a space-separated list of user-friendly key binding names to a list of Swing key strokes.
105.1830 - * @param s the string with keys
105.1831 - * @return array of key strokes, or <code>null</code> if the string description is not valid
105.1832 - * @see #stringToKey
105.1833 - */
105.1834 - public static KeyStroke[] stringToKeys(String s) {
105.1835 - StringTokenizer st = new StringTokenizer(s.toUpperCase(Locale.ENGLISH), " "); // NOI18N
105.1836 - ArrayList<KeyStroke> arr = new ArrayList<KeyStroke>();
105.1837 -
105.1838 - while (st.hasMoreElements()) {
105.1839 - s = st.nextToken();
105.1840 -
105.1841 - KeyStroke k = stringToKey(s);
105.1842 -
105.1843 - if (k == null) {
105.1844 - return null;
105.1845 - }
105.1846 -
105.1847 - arr.add(k);
105.1848 - }
105.1849 -
105.1850 - return arr.toArray(new KeyStroke[arr.size()]);
105.1851 - }
105.1852 -
105.1853 - /** Adds characters for modifiers to the buffer.
105.1854 - * @param buf buffer to add to
105.1855 - * @param modif modifiers to add (KeyEvent.XXX_MASK)
105.1856 - * @return true if something has been added
105.1857 - */
105.1858 - private static boolean addModifiers(StringBuilder buf, int modif) {
105.1859 - boolean b = false;
105.1860 -
105.1861 - if ((modif & KeyEvent.CTRL_MASK) != 0) {
105.1862 - buf.append("C"); // NOI18N
105.1863 - b = true;
105.1864 - }
105.1865 -
105.1866 - if ((modif & KeyEvent.ALT_MASK) != 0) {
105.1867 - buf.append("A"); // NOI18N
105.1868 - b = true;
105.1869 - }
105.1870 -
105.1871 - if ((modif & KeyEvent.SHIFT_MASK) != 0) {
105.1872 - buf.append("S"); // NOI18N
105.1873 - b = true;
105.1874 - }
105.1875 -
105.1876 - if ((modif & KeyEvent.META_MASK) != 0) {
105.1877 - buf.append("M"); // NOI18N
105.1878 - b = true;
105.1879 - }
105.1880 -
105.1881 - if ((modif & CTRL_WILDCARD_MASK) != 0) {
105.1882 - buf.append("D");
105.1883 - b = true;
105.1884 - }
105.1885 -
105.1886 - if ((modif & ALT_WILDCARD_MASK) != 0) {
105.1887 - buf.append("O");
105.1888 - b = true;
105.1889 - }
105.1890 -
105.1891 - return b;
105.1892 - }
105.1893 -
105.1894 - private static boolean addModifiersPortable(StringBuilder buf, int modifiers) {
105.1895 - boolean b = false;
105.1896 -
105.1897 - if ((modifiers & KeyEvent.SHIFT_MASK) != 0) {
105.1898 - buf.append('S');
105.1899 - b = true;
105.1900 - }
105.1901 -
105.1902 - if (Utilities.isMac() && ((modifiers & KeyEvent.META_MASK) != 0) || !Utilities.isMac() && ((modifiers & KeyEvent.CTRL_MASK) != 0)) {
105.1903 - buf.append('D');
105.1904 - b = true;
105.1905 - }
105.1906 -
105.1907 - if (Utilities.isMac() && ((modifiers & KeyEvent.CTRL_MASK) != 0) || !Utilities.isMac() && ((modifiers & KeyEvent.ALT_MASK) != 0)) {
105.1908 - buf.append('O');
105.1909 - b = true;
105.1910 - }
105.1911 - // mac alt fallback
105.1912 - if (Utilities.isMac() && ((modifiers & KeyEvent.ALT_MASK) != 0)) {
105.1913 - buf.append('A');
105.1914 - b = true;
105.1915 - }
105.1916 -
105.1917 - return b;
105.1918 - }
105.1919 -
105.1920 - /** Reads for modifiers and creates integer with required mask.
105.1921 - * @param s string with modifiers
105.1922 - * @return integer with mask
105.1923 - * @exception NoSuchElementException if some letter is not modifier
105.1924 - */
105.1925 - private static int readModifiers(String s) throws NoSuchElementException {
105.1926 - int m = 0;
105.1927 -
105.1928 - for (int i = 0; i < s.length(); i++) {
105.1929 - switch (s.charAt(i)) {
105.1930 - case 'C':
105.1931 - m |= KeyEvent.CTRL_MASK;
105.1932 -
105.1933 - break;
105.1934 -
105.1935 - case 'A':
105.1936 - m |= KeyEvent.ALT_MASK;
105.1937 -
105.1938 - break;
105.1939 -
105.1940 - case 'M':
105.1941 - m |= KeyEvent.META_MASK;
105.1942 -
105.1943 - break;
105.1944 -
105.1945 - case 'S':
105.1946 - m |= KeyEvent.SHIFT_MASK;
105.1947 -
105.1948 - break;
105.1949 -
105.1950 - case 'D':
105.1951 - m |= CTRL_WILDCARD_MASK;
105.1952 -
105.1953 - break;
105.1954 -
105.1955 - case 'O':
105.1956 - m |= ALT_WILDCARD_MASK;
105.1957 -
105.1958 - break;
105.1959 -
105.1960 - default:
105.1961 - throw new NoSuchElementException(s);
105.1962 - }
105.1963 - }
105.1964 -
105.1965 - return m;
105.1966 - }
105.1967 -
105.1968 - /**
105.1969 - * Finds out the monitor where the user currently has the input focus.
105.1970 - * This method is usually used to help the client code to figure out on
105.1971 - * which monitor it should place newly created windows/frames/dialogs.
105.1972 - *
105.1973 - * @return the GraphicsConfiguration of the monitor which currently has the
105.1974 - * input focus
105.1975 - */
105.1976 - private static GraphicsConfiguration getCurrentGraphicsConfiguration() {
105.1977 - Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
105.1978 - if (focusOwner != null) {
105.1979 - Window w = SwingUtilities.getWindowAncestor(focusOwner);
105.1980 - if (w != null) {
105.1981 - return w.getGraphicsConfiguration();
105.1982 - }
105.1983 - }
105.1984 -
105.1985 - return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
105.1986 - }
105.1987 -
105.1988 - /**
105.1989 - * Returns the usable area of the screen where applications can place its
105.1990 - * windows. The method subtracts from the screen the area of taskbars,
105.1991 - * system menus and the like. The screen this method applies to is the one
105.1992 - * which is considered current, ussually the one where the current input
105.1993 - * focus is.
105.1994 - *
105.1995 - * @return the rectangle of the screen where one can place windows
105.1996 - *
105.1997 - * @since 2.5
105.1998 - */
105.1999 - public static Rectangle getUsableScreenBounds() {
105.2000 - return getUsableScreenBounds(getCurrentGraphicsConfiguration());
105.2001 - }
105.2002 -
105.2003 - /**
105.2004 - * Returns the usable area of the screen where applications can place its
105.2005 - * windows. The method subtracts from the screen the area of taskbars,
105.2006 - * system menus and the like.
105.2007 - *
105.2008 - * @param gconf the GraphicsConfiguration of the monitor
105.2009 - * @return the rectangle of the screen where one can place windows
105.2010 - *
105.2011 - * @since 2.5
105.2012 - */
105.2013 - public static Rectangle getUsableScreenBounds(GraphicsConfiguration gconf) {
105.2014 - if (gconf == null) {
105.2015 - gconf = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
105.2016 - }
105.2017 -
105.2018 - Rectangle bounds = new Rectangle(gconf.getBounds());
105.2019 -
105.2020 - String str;
105.2021 -
105.2022 - str = System.getProperty("netbeans.screen.insets"); // NOI18N
105.2023 -
105.2024 - if (str != null) {
105.2025 - StringTokenizer st = new StringTokenizer(str, ", "); // NOI18N
105.2026 -
105.2027 - if (st.countTokens() == 4) {
105.2028 - try {
105.2029 - bounds.y = Integer.parseInt(st.nextToken());
105.2030 - bounds.x = Integer.parseInt(st.nextToken());
105.2031 - bounds.height -= (bounds.y + Integer.parseInt(st.nextToken()));
105.2032 - bounds.width -= (bounds.x + Integer.parseInt(st.nextToken()));
105.2033 - } catch (NumberFormatException ex) {
105.2034 - LOG.log(Level.WARNING, null, ex);
105.2035 - }
105.2036 - }
105.2037 -
105.2038 - return bounds;
105.2039 - }
105.2040 -
105.2041 - str = System.getProperty("netbeans.taskbar.height"); // NOI18N
105.2042 -
105.2043 - if (str != null) {
105.2044 - bounds.height -= Integer.getInteger(str, 0).intValue();
105.2045 -
105.2046 - return bounds;
105.2047 - }
105.2048 -
105.2049 - try {
105.2050 - Toolkit toolkit = Toolkit.getDefaultToolkit();
105.2051 - Insets insets = toolkit.getScreenInsets(gconf);
105.2052 - bounds.y += insets.top;
105.2053 - bounds.x += insets.left;
105.2054 - bounds.height -= (insets.top + insets.bottom);
105.2055 - bounds.width -= (insets.left + insets.right);
105.2056 - } catch (Exception ex) {
105.2057 - LOG.log(Level.WARNING, null, ex);
105.2058 - }
105.2059 -
105.2060 - return bounds;
105.2061 - }
105.2062 -
105.2063 - /**
105.2064 - * Helps client code place components on the center of the screen. It
105.2065 - * handles multiple monitor configuration correctly
105.2066 - *
105.2067 - * @param componentSize the size of the component
105.2068 - * @return bounds of the centered component
105.2069 - *
105.2070 - * @since 2.5
105.2071 - */
105.2072 - public static Rectangle findCenterBounds(Dimension componentSize) {
105.2073 - return findCenterBounds(getCurrentGraphicsConfiguration(), componentSize);
105.2074 - }
105.2075 -
105.2076 - /**
105.2077 - * Helps client code place components on the center of the screen. It
105.2078 - * handles multiple monitor configuration correctly
105.2079 - *
105.2080 - * @param gconf the GraphicsConfiguration of the monitor
105.2081 - * @param componentSize the size of the component
105.2082 - * @return bounds of the centered component
105.2083 - */
105.2084 - private static Rectangle findCenterBounds(GraphicsConfiguration gconf, Dimension componentSize) {
105.2085 - if (gconf == null) {
105.2086 - gconf = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
105.2087 - }
105.2088 -
105.2089 - Rectangle bounds = gconf.getBounds();
105.2090 -
105.2091 - return new Rectangle(
105.2092 - bounds.x + ((bounds.width - componentSize.width) / 2),
105.2093 - bounds.y + ((bounds.height - componentSize.height) / 2), componentSize.width, componentSize.height
105.2094 - );
105.2095 - }
105.2096 -
105.2097 - /** @return size of the screen. The size is modified for Windows OS
105.2098 - * - some points are subtracted to reflect a presence of the taskbar
105.2099 - *
105.2100 - * @deprecated this method is almost useless in multiple monitor configuration
105.2101 - *
105.2102 - * @see #getUsableScreenBounds()
105.2103 - * @see #findCenterBounds(Dimension)
105.2104 - */
105.2105 - @Deprecated
105.2106 - public static final Dimension getScreenSize() {
105.2107 - Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
105.2108 -
105.2109 - if (isWindows() && !Boolean.getBoolean("netbeans.no.taskbar")) {
105.2110 - screenSize.height -= TYPICAL_WINDOWS_TASKBAR_HEIGHT;
105.2111 - } else if (isMac()) {
105.2112 - screenSize.height -= TYPICAL_MACOSX_MENU_HEIGHT;
105.2113 - }
105.2114 -
105.2115 - return screenSize;
105.2116 - }
105.2117 -
105.2118 - /** Utility method for avoiding of memory leak in JDK 1.3 / JFileChooser.showDialog(...)
105.2119 - * @param parent
105.2120 - * @param approveButtonText
105.2121 - * @deprecated Not needed in JDK 1.4.
105.2122 - * @see <a href="@org-openide-filesystems@/org/openide/filesystems/FileChooserBuilder.html"><code>FileChooserBuilder</code></a>
105.2123 - */
105.2124 - @Deprecated
105.2125 - public static final int showJFileChooser(
105.2126 - javax.swing.JFileChooser chooser, java.awt.Component parent, java.lang.String approveButtonText
105.2127 - ) {
105.2128 - if (approveButtonText != null) {
105.2129 - chooser.setApproveButtonText(approveButtonText);
105.2130 - chooser.setDialogType(javax.swing.JFileChooser.CUSTOM_DIALOG);
105.2131 - }
105.2132 -
105.2133 - Frame frame = null;
105.2134 - Dialog parentDlg = null;
105.2135 -
105.2136 - if (parent instanceof Dialog) {
105.2137 - parentDlg = (Dialog) parent;
105.2138 - } else {
105.2139 - frame = (parent instanceof java.awt.Frame) ? (Frame) parent
105.2140 - : (Frame) javax.swing.SwingUtilities.getAncestorOfClass(
105.2141 - Frame.class, parent
105.2142 - );
105.2143 - }
105.2144 -
105.2145 - String title = chooser.getDialogTitle();
105.2146 -
105.2147 - if (title == null) {
105.2148 - title = chooser.getUI().getDialogTitle(chooser);
105.2149 - }
105.2150 -
105.2151 - final javax.swing.JDialog dialog;
105.2152 -
105.2153 - if (parentDlg != null) {
105.2154 - dialog = new javax.swing.JDialog(parentDlg, title, true);
105.2155 - } else {
105.2156 - dialog = new javax.swing.JDialog(frame, title, true);
105.2157 - }
105.2158 -
105.2159 - dialog.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
105.2160 -
105.2161 - Container contentPane = dialog.getContentPane();
105.2162 - contentPane.setLayout(new BorderLayout());
105.2163 - contentPane.add(chooser, BorderLayout.CENTER);
105.2164 -
105.2165 - dialog.pack();
105.2166 - dialog.setBounds(findCenterBounds(parent.getGraphicsConfiguration(), dialog.getSize()));
105.2167 -
105.2168 - chooser.rescanCurrentDirectory();
105.2169 -
105.2170 - final int[] retValue = {javax.swing.JFileChooser.CANCEL_OPTION};
105.2171 -
105.2172 - java.awt.event.ActionListener l = new java.awt.event.ActionListener() {
105.2173 - public void actionPerformed(java.awt.event.ActionEvent ev) {
105.2174 - if (javax.swing.JFileChooser.APPROVE_SELECTION.equals(ev.getActionCommand())) {
105.2175 - retValue[0] = javax.swing.JFileChooser.APPROVE_OPTION;
105.2176 - }
105.2177 -
105.2178 - dialog.setVisible(false);
105.2179 - dialog.dispose();
105.2180 - }
105.2181 - };
105.2182 -
105.2183 - chooser.addActionListener(l);
105.2184 -
105.2185 - dialog.show();
105.2186 -
105.2187 - return retValue[0];
105.2188 - }
105.2189 -
105.2190 - /** Sort a list according to a specified partial order.
105.2191 - * Note that in the current implementation, the comparator will be called
105.2192 - * exactly once for each distinct pair of list elements, ignoring order,
105.2193 - * so caching its results is a waste of time.
105.2194 - * @param l the list to sort (will not be modified)
105.2195 - * @param c a comparator to impose the partial order; "equal" means that the elements
105.2196 - * are not ordered with respect to one another, i.e. may be only a partial order
105.2197 - * @param stable whether to attempt a stable sort, meaning that the position of elements
105.2198 - * will be disturbed as little as possible; might be slightly slower
105.2199 - * @return the partially-sorted list
105.2200 - * @throws UnorderableException if the specified partial order is inconsistent on this list
105.2201 - * @deprecated Deprecated in favor of the potentially much faster (and possibly more correct) {@link #topologicalSort}.
105.2202 - */
105.2203 - @SuppressWarnings("unchecked") // do not bother, it is deprecated anyway
105.2204 - @Deprecated
105.2205 - public static List partialSort(List l, Comparator c, boolean stable)
105.2206 - throws UnorderableException {
105.2207 - // map from objects in the list to null or sets of objects they are greater than
105.2208 - // (i.e. must appear after):
105.2209 - Map deps = new HashMap(); // Map<Object,Set<Object>>
105.2210 - int size = l.size();
105.2211 -
105.2212 - // Create a table of dependencies.
105.2213 - for (int i = 0; i < size; i++) {
105.2214 - for (int j = i + 1; j < size; j++) {
105.2215 - int cmp = c.compare(l.get(i), l.get(j));
105.2216 -
105.2217 - if (cmp != 0) {
105.2218 - Object earlier = l.get((cmp < 0) ? i : j);
105.2219 - Object later = l.get((cmp > 0) ? i : j);
105.2220 - Set s = (Set) deps.get(later);
105.2221 -
105.2222 - if (s == null) {
105.2223 - deps.put(later, s = new HashSet());
105.2224 - }
105.2225 -
105.2226 - s.add(earlier);
105.2227 - }
105.2228 - }
105.2229 - }
105.2230 -
105.2231 - // Lists of items to process, and items sorted.
105.2232 - List left = new LinkedList(l);
105.2233 - List sorted = new ArrayList(size);
105.2234 -
105.2235 - while (left.size() > 0) {
105.2236 - boolean stillGoing = false;
105.2237 - Iterator it = left.iterator();
105.2238 -
105.2239 - while (it.hasNext()) {
105.2240 - Object elt = it.next();
105.2241 - Set eltDeps = (Set) deps.get(elt);
105.2242 -
105.2243 - if ((eltDeps == null) || (eltDeps.size() == 0)) {
105.2244 - // This one is OK to add to the result now.
105.2245 - it.remove();
105.2246 - stillGoing = true;
105.2247 - sorted.add(elt);
105.2248 -
105.2249 - // Mark other elements that should be later
105.2250 - // than this as having their dep satisfied.
105.2251 - Iterator it2 = left.iterator();
105.2252 -
105.2253 - while (it2.hasNext()) {
105.2254 - Object elt2 = it2.next();
105.2255 - Set eltDeps2 = (Set) deps.get(elt2);
105.2256 -
105.2257 - if (eltDeps2 != null) {
105.2258 - eltDeps2.remove(elt);
105.2259 - }
105.2260 - }
105.2261 -
105.2262 - if (stable) {
105.2263 - break;
105.2264 - }
105.2265 - }
105.2266 - }
105.2267 -
105.2268 - if (!stillGoing) {
105.2269 - // Clean up deps to only include "interesting" problems.
105.2270 - it = deps.entrySet().iterator();
105.2271 -
105.2272 - while (it.hasNext()) {
105.2273 - Map.Entry me = (Map.Entry) it.next();
105.2274 -
105.2275 - if (!left.contains(me.getKey())) {
105.2276 - it.remove();
105.2277 - } else {
105.2278 - Set s = (Set) me.getValue();
105.2279 - Iterator it2 = s.iterator();
105.2280 -
105.2281 - while (it2.hasNext()) {
105.2282 - if (!left.contains(it2.next())) {
105.2283 - it2.remove();
105.2284 - }
105.2285 - }
105.2286 -
105.2287 - if (s.isEmpty()) {
105.2288 - it.remove();
105.2289 - }
105.2290 - }
105.2291 - }
105.2292 -
105.2293 - throw new UnorderableException(left, deps);
105.2294 - }
105.2295 - }
105.2296 -
105.2297 - return sorted;
105.2298 - }
105.2299 -
105.2300 - /**
105.2301 - * Topologically sort some objects.
105.2302 - * <p>There may not be any nulls among the objects, nor duplicates
105.2303 - * (as per hash/equals), nor duplicates among the edge lists.
105.2304 - * The edge map need not contain an entry for every object, only if it
105.2305 - * has some outgoing edges (empty but not null map values are permitted).
105.2306 - * The edge map shall not contain neither keys nor value entries for objects not
105.2307 - * in the collection to be sorted, if that happens they will be ignored (since version 7.9).
105.2308 - * <p>The incoming parameters will not be modified; they must not be changed
105.2309 - * during the call and possible calls to TopologicalSortException methods.
105.2310 - * The returned list will support modifications.
105.2311 - * <p>There is a <em>weak</em> stability guarantee: if there are no edges
105.2312 - * which contradict the incoming order, the resulting list will be in the same
105.2313 - * order as the incoming elements. However if some elements need to be rearranged,
105.2314 - * it is <em>not</em> guaranteed that others will not also be rearranged, even
105.2315 - * if they did not strictly speaking need to be.
105.2316 - * @param c a collection of objects to be topologically sorted
105.2317 - * @param edges constraints among those objects, of type <code>Map<Object,Collection></code>;
105.2318 - * if an object is a key in this map, the resulting order will
105.2319 - * have that object before any objects listed in the value
105.2320 - * @return a partial ordering of the objects in the collection,
105.2321 - * @exception TopologicalSortException if the sort cannot succeed due to cycles in the graph, the
105.2322 - * exception contains additional information to describe and possibly recover from the error
105.2323 - * @since 3.30
105.2324 - * @see <a href="http://www.netbeans.org/issues/show_bug.cgi?id=27286">Issue #27286</a>
105.2325 - */
105.2326 - public static <T> List<T> topologicalSort(Collection<T> c, Map<? super T, ? extends Collection<? extends T>> edges)
105.2327 - throws TopologicalSortException {
105.2328 - Map<T,Boolean> finished = new HashMap<T,Boolean>();
105.2329 - List<T> r = new ArrayList<T>(Math.max(c.size(), 1));
105.2330 - List<T> cRev = new ArrayList<T>(c);
105.2331 - Collections.reverse(cRev);
105.2332 -
105.2333 - Iterator<T> it = cRev.iterator();
105.2334 -
105.2335 - while (it.hasNext()) {
105.2336 - List<T> cycle = visit(it.next(), edges, finished, r);
105.2337 -
105.2338 - if (cycle != null) {
105.2339 - throw new TopologicalSortException(cRev, edges);
105.2340 - }
105.2341 - }
105.2342 -
105.2343 - Collections.reverse(r);
105.2344 - if (r.size() != c.size()) {
105.2345 - r.retainAll(c);
105.2346 - }
105.2347 -
105.2348 - return r;
105.2349 - }
105.2350 -
105.2351 - /**
105.2352 - * Visit one node in the DAG.
105.2353 - * @param node node to visit
105.2354 - * @param edges edges in the DAG
105.2355 - * @param finished which nodes are finished; a node has no entry if it has not yet
105.2356 - * been visited, else it is set to false while recurring and true
105.2357 - * when it has finished
105.2358 - * @param r the order in progress
105.2359 - * @return list with detected cycle
105.2360 - */
105.2361 - static <T> List<T> visit(
105.2362 - T node,
105.2363 - Map<? super T, ? extends Collection<? extends T>> edges,
105.2364 - Map<T,Boolean> finished,
105.2365 - List<T> r
105.2366 - ) {
105.2367 - Boolean b = finished.get(node);
105.2368 -
105.2369 - //System.err.println("node=" + node + " color=" + b);
105.2370 - if (b != null) {
105.2371 - if (b.booleanValue()) {
105.2372 - return null;
105.2373 - }
105.2374 -
105.2375 - ArrayList<T> cycle = new ArrayList<T>();
105.2376 - cycle.add(node);
105.2377 - finished.put(node, null);
105.2378 -
105.2379 - return cycle;
105.2380 - }
105.2381 -
105.2382 - Collection<? extends T> e = edges.get(node);
105.2383 -
105.2384 - if (e != null) {
105.2385 - finished.put(node, Boolean.FALSE);
105.2386 -
105.2387 - Iterator<? extends T> it = e.iterator();
105.2388 -
105.2389 - while (it.hasNext()) {
105.2390 - List<T> cycle = visit(it.next(), edges, finished, r);
105.2391 -
105.2392 - if (cycle != null) {
105.2393 - if (cycle instanceof ArrayList) {
105.2394 - // if cycle instanceof ArrayList we are still in the
105.2395 - // cycle and we want to collect new members
105.2396 - if (Boolean.FALSE == finished.get(node)) {
105.2397 - // another member in the cycle
105.2398 - cycle.add(node);
105.2399 - } else {
105.2400 - // we have reached the head of the cycle
105.2401 - // do not add additional cycles anymore
105.2402 - Collections.reverse(cycle);
105.2403 -
105.2404 - // changing cycle to not be ArrayList
105.2405 - cycle = Collections.unmodifiableList(cycle);
105.2406 - }
105.2407 - }
105.2408 -
105.2409 - // mark this node as tested
105.2410 - finished.put(node, Boolean.TRUE);
105.2411 -
105.2412 - // and report an error
105.2413 - return cycle;
105.2414 - }
105.2415 - }
105.2416 - }
105.2417 -
105.2418 - finished.put(node, Boolean.TRUE);
105.2419 - r.add(node);
105.2420 -
105.2421 - return null;
105.2422 - }
105.2423 -
105.2424 - /** Provides support for parts of the system that deal with classnames
105.2425 - * (use <code>Class.forName</code>, <code>NbObjectInputStream</code>, etc.).
105.2426 - * <P>
105.2427 - * Often class names (especially package names) changes during lifecycle
105.2428 - * of a module. When some piece of the system stores the name of a class
105.2429 - * in certain point of a time and wants to find the correct <code>Class</code>
105.2430 - * later it needs to count with the possibility of rename.
105.2431 - * <P>
105.2432 - * For such purposes this method has been created. It allows modules to
105.2433 - * register their classes that changed names and other parts of system that
105.2434 - * deal with class names to find the correct names.
105.2435 - * <P>
105.2436 - * To register a mapping from old class names to new ones create a file
105.2437 - * <code>META-INF/netbeans/translate.names</code> in your module and fill it
105.2438 - * with your mapping:
105.2439 - * <PRE>
105.2440 - * #
105.2441 - * # Mapping of legacy classes to new ones
105.2442 - * #
105.2443 - *
105.2444 - * org.oldpackage.MyClass=org.newpackage.MyClass # rename of package for one class
105.2445 - * org.mypackage.OldClass=org.mypackage.NewClass # rename of class in a package
105.2446 - *
105.2447 - * # rename of class and package
105.2448 - * org.oldpackage.OldClass=org.newpackage.NewClass
105.2449 - *
105.2450 - * # rename of whole package
105.2451 - * org.someoldpackage=org.my.new.package.structure
105.2452 - *
105.2453 - * # class was removed without replacement
105.2454 - * org.mypackage.OldClass=
105.2455 - *
105.2456 - * </PRE>
105.2457 - * Btw. one can use spaces instead of <code>=</code> sign.
105.2458 - * For a real world example
105.2459 - * check the
105.2460 - * <a href="http://www.netbeans.org/source/browse/xml/text-edit/compat/src/META-INF/netbeans/">
105.2461 - * xml module</a>.
105.2462 - *
105.2463 - * <P>
105.2464 - * For purposes of <link>org.openide.util.io.NbObjectInputStream</link> there is
105.2465 - * a following special convention:
105.2466 - * If the
105.2467 - * className is not listed as one that is to be renamed, the returned
105.2468 - * string == className, if the className is registered to be renamed
105.2469 - * than the className != returned value, even in a case when className.equals (retValue)
105.2470 - *
105.2471 - * @param className fully qualified name of a class to translate
105.2472 - * @return new name of the class according to renaming rules.
105.2473 - */
105.2474 - public static String translate(final String className) {
105.2475 - checkMapping();
105.2476 -
105.2477 - RE exp;
105.2478 -
105.2479 - synchronized (TRANS_LOCK) {
105.2480 - exp = transExp;
105.2481 - }
105.2482 -
105.2483 - if (exp == null) {
105.2484 - // no transition table found
105.2485 - return className;
105.2486 - }
105.2487 -
105.2488 - synchronized (exp) {
105.2489 - // refusing convertions as fast as possible
105.2490 - return exp.convert(className);
105.2491 - }
105.2492 - }
105.2493 -
105.2494 - /** Loads all resources that contain renaming information.
105.2495 - * @param l classloader to load packages from
105.2496 - */
105.2497 - private static void checkMapping() {
105.2498 - // test if we run in test mode
105.2499 - if (transLoader == TRANS_LOCK) {
105.2500 - // no check
105.2501 - return;
105.2502 - }
105.2503 -
105.2504 - ClassLoader current = Lookup.getDefault().lookup(ClassLoader.class);
105.2505 -
105.2506 - if (current == null) {
105.2507 - current = ClassLoader.getSystemClassLoader();
105.2508 - }
105.2509 -
105.2510 - if (transLoader == current) {
105.2511 - // no change, no rescan
105.2512 - return;
105.2513 - }
105.2514 -
105.2515 - initForLoader(current, current);
105.2516 - }
105.2517 -
105.2518 - /* Initializes the content of transition table from a classloader.
105.2519 - * @param loader loader to read data from
105.2520 - * @param set loader to set as the transLoader or null if we run in test mode
105.2521 - */
105.2522 - static void initForLoader(ClassLoader current, Object set) {
105.2523 - if (set == null) {
105.2524 - set = TRANS_LOCK;
105.2525 - }
105.2526 -
105.2527 - Enumeration en;
105.2528 -
105.2529 - try {
105.2530 - en = current.getResources("META-INF/netbeans/translate.names");
105.2531 - } catch (IOException ex) {
105.2532 - LOG.log(Level.WARNING, null, ex);
105.2533 - en = null;
105.2534 - }
105.2535 -
105.2536 - if ((en == null) || !en.hasMoreElements()) {
105.2537 - synchronized (TRANS_LOCK) {
105.2538 - transLoader = set;
105.2539 - transExp = null;
105.2540 - }
105.2541 -
105.2542 - return;
105.2543 - }
105.2544 -
105.2545 - // format of line in the meta files
105.2546 - //
105.2547 - // # comments are allowed
105.2548 - // a.name.in.a.Package=another.Name # with comment is allowed
105.2549 - // for.compatibility.one.can.use.Space instead.of.Equal
105.2550 - //
105.2551 - RE re = null;
105.2552 -
105.2553 - // [pnejedly:perf] commented out. The RegExp based translation was way slower
105.2554 - // than the hand-written RE13
105.2555 - // if (Dependency.JAVA_SPEC.compareTo(new SpecificationVersion("1.4")) >= 0) { // NOI18N
105.2556 - // try {
105.2557 - // re = (RE)Class.forName ("org.openide.util.RE14").newInstance ();
105.2558 - // } catch (ThreadDeath t) {
105.2559 - // throw t;
105.2560 - // } catch (Throwable t) {
105.2561 - // }
105.2562 - // }
105.2563 - // if (re == null) {
105.2564 - re = new RE13();
105.2565 -
105.2566 - // }
105.2567 - TreeSet<String[]> list = new TreeSet<String[]>(
105.2568 - new Comparator<String[]>() {
105.2569 - public int compare(String[] o1, String[] o2) {
105.2570 - String s1 = o1[0];
105.2571 - String s2 = o2[0];
105.2572 -
105.2573 - int i1 = s1.length();
105.2574 - int i2 = s2.length();
105.2575 -
105.2576 - if (i1 != i2) {
105.2577 - return i2 - i1;
105.2578 - }
105.2579 -
105.2580 - return s2.compareTo(s1);
105.2581 - }
105.2582 - }
105.2583 - );
105.2584 -
105.2585 - while (en.hasMoreElements()) {
105.2586 - URL u = (URL) en.nextElement();
105.2587 -
105.2588 - try {
105.2589 - BufferedReader reader = new BufferedReader(
105.2590 - new InputStreamReader(u.openStream(), "UTF8") // use explicit encoding //NOI18N
105.2591 - );
105.2592 - loadTranslationFile(re, reader, list);
105.2593 - reader.close();
105.2594 - } catch (IOException ex) {
105.2595 - LOG.log(Level.WARNING, "Problematic file: " + u);
105.2596 - LOG.log(Level.WARNING, null, ex);
105.2597 - }
105.2598 - }
105.2599 -
105.2600 - // construct a regular expression of following form. Let "1", "2", "3", "4"
105.2601 - // be the keys:
105.2602 - // "^
105.2603 - // thus if 4 is matched five groups will be created
105.2604 - String[] arr = new String[list.size()];
105.2605 - String[] pattern = new String[arr.length];
105.2606 -
105.2607 - int i = 0;
105.2608 - Iterator it = list.iterator();
105.2609 -
105.2610 - while (it.hasNext()) {
105.2611 - String[] pair = (String[]) it.next();
105.2612 - arr[i] = pair[1].intern(); // name of the track
105.2613 - pattern[i] = pair[0]; // original object
105.2614 - i++;
105.2615 - }
105.2616 -
105.2617 - synchronized (TRANS_LOCK) {
105.2618 - // last check
105.2619 - if (arr.length == 0) {
105.2620 - transExp = null;
105.2621 - } else {
105.2622 - transExp = re;
105.2623 - transExp.init(pattern, arr);
105.2624 - }
105.2625 -
105.2626 - transLoader = set;
105.2627 - }
105.2628 - }
105.2629 -
105.2630 - /**
105.2631 - * Load single translation file.
105.2632 - * @param resource URL identifiing transaction table
105.2633 - * @param results will be filled with String[2]
105.2634 - */
105.2635 - private static void loadTranslationFile(RE re, BufferedReader reader, Set<String[]> results)
105.2636 - throws IOException {
105.2637 - for (;;) {
105.2638 - String line = reader.readLine();
105.2639 -
105.2640 - if (line == null) {
105.2641 - break;
105.2642 - }
105.2643 -
105.2644 - if ((line.length() == 0) || line.startsWith("#")) { // NOI18N
105.2645 -
105.2646 - continue;
105.2647 - }
105.2648 -
105.2649 - String[] pair = re.readPair(line);
105.2650 -
105.2651 - if (pair == null) {
105.2652 - throw new java.io.InvalidObjectException("Line is invalid: " + line);
105.2653 - }
105.2654 -
105.2655 - results.add(pair);
105.2656 - }
105.2657 - }
105.2658 -
105.2659 - /** This method merges two images into the new one. The second image is drawn
105.2660 - * over the first one with its top-left corner at x, y. Images need not be of the same size.
105.2661 - * New image will have a size of max(second image size + top-left corner, first image size).
105.2662 - * Method is used mostly when second image contains transparent pixels (e.g. for badging).
105.2663 - * @param image1 underlying image
105.2664 - * @param image2 second image
105.2665 - * @param x x position of top-left corner
105.2666 - * @param y y position of top-left corner
105.2667 - * @return new merged image
105.2668 - * @deprecated Use {@link ImageUtilities#mergeImages}.
105.2669 - */
105.2670 - @Deprecated
105.2671 - public static final Image mergeImages(Image image1, Image image2, int x, int y) {
105.2672 - return ImageUtilities.mergeImages(image1, image2, x, y);
105.2673 - }
105.2674 -
105.2675 - /**
105.2676 - * Loads an image from the specified resource ID. The image is loaded using the "system" classloader registered in
105.2677 - * Lookup.
105.2678 - * @param resourceID resource path of the icon (no initial slash)
105.2679 - * @return icon's Image, or null, if the icon cannot be loaded.
105.2680 - * @deprecated Use {@link ImageUtilities#loadImage(java.lang.String)}.
105.2681 - */
105.2682 - @Deprecated
105.2683 - public static final Image loadImage(String resourceID) {
105.2684 - return ImageUtilities.loadImage(resourceID);
105.2685 - }
105.2686 -
105.2687 - /**
105.2688 - * Converts given icon to a {@link java.awt.Image}.
105.2689 - *
105.2690 - * @param icon {@link javax.swing.Icon} to be converted.
105.2691 - * @since 7.3
105.2692 - * @deprecated Use {@link ImageUtilities#icon2Image}.
105.2693 - */
105.2694 - @Deprecated
105.2695 - public static final Image icon2Image(Icon icon) {
105.2696 - return ImageUtilities.icon2Image(icon);
105.2697 - }
105.2698 -
105.2699 - /** Builds a popup menu from actions for provided context specified by
105.2700 - * <code>Lookup</code>.
105.2701 - * Takes list of actions and for actions whic are instances of
105.2702 - * <code>ContextAwareAction</code> creates and uses the context aware instance.
105.2703 - * Then gets the action presenter or simple menu item for the action to the
105.2704 - * popup menu for each action (or separator for each 'lonely' null array member).
105.2705 - *
105.2706 - * @param actions array of actions to build menu for. Can contain null
105.2707 - * elements, they will be replaced by separators
105.2708 - * @param context the context for which the popup is build
105.2709 - * @return the constructed popup menu
105.2710 - * @see ContextAwareAction
105.2711 - * @since 3.29
105.2712 - */
105.2713 - public static JPopupMenu actionsToPopup(Action[] actions, Lookup context) {
105.2714 - // keeps actions for which was menu item created already (do not add them twice)
105.2715 - Set<Action> counted = new HashSet<Action>();
105.2716 - // components to be added (separators are null)
105.2717 - List<Component> components = new ArrayList<Component>();
105.2718 -
105.2719 - for (Action action : actions) {
105.2720 - if (action != null && counted.add(action)) {
105.2721 - // switch to replacement action if there is some
105.2722 - if (action instanceof ContextAwareAction) {
105.2723 - Action contextAwareAction = ((ContextAwareAction) action).createContextAwareInstance(context);
105.2724 - if (contextAwareAction == null) {
105.2725 - Logger.getLogger(Utilities.class.getName()).warning(
105.2726 - "ContextAwareAction.createContextAwareInstance(context) returns null. That is illegal!" // NOI18N
105.2727 - + " action=" + action + ", context=" + context); // NOI18N
105.2728 - } else {
105.2729 - action = contextAwareAction;
105.2730 - }
105.2731 - }
105.2732 -
105.2733 - JMenuItem item;
105.2734 - if (action instanceof Presenter.Popup) {
105.2735 - item = ((Presenter.Popup) action).getPopupPresenter();
105.2736 - if (item == null) {
105.2737 - Logger.getLogger(Utilities.class.getName()).warning(
105.2738 - "findContextMenuImpl, getPopupPresenter returning null for " + action); // NOI18N
105.2739 - continue;
105.2740 - }
105.2741 - } else {
105.2742 - // We need to correctly handle mnemonics with '&' etc.
105.2743 - item = ActionPresenterProvider.getDefault().createPopupPresenter(action);
105.2744 - }
105.2745 -
105.2746 - for (Component c : ActionPresenterProvider.getDefault().convertComponents(item)) {
105.2747 - if (c instanceof JSeparator) {
105.2748 - components.add(null);
105.2749 - } else {
105.2750 - components.add(c);
105.2751 - }
105.2752 - }
105.2753 - } else {
105.2754 - components.add(null);
105.2755 - }
105.2756 - }
105.2757 -
105.2758 - // Now create actual menu. Strip adjacent, leading, and trailing separators.
105.2759 - JPopupMenu menu = ActionPresenterProvider.getDefault().createEmptyPopup();
105.2760 - boolean nonempty = false; // has anything been added yet?
105.2761 - boolean pendingSep = false; // should there be a separator before any following item?
105.2762 - for (Component c : components) {
105.2763 - if (c == null) {
105.2764 - pendingSep = nonempty;
105.2765 - } else {
105.2766 - nonempty = true;
105.2767 - if (pendingSep) {
105.2768 - pendingSep = false;
105.2769 - menu.addSeparator();
105.2770 - }
105.2771 - menu.add(c);
105.2772 - }
105.2773 - }
105.2774 - return menu;
105.2775 - }
105.2776 -
105.2777 - /** Builds a popup menu for provided component. It retrieves context
105.2778 - * (lookup) from provided component instance or one of its parent
105.2779 - * (it searches up to the hierarchy for <code>Lookup.Provider</code> instance).
105.2780 - * If none of the components is <code>Lookup.Provider</code> instance, then
105.2781 - * it is created context which is fed with composite ActionMap which delegates
105.2782 - * to all components up to hierarchy started from the specified one.
105.2783 - * Then <code>actionsToPopup(Action[], Lookup)</code>} is called with
105.2784 - * the found <code>Lookup</code> instance, which actually creates a popup menu.
105.2785 - *
105.2786 - * @param actions array of actions to build menu for. Can contain null
105.2787 - * elements, they will be replaced by separators
105.2788 - * @param component a component in which to search for a context
105.2789 - * @return the constructed popup menu
105.2790 - * @see Lookup.Provider
105.2791 - * @see #actionsToPopup(Action[], Lookup)
105.2792 - * @since 3.29
105.2793 - */
105.2794 - public static javax.swing.JPopupMenu actionsToPopup(Action[] actions, java.awt.Component component) {
105.2795 - Lookup lookup = null;
105.2796 -
105.2797 - for (Component c = component; c != null; c = c.getParent()) {
105.2798 - if (c instanceof Lookup.Provider) {
105.2799 - lookup = ((Lookup.Provider) c).getLookup();
105.2800 -
105.2801 - if (lookup != null) {
105.2802 - break;
105.2803 - }
105.2804 - }
105.2805 - }
105.2806 -
105.2807 - if (lookup == null) {
105.2808 - // Fallback to composite action map, even it is questionable,
105.2809 - // whether we should support component which is not (nor
105.2810 - // none of its parents) lookup provider.
105.2811 - UtilitiesCompositeActionMap map = new UtilitiesCompositeActionMap(component);
105.2812 - lookup = org.openide.util.lookup.Lookups.singleton(map);
105.2813 - }
105.2814 -
105.2815 - return actionsToPopup(actions, lookup);
105.2816 - }
105.2817 -
105.2818 - /**
105.2819 - * Load a menu sequence from a lookup path.
105.2820 - * Any {@link Action} instances are returned as is;
105.2821 - * any {@link JSeparator} instances are translated to nulls.
105.2822 - * Warnings are logged for any other instances.
105.2823 - * @param path a path as given to {@link Lookups#forPath}, generally a layer folder name
105.2824 - * @return a list of actions interspersed with null separators
105.2825 - * @since org.openide.util 7.14
105.2826 - */
105.2827 - public static List<? extends Action> actionsForPath(String path) {
105.2828 - List<Action> actions = new ArrayList<Action>();
105.2829 - for (Lookup.Item<Object> item : Lookups.forPath(path).lookupResult(Object.class).allItems()) {
105.2830 - if (Action.class.isAssignableFrom(item.getType())) {
105.2831 - Object instance = item.getInstance();
105.2832 - if (instance != null) {
105.2833 - actions.add((Action) instance);
105.2834 - }
105.2835 - } else if (JSeparator.class.isAssignableFrom(item.getType())) {
105.2836 - actions.add(null);
105.2837 - } else {
105.2838 - Logger.getLogger(Utilities.class.getName()).warning("Unrecognized object of " + item.getType() + " found in actions path " + path);
105.2839 - }
105.2840 - }
105.2841 - return actions;
105.2842 - }
105.2843 -
105.2844 - /**
105.2845 - * Global context for actions. Toolbar, menu or any other "global"
105.2846 - * action presenters shall operate in this context.
105.2847 - * Presenters for context menu items should <em>not</em> use
105.2848 - * this method; instead see {@link ContextAwareAction}.
105.2849 - * @see ContextGlobalProvider
105.2850 - * @see ContextAwareAction
105.2851 - * @see <a href="http://wiki.netbeans.org/DevFaqActionContextSensitive">NetBeans FAQ</a>
105.2852 - * @return the context for actions
105.2853 - * @since 4.10
105.2854 - */
105.2855 - public static Lookup actionsGlobalContext() {
105.2856 - synchronized (ContextGlobalProvider.class) {
105.2857 - if (global != null) {
105.2858 - return global;
105.2859 - }
105.2860 - }
105.2861 -
105.2862 - ContextGlobalProvider p = Lookup.getDefault().lookup(ContextGlobalProvider.class);
105.2863 - Lookup l = (p == null) ? Lookup.EMPTY : p.createGlobalContext();
105.2864 -
105.2865 - synchronized (ContextGlobalProvider.class) {
105.2866 - if (global == null) {
105.2867 - global = l;
105.2868 - }
105.2869 -
105.2870 - return global;
105.2871 - }
105.2872 - }
105.2873 -
105.2874 - //
105.2875 - // end of actions stuff
105.2876 - //
105.2877 -
105.2878 - /**
105.2879 - * Loads an image based on resource path.
105.2880 - * Exactly like {@link #loadImage(String)} but may do a localized search.
105.2881 - * For example, requesting <samp>org/netbeans/modules/foo/resources/foo.gif</samp>
105.2882 - * might actually find <samp>org/netbeans/modules/foo/resources/foo_ja.gif</samp>
105.2883 - * or <samp>org/netbeans/modules/foo/resources/foo_mybranding.gif</samp>.
105.2884 - *
105.2885 - * <p>Caching of loaded images can be used internally to improve performance.
105.2886 - *
105.2887 - * @since 3.24
105.2888 - * @deprecated Use {@link ImageUtilities#loadImage(java.lang.String, boolean)}.
105.2889 - */
105.2890 - @Deprecated
105.2891 - public static final Image loadImage(String resource, boolean localized) {
105.2892 - return ImageUtilities.loadImage(resource, localized);
105.2893 - }
105.2894 -
105.2895 - /**
105.2896 - * Returns a cursor with an arrow and an hourglass (or stop watch) badge,
105.2897 - * to be used when a component is busy but the UI is still responding to the user.
105.2898 - *
105.2899 - * Similar to the predefined {@link Cursor#WAIT_CURSOR}, but has an arrow to indicate
105.2900 - * a still-responsive UI.
105.2901 - *
105.2902 - * <p>Typically you will set the cursor only temporarily:
105.2903 - *
105.2904 - * <pre>
105.2905 - * <font class="comment">// code is running in other then event dispatch thread</font>
105.2906 - * currentComponent.setCursor(Utilities.createProgressCursor(currentComponent));
105.2907 - * <font class="keyword">try</font> {
105.2908 - * <font class="comment">// perform some work in other than event dispatch thread
105.2909 - * // (do not block UI)</font>
105.2910 - * } <font class="keyword">finally</font> {
105.2911 - * currentComponent.setCursor(<font class="constant">null</font>);
105.2912 - * }
105.2913 - * </pre>
105.2914 - *
105.2915 - * <p>This implementation provides one cursor for all Mac systems, one for all
105.2916 - * Unix systems (regardless of window manager), and one for all other systems
105.2917 - * including Windows. Note: The cursor does not have to look native in some
105.2918 - * cases on some platforms!
105.2919 - *
105.2920 - * @param component the non-null component that will use the progress cursor
105.2921 - * @return a progress cursor (Unix, Windows or Mac)
105.2922 - *
105.2923 - * @since 3.23
105.2924 - */
105.2925 - public static final Cursor createProgressCursor(Component component) {
105.2926 - // refuse null component
105.2927 - if (component == null) {
105.2928 - throw new NullPointerException("Given component is null"); //NOI18N
105.2929 - }
105.2930 -
105.2931 - Image image = null;
105.2932 -
105.2933 - // First check for Mac because its part of the Unix_Mask
105.2934 - if (isMac()) {
105.2935 - image = ImageUtilities.loadImage("org/openide/util/progress-cursor-mac.gif"); //NOI18N
105.2936 - } else if (isUnix()) {
105.2937 - image = ImageUtilities.loadImage("org/openide/util/progress-cursor-motif.gif"); //NOI18N
105.2938 - }
105.2939 - // All other OS, including Windows, use Windows cursor
105.2940 - else {
105.2941 - image = ImageUtilities.loadImage("org/openide/util/progress-cursor-win.gif"); //NOI18N
105.2942 - }
105.2943 -
105.2944 - return createCustomCursor(component, image, "PROGRESS_CURSOR"); //NOI18N
105.2945 - }
105.2946 -
105.2947 - // added to fix issue #30665 (bad size on linux)
105.2948 - public static Cursor createCustomCursor(Component component, Image icon, String name) {
105.2949 - Toolkit t = component.getToolkit();
105.2950 - Dimension d = t.getBestCursorSize(16, 16);
105.2951 - Image i = icon;
105.2952 -
105.2953 - if (d.width != icon.getWidth(null)) {
105.2954 - if (((d.width) == 0) && (d.height == 0)) {
105.2955 - // system doesn't support custom cursors, falling back
105.2956 - return Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);
105.2957 - }
105.2958 -
105.2959 - // need to resize the icon
105.2960 - Image empty = ImageUtilities.createBufferedImage(d.width, d.height);
105.2961 - i = ImageUtilities.mergeImages(icon, empty, 0, 0);
105.2962 - }
105.2963 -
105.2964 - return t.createCustomCursor(i, new Point(1, 1), name);
105.2965 - }
105.2966 -
105.2967 - /** Attaches asynchronous init job to given component.
105.2968 - * {@link AsyncGUIJob#construct()} will be called after first
105.2969 - * paint, when paint event arrives. Later, {@link AsyncGUIJob#finished()}
105.2970 - * will be called according to the rules of the <code>AsyncGUIJob</code> interface.
105.2971 - *
105.2972 - * Useful for components that have slower initialization phase, component
105.2973 - * can benefit from more responsive behaviour during init.
105.2974 - *
105.2975 - * @param comp4Init Regular component in its pre-inited state, state in which
105.2976 - * component will be shown between first paint and init completion.
105.2977 - * @param initJob Initialization job to be called asynchronously. Job can
105.2978 - * optionally implement {@link Cancellable}
105.2979 - * interface for proper cancel logic. Cancel method will be called
105.2980 - * when component stops to be showing during job's progress.
105.2981 - * See {@link java.awt.Component#isShowing}
105.2982 - *
105.2983 - * @since 3.36
105.2984 - */
105.2985 - public static final void attachInitJob(Component comp4Init, AsyncGUIJob initJob) {
105.2986 - new AsyncInitSupport(comp4Init, initJob);
105.2987 - }
105.2988 -
105.2989 - /**
105.2990 - * Convert a file to a matching <code>file:</code> URL.
105.2991 - * @param f a file (absolute only)
105.2992 - * @return a URL using the <code>file</code> protocol
105.2993 - * @throws MalformedURLException for no good reason
105.2994 - * @see #toFile
105.2995 - * @see <a href="http://www.netbeans.org/issues/show_bug.cgi?id=29711">Issue #29711</a>
105.2996 - * @since 3.26
105.2997 - * @deprecated Use {@link File#toURI} and {@link URI#toURL} instead under JDK 1.4.
105.2998 - * ({@link File#toURL} is buggy in JDK 1.3 and the bugs are not fixed in JDK 1.4.)
105.2999 - */
105.3000 - @Deprecated
105.3001 - public static URL toURL(File f) throws MalformedURLException {
105.3002 - if (f == null) {
105.3003 - throw new NullPointerException();
105.3004 - }
105.3005 -
105.3006 - if (!f.isAbsolute()) {
105.3007 - throw new IllegalArgumentException("Relative path: " + f); // NOI18N
105.3008 - }
105.3009 -
105.3010 - URI uri = f.toURI();
105.3011 -
105.3012 - return uri.toURL();
105.3013 - }
105.3014 -
105.3015 - /**
105.3016 - * Convert a <code>file:</code> URL to a matching file.
105.3017 - * <p>You may not use a URL generated from a file on a different
105.3018 - * platform, as file name conventions may make the result meaningless
105.3019 - * or even unparsable.
105.3020 - * @param u a URL with the <code>file</code> protocol
105.3021 - * @return an absolute file it points to, or <code>null</code> if the URL
105.3022 - * does not seem to point to a file at all
105.3023 - * @see #toURL
105.3024 - * @see <a href="http://www.netbeans.org/issues/show_bug.cgi?id=29711">Issue #29711</a>
105.3025 - * @since 3.26
105.3026 - * @deprecated Use {@link URI#URI(String)} and {@link File#File(URI)} instead under JDK 1.4.
105.3027 - * (There was no proper equivalent under JDK 1.3.)
105.3028 - */
105.3029 - @Deprecated
105.3030 - public static File toFile(URL u) {
105.3031 - if (u == null) {
105.3032 - throw new NullPointerException();
105.3033 - }
105.3034 -
105.3035 - try {
105.3036 - URI uri = new URI(u.toExternalForm());
105.3037 -
105.3038 - return new File(uri);
105.3039 - } catch (URISyntaxException use) {
105.3040 - // malformed URL
105.3041 - return null;
105.3042 - } catch (IllegalArgumentException iae) {
105.3043 - // not a file: URL
105.3044 - return null;
105.3045 - }
105.3046 - }
105.3047 -
105.3048 - /** Interfaces for communication between Utilities.translate and regular
105.3049 - * expression impl.
105.3050 - *
105.3051 - * Order of methods is:
105.3052 - * readPair few times
105.3053 - * init once
105.3054 - * convert many times
105.3055 - */
105.3056 - static interface RE {
105.3057 - public void init(String[] original, String[] newversion);
105.3058 -
105.3059 - public String convert(String pattern);
105.3060 -
105.3061 - /** Parses line of text to two parts: the key and the rest
105.3062 - */
105.3063 - public String[] readPair(String line);
105.3064 - }
105.3065 -
105.3066 - /** Exception indicating that a given list could not be partially-ordered.
105.3067 - * @see #partialSort
105.3068 - * @deprecated Used only by the deprecated partialSort
105.3069 - */
105.3070 - @Deprecated
105.3071 - public static class UnorderableException extends RuntimeException {
105.3072 - static final long serialVersionUID = 6749951134051806661L;
105.3073 - private Collection unorderable;
105.3074 - private Map deps;
105.3075 -
105.3076 - /** Create a new unorderable-list exception with no detail message.
105.3077 - * @param unorderable a collection of list elements which could not be ordered
105.3078 - * (because there was some sort of cycle)
105.3079 - * @param deps dependencies associated with the list; a map from list elements
105.3080 - * to sets of list elements which that element must appear after
105.3081 - */
105.3082 - public UnorderableException(Collection unorderable, Map deps) {
105.3083 - super( /* "Cannot be ordered: " + unorderable */
105.3084 - ); // NOI18N
105.3085 - this.unorderable = unorderable;
105.3086 - this.deps = deps;
105.3087 - }
105.3088 -
105.3089 - /** Create a new unorderable-list exception with a specified detail message.
105.3090 - * @param message the detail message
105.3091 - * @param unorderable a collection of list elements which could not be ordered
105.3092 - * (because there was some sort of cycle)
105.3093 - * @param deps dependencies associated with the list; a map from list elements
105.3094 - * to sets of list elements which that element must appear after
105.3095 - */
105.3096 - public UnorderableException(String message, Collection unorderable, Map deps) {
105.3097 - super(message);
105.3098 - this.unorderable = unorderable;
105.3099 - this.deps = deps;
105.3100 - }
105.3101 -
105.3102 - /** Get the unorderable elements.
105.3103 - * @return the elements
105.3104 - * @see Utilities.UnorderableException#Utilities.UnorderableException(Collection,Map)
105.3105 - */
105.3106 - public Collection getUnorderable() {
105.3107 - return unorderable;
105.3108 - }
105.3109 -
105.3110 - /** Get the dependencies.
105.3111 - * @return the dependencies
105.3112 - * @see Utilities.UnorderableException#Utilities.UnorderableException(Collection,Map)
105.3113 - */
105.3114 - public Map getDeps() {
105.3115 - return deps;
105.3116 - }
105.3117 - }
105.3118 -}
106.1 --- a/openide.util/src/org/openide/util/WeakSet.java Wed Jan 27 17:46:23 2010 -0500
106.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
106.3 @@ -1,579 +0,0 @@
106.4 -/*
106.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
106.6 - *
106.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
106.8 - *
106.9 - * The contents of this file are subject to the terms of either the GNU
106.10 - * General Public License Version 2 only ("GPL") or the Common
106.11 - * Development and Distribution License("CDDL") (collectively, the
106.12 - * "License"). You may not use this file except in compliance with the
106.13 - * License. You can obtain a copy of the License at
106.14 - * http://www.netbeans.org/cddl-gplv2.html
106.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
106.16 - * specific language governing permissions and limitations under the
106.17 - * License. When distributing the software, include this License Header
106.18 - * Notice in each file and include the License file at
106.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
106.20 - * particular file as subject to the "Classpath" exception as provided
106.21 - * by Sun in the GPL Version 2 section of the License file that
106.22 - * accompanied this code. If applicable, add the following below the
106.23 - * License Header, with the fields enclosed by brackets [] replaced by
106.24 - * your own identifying information:
106.25 - * "Portions Copyrighted [year] [name of copyright owner]"
106.26 - *
106.27 - * Contributor(s):
106.28 - *
106.29 - * The Original Software is NetBeans. The Initial Developer of the Original
106.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
106.31 - * Microsystems, Inc. All Rights Reserved.
106.32 - *
106.33 - * If you wish your version of this file to be governed by only the CDDL
106.34 - * or only the GPL Version 2, indicate your decision by adding
106.35 - * "[Contributor] elects to include this software in this distribution
106.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
106.37 - * single choice of license, a recipient has the option to distribute
106.38 - * your version of this file under either the CDDL, the GPL Version 2 or
106.39 - * to extend the choice of license to its licensees as provided above.
106.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
106.41 - * Version 2 license, then the option applies only if the new code is
106.42 - * made subject to such option by the copyright holder.
106.43 - */
106.44 -
106.45 -package org.openide.util;
106.46 -
106.47 -import java.io.IOException;
106.48 -import java.io.ObjectInputStream;
106.49 -import java.io.ObjectOutputStream;
106.50 -import java.io.Serializable;
106.51 -import java.lang.ref.ReferenceQueue;
106.52 -import java.lang.ref.WeakReference;
106.53 -import java.util.AbstractSet;
106.54 -import java.util.ArrayList;
106.55 -import java.util.Collection;
106.56 -import java.util.ConcurrentModificationException;
106.57 -import java.util.Iterator;
106.58 -import java.util.logging.Level;
106.59 -import java.util.logging.Logger;
106.60 -
106.61 -/** Set which holds its members by using of WeakReferences.
106.62 -* MT level: unsafe.
106.63 - * <p><strong>Note:</strong> you can instead use
106.64 - * <pre>
106.65 - * Set<T> s = Collections.newSetFromMap(new WeakHashMap<T, Boolean>());
106.66 - * </pre>
106.67 -*
106.68 -* @author Ales Novak
106.69 -*/
106.70 -public class WeakSet<E> extends AbstractSet<E> implements Cloneable, Serializable {
106.71 - static final long serialVersionUID = 3062376055928236721L;
106.72 -
106.73 - /** load factor */
106.74 - private float loadFactor;
106.75 -
106.76 - /** Number of items. */
106.77 - private int size;
106.78 -
106.79 - /** Modification count */
106.80 - private long modcount;
106.81 -
106.82 - /** Reference queue of collected weak refs */
106.83 - private transient ReferenceQueue<E> refq;
106.84 -
106.85 - /** Count of <tt>null</tt> in this set */
106.86 - long nullCount;
106.87 -
106.88 - /** An array of Entries */
106.89 - private transient Entry<E>[] entries;
106.90 - transient Entry<E> iterChain;
106.91 -
106.92 - /** Constructs a new set. */
106.93 - public WeakSet() {
106.94 - this(11, 0.75f);
106.95 - }
106.96 -
106.97 - /** Constructs a new set containing the elements in the specified collection.
106.98 - * @param c a collection to add
106.99 - */
106.100 - public WeakSet(Collection<? extends E> c) {
106.101 - this();
106.102 - addAll(c);
106.103 - }
106.104 -
106.105 - /** Constructs a new, empty set;
106.106 - * @param initialCapacity initial capacity
106.107 - */
106.108 - public WeakSet(int initialCapacity) {
106.109 - this(initialCapacity, 0.75f);
106.110 - }
106.111 -
106.112 - /** Constructs a new, empty set;
106.113 - *
106.114 - * @param initialCapacity initial capacity
106.115 - * @param loadFactor load factor
106.116 - */
106.117 - public WeakSet(int initialCapacity, float loadFactor) {
106.118 - if ((initialCapacity <= 0) || (loadFactor <= 0)) {
106.119 - throw new IllegalArgumentException();
106.120 - }
106.121 -
106.122 - size = 0;
106.123 - modcount = 0;
106.124 - this.loadFactor = loadFactor;
106.125 - nullCount = 0;
106.126 - refq = new ReferenceQueue<E>();
106.127 - entries = Entry.createArray(initialCapacity);
106.128 - iterChain = null;
106.129 - }
106.130 -
106.131 - /**
106.132 - * logs iterator chain (for debugging)
106.133 - * @param msg
106.134 - */
106.135 - void logIterChain(String msg) {
106.136 - Logger log = Logger.getLogger(WeakSet.class.getName());
106.137 - log.log(Level.FINE, msg);
106.138 - if (iterChain == null) {
106.139 - log.log(Level.FINE, "Empty");
106.140 - return;
106.141 - }
106.142 - StringBuilder str = new StringBuilder();
106.143 - Entry<E> it = iterChain;
106.144 - str.append(size + ": ");
106.145 - while (it != null) {
106.146 - str.append(it.get() + "(" + it.hashcode + ")" + "->");
106.147 - it = it.iterChainNext;
106.148 - }
106.149 - log.log(Level.FINE, str.toString());
106.150 - }
106.151 -
106.152 - /** Adds the specified element to this set if it is not already present.
106.153 - *
106.154 - * @param o an Object to add
106.155 - */
106.156 - public boolean add(E o) {
106.157 - if (o == null) {
106.158 - size++;
106.159 - nullCount++;
106.160 - modcount++;
106.161 -
106.162 - return true;
106.163 - }
106.164 -
106.165 - Entry e = object2Entry(o);
106.166 -
106.167 - if (e != null) {
106.168 - return false;
106.169 - }
106.170 -
106.171 - modcount++;
106.172 - size++;
106.173 -
106.174 - int hash = hashIt(o);
106.175 - Entry<E> next = entries[hash];
106.176 - iterChain = entries[hash] = new Entry<E>(this, o, refq, next, iterChain);
106.177 - rehash();
106.178 -
106.179 - return true;
106.180 - }
106.181 -
106.182 - /** Removes all of the elements from this set. */
106.183 - public void clear() {
106.184 - for (int i = 0; i < entries.length; i++) {
106.185 - entries[i] = null;
106.186 - }
106.187 -
106.188 - nullCount = 0;
106.189 - modcount++;
106.190 - size = 0;
106.191 - iterChain = null;
106.192 - }
106.193 -
106.194 - /** Returns a shallow copy of this WeakSet instance: the elements themselves are not cloned. */
106.195 - public Object clone() {
106.196 - WeakSet<E> nws = new WeakSet<E>(1, loadFactor);
106.197 - nws.size = size;
106.198 - nws.nullCount = nullCount;
106.199 -
106.200 - Entry<E>[] cloned = Entry.createArray(entries.length);
106.201 - nws.entries = cloned;
106.202 -
106.203 - for (int i = 0; i < cloned.length; i++) {
106.204 - Object ref;
106.205 -
106.206 - if ((entries[i] == null) || ((ref = entries[i].get()) == null)) {
106.207 - cloned[i] = null;
106.208 - } else {
106.209 - cloned[i] = ((entries[i] == null) ? null : entries[i].clone(nws.refq));
106.210 - ref = null;
106.211 - }
106.212 -
106.213 - // chains into nws iterator chain
106.214 - Entry<E> entry = cloned[i];
106.215 -
106.216 - while (entry != null) {
106.217 - entry.chainIntoIter(nws.iterChain);
106.218 - nws.iterChain = entry;
106.219 - entry = entry.next;
106.220 - }
106.221 - }
106.222 -
106.223 - return nws;
106.224 - }
106.225 -
106.226 - /** Returns true if this set contains the specified element.
106.227 - *
106.228 - * @param o an Object to examine
106.229 - */
106.230 - public boolean contains(Object o) {
106.231 - if (o == null) {
106.232 - return nullCount > 0;
106.233 - }
106.234 -
106.235 - return object2Entry(o) != null;
106.236 - }
106.237 -
106.238 - /** Returns true if this set contains no elements.
106.239 - */
106.240 - public boolean isEmpty() {
106.241 - return ((nullCount == 0) && (size() == 0));
106.242 - }
106.243 -
106.244 - /** Returns an iterator over the elements in this set. */
106.245 - public Iterator<E> iterator() {
106.246 - return new WeakSetIterator();
106.247 - }
106.248 -
106.249 - /** Removes the given element from this set if it is present.
106.250 - *
106.251 - * @param o an Object to remove
106.252 - * @return <tt>true</tt> if and only if the Object was successfuly removed.
106.253 - */
106.254 - public boolean remove(Object o) {
106.255 - if (o == null) {
106.256 - if (nullCount > 0) {
106.257 - nullCount--;
106.258 - modcount++;
106.259 - size--;
106.260 - }
106.261 -
106.262 - return true;
106.263 - }
106.264 -
106.265 - Entry e = object2Entry(o);
106.266 -
106.267 - if (e != null) {
106.268 - modcount++;
106.269 - size--;
106.270 - e.remove();
106.271 - rehash();
106.272 -
106.273 - return true;
106.274 - }
106.275 -
106.276 - return false;
106.277 - }
106.278 -
106.279 - /** @return the number of elements in this set (its cardinality). */
106.280 - public int size() {
106.281 - checkRefQueue();
106.282 -
106.283 - return size;
106.284 - }
106.285 -
106.286 - public <T> T[] toArray(T[] array) {
106.287 - ArrayList<E> list = new ArrayList<E>(array.length);
106.288 - Iterator<E> it = iterator();
106.289 -
106.290 - while (it.hasNext()) {
106.291 - list.add(it.next());
106.292 - }
106.293 -
106.294 - return list.toArray(array);
106.295 - }
106.296 -
106.297 - public Object[] toArray() {
106.298 - ArrayList<E> list = new ArrayList<E>();
106.299 - Iterator<E> it = iterator();
106.300 -
106.301 - while (it.hasNext()) {
106.302 - list.add(it.next());
106.303 - }
106.304 -
106.305 - return list.toArray();
106.306 - }
106.307 -
106.308 - // #14772
106.309 - public String toString() {
106.310 - StringBuffer buf = new StringBuffer();
106.311 - Iterator e = iterator();
106.312 - buf.append("[");
106.313 -
106.314 - while (e.hasNext()) {
106.315 - buf.append(String.valueOf(e.next()));
106.316 -
106.317 - if (e.hasNext()) {
106.318 - buf.append(", ");
106.319 - }
106.320 - }
106.321 -
106.322 - buf.append("]");
106.323 -
106.324 - return buf.toString();
106.325 - }
106.326 -
106.327 - /** Checks if the queue is empty if not pending weak refs are removed. */
106.328 - void checkRefQueue() {
106.329 - for (;;) {
106.330 - Entry entry = Entry.class.cast(refq.poll());
106.331 -
106.332 - if (entry == null) {
106.333 - break;
106.334 - }
106.335 -
106.336 - entry.remove();
106.337 - size--;
106.338 - }
106.339 - }
106.340 -
106.341 - /** @return modcount */
106.342 - long modCount() {
106.343 - return modcount;
106.344 - }
106.345 -
106.346 - /** @return an index to entries array */
106.347 - int hashIt(Object o) {
106.348 - return (o.hashCode() & 0x7fffffff) % entries.length;
106.349 - }
106.350 -
106.351 - /** rehashes this Set */
106.352 - void rehash() {
106.353 - /*
106.354 - float currentLF = ((float) size) / ((float) entries.length);
106.355 - if (currentLF < loadFactor) {
106.356 - return;
106.357 - }
106.358 - */
106.359 - }
106.360 -
106.361 - /** @return an Entry with given object */
106.362 - private Entry object2Entry(Object o) {
106.363 - checkRefQueue(); // clear ref q
106.364 -
106.365 - int hash = hashIt(o);
106.366 - Entry e = entries[hash];
106.367 -
106.368 - if (e == null) {
106.369 - return null;
106.370 - }
106.371 -
106.372 - while ((e != null) && !e.equals(o)) {
106.373 - e = e.next;
106.374 - }
106.375 -
106.376 - return e;
106.377 - }
106.378 -
106.379 - private void writeObject(ObjectOutputStream obtos)
106.380 - throws IOException {
106.381 - obtos.defaultWriteObject();
106.382 - obtos.writeObject(toArray());
106.383 - }
106.384 -
106.385 - @SuppressWarnings("unchecked")
106.386 - private void readObject(ObjectInputStream obtis) throws IOException, ClassNotFoundException {
106.387 - obtis.defaultReadObject();
106.388 -
106.389 - Object[] arr = (Object[]) obtis.readObject();
106.390 - entries = new Entry[(int) (size * 1.5)];
106.391 - refq = new ReferenceQueue<E>();
106.392 -
106.393 - for (int i = 0; i < arr.length; i++) {
106.394 - add((E)arr[i]);
106.395 - }
106.396 - }
106.397 -
106.398 - class WeakSetIterator implements Iterator<E> {
106.399 - Entry<E> current;
106.400 - Entry<E> next;
106.401 - E currentObj;
106.402 - E nextObj;
106.403 - final long myModcount;
106.404 - long myNullCount;
106.405 -
106.406 - WeakSetIterator() {
106.407 - myModcount = modCount();
106.408 - myNullCount = nullCount;
106.409 - current = null;
106.410 - next = null;
106.411 -
106.412 - Entry<E> ee = iterChain;
106.413 -
106.414 - if (ee == null) {
106.415 - return;
106.416 - }
106.417 -
106.418 - E o = ee.get();
106.419 -
106.420 - while (ee.isEnqueued()) {
106.421 - ee = ee.iterChainNext;
106.422 -
106.423 - if (ee == null) {
106.424 - return;
106.425 - }
106.426 -
106.427 - o = ee.get();
106.428 - }
106.429 -
106.430 - nextObj = o;
106.431 - next = ee;
106.432 - }
106.433 -
106.434 - public boolean hasNext() {
106.435 - checkModcount();
106.436 -
106.437 - return ((myNullCount > 0) || (next != null));
106.438 - }
106.439 -
106.440 - public E next() {
106.441 - checkModcount();
106.442 - checkRefQueue();
106.443 -
106.444 - if (myNullCount > 0) {
106.445 - myNullCount--;
106.446 -
106.447 - return null;
106.448 - } else {
106.449 - if (next == null) {
106.450 - throw new java.util.NoSuchElementException();
106.451 - }
106.452 -
106.453 - current = next;
106.454 - currentObj = nextObj;
106.455 -
106.456 - // move to next requested
106.457 - do {
106.458 - next = next.iterChainNext;
106.459 -
106.460 - if (next == null) {
106.461 - break;
106.462 - }
106.463 -
106.464 - nextObj = next.get();
106.465 - } while (next.isEnqueued());
106.466 -
106.467 - return currentObj;
106.468 - }
106.469 - }
106.470 -
106.471 - public void remove() {
106.472 - checkModcount();
106.473 -
106.474 - if (current == null) {
106.475 - throw new IllegalStateException();
106.476 - }
106.477 -
106.478 - current.remove();
106.479 - size--;
106.480 - }
106.481 -
106.482 - void checkModcount() {
106.483 - if (myModcount != modCount()) {
106.484 - throw new ConcurrentModificationException();
106.485 - }
106.486 - }
106.487 - }
106.488 -
106.489 - /** Entries of this set */
106.490 - static class Entry<E> extends WeakReference<E> {
106.491 - /** reference to outer WeakSet */
106.492 - private WeakSet<E> set;
106.493 -
106.494 - // double linked list
106.495 - Entry<E> prev;
106.496 - Entry<E> next;
106.497 - private final int hashcode;
106.498 - Entry<E> iterChainNext;
106.499 - Entry<E> iterChainPrev;
106.500 -
106.501 - Entry(WeakSet<E> set, E referenced, ReferenceQueue<E> q, Entry<E> next, Entry<E> nextInIter) {
106.502 - super(referenced, q);
106.503 - this.set = set;
106.504 -
106.505 - this.next = next;
106.506 - this.prev = null;
106.507 -
106.508 - if (next != null) {
106.509 - next.prev = this;
106.510 - }
106.511 -
106.512 - if (referenced != null) {
106.513 - hashcode = set.hashIt(referenced);
106.514 - } else {
106.515 - hashcode = 0;
106.516 - }
106.517 -
106.518 - chainIntoIter(nextInIter);
106.519 - }
106.520 -
106.521 - @SuppressWarnings("unchecked")
106.522 - static final <E> Entry<E>[] createArray(int size) {
106.523 - return new Entry[size];
106.524 - }
106.525 -
106.526 - void chainIntoIter(Entry<E> nextInIter) {
106.527 - iterChainNext = nextInIter;
106.528 -
106.529 - if (nextInIter != null) {
106.530 - nextInIter.iterChainPrev = this;
106.531 - }
106.532 - }
106.533 -
106.534 - /** deques itself */
106.535 - void remove() {
106.536 - if (prev != null) {
106.537 - prev.next = next;
106.538 - }
106.539 -
106.540 - if (next != null) {
106.541 - next.prev = prev;
106.542 - }
106.543 -
106.544 - if (iterChainNext != null) {
106.545 - iterChainNext.iterChainPrev = iterChainPrev;
106.546 - }
106.547 -
106.548 - if (iterChainPrev != null) {
106.549 - iterChainPrev.iterChainNext = iterChainNext;
106.550 - } else { // root
106.551 - set.iterChain = iterChainNext;
106.552 - }
106.553 -
106.554 - if (set.entries[hashcode] == this) {
106.555 - set.entries[hashcode] = next;
106.556 - }
106.557 -
106.558 - prev = null;
106.559 - next = null;
106.560 - iterChainNext = null;
106.561 - iterChainPrev = null;
106.562 - }
106.563 -
106.564 - public int hashCode() {
106.565 - return hashcode;
106.566 - }
106.567 -
106.568 - public boolean equals(Object o) {
106.569 - Object oo = get();
106.570 -
106.571 - if (oo == null) {
106.572 - return false;
106.573 - } else {
106.574 - return oo.equals(o);
106.575 - }
106.576 - }
106.577 -
106.578 - public Entry<E> clone(ReferenceQueue<E> q) {
106.579 - return new Entry<E>(set, get(), q, next != null ? next.clone(q) : null, null);
106.580 - }
106.581 - }
106.582 -}
107.1 --- a/openide.util/src/org/openide/util/actions/ActionInvoker.java Wed Jan 27 17:46:23 2010 -0500
107.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
107.3 @@ -1,187 +0,0 @@
107.4 -/*
107.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
107.6 - *
107.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
107.8 - *
107.9 - * The contents of this file are subject to the terms of either the GNU
107.10 - * General Public License Version 2 only ("GPL") or the Common
107.11 - * Development and Distribution License("CDDL") (collectively, the
107.12 - * "License"). You may not use this file except in compliance with the
107.13 - * License. You can obtain a copy of the License at
107.14 - * http://www.netbeans.org/cddl-gplv2.html
107.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
107.16 - * specific language governing permissions and limitations under the
107.17 - * License. When distributing the software, include this License Header
107.18 - * Notice in each file and include the License file at
107.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
107.20 - * particular file as subject to the "Classpath" exception as provided
107.21 - * by Sun in the GPL Version 2 section of the License file that
107.22 - * accompanied this code. If applicable, add the following below the
107.23 - * License Header, with the fields enclosed by brackets [] replaced by
107.24 - * your own identifying information:
107.25 - * "Portions Copyrighted [year] [name of copyright owner]"
107.26 - *
107.27 - * Contributor(s):
107.28 - *
107.29 - * The Original Software is NetBeans. The Initial Developer of the Original
107.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
107.31 - * Microsystems, Inc. All Rights Reserved.
107.32 - *
107.33 - * If you wish your version of this file to be governed by only the CDDL
107.34 - * or only the GPL Version 2, indicate your decision by adding
107.35 - * "[Contributor] elects to include this software in this distribution
107.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
107.37 - * single choice of license, a recipient has the option to distribute
107.38 - * your version of this file under either the CDDL, the GPL Version 2 or
107.39 - * to extend the choice of license to its licensees as provided above.
107.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
107.41 - * Version 2 license, then the option applies only if the new code is
107.42 - * made subject to such option by the copyright holder.
107.43 - */
107.44 -
107.45 -package org.openide.util.actions;
107.46 -
107.47 -import java.awt.event.ActionEvent;
107.48 -import java.beans.PropertyChangeListener;
107.49 -import javax.swing.Action;
107.50 -import org.openide.util.Lookup;
107.51 -import org.openide.util.RequestProcessor;
107.52 -import org.openide.util.actions.SystemAction;
107.53 -import org.openide.util.lookup.ServiceProvider;
107.54 -
107.55 -/** A mixture of a utility class allowing to invoke actions and also a
107.56 - * <a href="http://wiki.apidesign.org/wiki/CodeInjection">
107.57 - * code injection mechanism</a> to allow overall system to be aware of invoked
107.58 - * actions.
107.59 - * <p>
107.60 - * Callers shall use the {@link #invokeAction(javax.swing.Action, java.awt.event.ActionEvent, boolean, java.lang.Runnable)}
107.61 - * method.
107.62 - * <p>
107.63 - * Implementors register an implementation of this class via {@link ServiceProvider}
107.64 - * annotation.
107.65 - *
107.66 - * @since 8.1
107.67 - */
107.68 -public abstract class ActionInvoker extends Object {
107.69 - /** thread to run actions in */
107.70 - private static final RequestProcessor RP = new RequestProcessor("Module-Actions", Integer.MAX_VALUE); // NOI18N
107.71 -
107.72 - /** Subclass constructor. */
107.73 - protected ActionInvoker() {}
107.74 -
107.75 - /** An infrastructure method that handles invocation of an an action.
107.76 - * @param action the action to invoke
107.77 - * @param ev the event used during invocation
107.78 - */
107.79 - protected abstract void invokeAction(Action action, ActionEvent ev);
107.80 -
107.81 - /** Invokes the action in the currently registered ActionsBridge.
107.82 - *
107.83 - * @param action the action that is to be invoked
107.84 - * @param ev the event used to invoke the action
107.85 - * @param asynchronous shall the execution be performed in a background thread?
107.86 - * @param invoker the actual code that shall be performed to "run" the action. If null, action.actionPerformed(ev) will be called
107.87 - */
107.88 - public static void invokeAction(Action action, ActionEvent ev, boolean asynchronous, final Runnable invoker) {
107.89 - ActionRunnable r = new ActionRunnable(ev, action, asynchronous) {
107.90 - @Override
107.91 - protected void run() {
107.92 - if (invoker == null) {
107.93 - action.actionPerformed(ev);
107.94 - } else {
107.95 - invoker.run();
107.96 - }
107.97 - }
107.98 - };
107.99 - doPerformAction(action, r);
107.100 - }
107.101 -
107.102 - private static void doPerformAction(Action action, final ActionInvoker.ActionRunnable r) {
107.103 - assert java.awt.EventQueue.isDispatchThread() : "Action " + action.getClass().getName() +
107.104 - " may not be invoked from the thread " + Thread.currentThread().getName() +
107.105 - ", only the event queue: http://www.netbeans.org/download/4_1/javadoc/OpenAPIs/apichanges.html#actions-event-thread";
107.106 -
107.107 - if (r.async && !r.needsToBeSynchronous()) {
107.108 - Runnable r2 = new Runnable() {
107.109 - public void run() {
107.110 - r.doRun();
107.111 - }
107.112 - };
107.113 -
107.114 - RP.post(r2);
107.115 - } else {
107.116 - r.run();
107.117 - }
107.118 - }
107.119 -
107.120 - /** Special class that can be passed to invokeAction and delegates
107.121 - * to correct values
107.122 - */
107.123 - private static abstract class ActionRunnable implements Action {
107.124 - final ActionEvent ev;
107.125 - final Action action;
107.126 - final boolean async;
107.127 -
107.128 - public ActionRunnable(ActionEvent ev, SystemAction action, boolean async) {
107.129 - this(ev, (Action)action, async);
107.130 - }
107.131 - public ActionRunnable(ActionEvent ev, Action action, boolean async) {
107.132 - this.ev = ev;
107.133 - this.action = action;
107.134 - this.async = async;
107.135 - }
107.136 -
107.137 - public static ActionRunnable create(ActionEvent ev, Action a, boolean async) {
107.138 - return new ActionRunnable(ev, a, async) {
107.139 - @Override
107.140 - protected void run() {
107.141 - action.actionPerformed(ev);
107.142 - }
107.143 - };
107.144 - }
107.145 -
107.146 - public final boolean needsToBeSynchronous() {
107.147 - return "waitFinished".equals(ev.getActionCommand()); // NOI18N
107.148 - }
107.149 -
107.150 - public final void doRun() {
107.151 - ActionInvoker bridge = Lookup.getDefault().lookup(ActionInvoker.class);
107.152 - if (bridge != null) {
107.153 - bridge.invokeAction (this, ev);
107.154 - } else {
107.155 - this.actionPerformed(ev);
107.156 - }
107.157 - }
107.158 -
107.159 - protected abstract void run();
107.160 -
107.161 - public final void actionPerformed(ActionEvent e) {
107.162 - run();
107.163 - }
107.164 -
107.165 - public final void addPropertyChangeListener(PropertyChangeListener listener) {
107.166 - throw new UnsupportedOperationException();
107.167 - }
107.168 -
107.169 - public final Object getValue(String key) {
107.170 - return action.getValue(key);
107.171 - }
107.172 -
107.173 - public final boolean isEnabled() {
107.174 - return action.isEnabled();
107.175 - }
107.176 -
107.177 - public final void putValue(String key, Object value) {
107.178 - throw new UnsupportedOperationException();
107.179 - }
107.180 -
107.181 - public final void removePropertyChangeListener(PropertyChangeListener listener) {
107.182 - throw new UnsupportedOperationException();
107.183 - }
107.184 -
107.185 - public final void setEnabled(boolean b) {
107.186 - throw new UnsupportedOperationException();
107.187 - }
107.188 - }
107.189 - // end of ActionRunnable
107.190 -}
108.1 --- a/openide.util/src/org/openide/util/actions/ActionPresenterProvider.java Wed Jan 27 17:46:23 2010 -0500
108.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
108.3 @@ -1,128 +0,0 @@
108.4 -/*
108.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
108.6 - *
108.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
108.8 - *
108.9 - * The contents of this file are subject to the terms of either the GNU
108.10 - * General Public License Version 2 only ("GPL") or the Common
108.11 - * Development and Distribution License("CDDL") (collectively, the
108.12 - * "License"). You may not use this file except in compliance with the
108.13 - * License. You can obtain a copy of the License at
108.14 - * http://www.netbeans.org/cddl-gplv2.html
108.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
108.16 - * specific language governing permissions and limitations under the
108.17 - * License. When distributing the software, include this License Header
108.18 - * Notice in each file and include the License file at
108.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
108.20 - * particular file as subject to the "Classpath" exception as provided
108.21 - * by Sun in the GPL Version 2 section of the License file that
108.22 - * accompanied this code. If applicable, add the following below the
108.23 - * License Header, with the fields enclosed by brackets [] replaced by
108.24 - * your own identifying information:
108.25 - * "Portions Copyrighted [year] [name of copyright owner]"
108.26 - *
108.27 - * Contributor(s):
108.28 - *
108.29 - * The Original Software is NetBeans. The Initial Developer of the Original
108.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
108.31 - * Microsystems, Inc. All Rights Reserved.
108.32 - *
108.33 - * If you wish your version of this file to be governed by only the CDDL
108.34 - * or only the GPL Version 2, indicate your decision by adding
108.35 - * "[Contributor] elects to include this software in this distribution
108.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
108.37 - * single choice of license, a recipient has the option to distribute
108.38 - * your version of this file under either the CDDL, the GPL Version 2 or
108.39 - * to extend the choice of license to its licensees as provided above.
108.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
108.41 - * Version 2 license, then the option applies only if the new code is
108.42 - * made subject to such option by the copyright holder.
108.43 - */
108.44 -
108.45 -package org.openide.util.actions;
108.46 -
108.47 -import java.awt.Component;
108.48 -import javax.swing.Action;
108.49 -import javax.swing.JButton;
108.50 -import javax.swing.JMenuItem;
108.51 -import javax.swing.JPopupMenu;
108.52 -import org.openide.util.Lookup;
108.53 -
108.54 -/** Provider of action presentations. Based on type of the action
108.55 - * should be able to derive its menu, popup menu and toolbar
108.56 - * presenter.
108.57 - * <P>
108.58 - * In order to provide greater flexibility this is made as a pluggable component
108.59 - * to allow other parts of the system to provide more enhanced
108.60 - * visualizations.
108.61 - * @since 8.1
108.62 - */
108.63 -public abstract class ActionPresenterProvider extends Object {
108.64 - /** Gets the default implementation from lookup.
108.65 - * @return the presenter
108.66 - */
108.67 - public static ActionPresenterProvider getDefault () {
108.68 - ActionPresenterProvider ap = Lookup.getDefault().lookup(ActionPresenterProvider.class);
108.69 - return ap == null ? new Default () : ap;
108.70 - }
108.71 -
108.72 - /** Subclass constructor. */
108.73 - protected ActionPresenterProvider() {}
108.74 -
108.75 - /** Creates a default empty implementation of popup menu.
108.76 - * @return popup menu
108.77 - */
108.78 - public abstract JPopupMenu createEmptyPopup();
108.79 -
108.80 - /** Creates a menu item that can present this action in a {@link javax.swing.JMenu}.
108.81 - * @param action the action to represent
108.82 - * @return the representation for this action
108.83 - */
108.84 - public abstract JMenuItem createMenuPresenter (Action action);
108.85 -
108.86 - /** Get a menu item that can present this action in a {@link javax.swing.JPopupMenu}.
108.87 - * @param action the action to represent
108.88 - * @return the representation for this action
108.89 - */
108.90 - public abstract JMenuItem createPopupPresenter (Action action);
108.91 -
108.92 - /** Get a component that can present this action in a {@link javax.swing.JToolBar}.
108.93 - * @param action the action to represent
108.94 - * @return the representation for this action
108.95 - */
108.96 - public abstract Component createToolbarPresenter (Action action);
108.97 -
108.98 - /**
108.99 - * Used for implementation of <a href="@org-openide-awt@/org/openide/awt/DynamicMenuContent.html"><code>DynamicMenuContent</code></a>.
108.100 - * @param comp a component
108.101 - * @return zero or more components to display in its place
108.102 - */
108.103 - public abstract Component[] convertComponents(Component comp);
108.104 -
108.105 - //
108.106 - // Default implementation of the the presenter
108.107 - //
108.108 -
108.109 - private static final class Default extends ActionPresenterProvider {
108.110 -
108.111 - public JMenuItem createMenuPresenter(Action action) {
108.112 - return new JMenuItem(action);
108.113 - }
108.114 -
108.115 - public JMenuItem createPopupPresenter(Action action) {
108.116 - return new JMenuItem(action);
108.117 - }
108.118 -
108.119 - public Component createToolbarPresenter(Action action) {
108.120 - return new JButton(action);
108.121 - }
108.122 -
108.123 - public JPopupMenu createEmptyPopup() {
108.124 - return new JPopupMenu();
108.125 - }
108.126 -
108.127 - public Component[] convertComponents(Component comp) {
108.128 - return new Component[] {comp};
108.129 - }
108.130 - }
108.131 -}
109.1 --- a/openide.util/src/org/openide/util/actions/BooleanStateAction.java Wed Jan 27 17:46:23 2010 -0500
109.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
109.3 @@ -1,120 +0,0 @@
109.4 -/*
109.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
109.6 - *
109.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
109.8 - *
109.9 - * The contents of this file are subject to the terms of either the GNU
109.10 - * General Public License Version 2 only ("GPL") or the Common
109.11 - * Development and Distribution License("CDDL") (collectively, the
109.12 - * "License"). You may not use this file except in compliance with the
109.13 - * License. You can obtain a copy of the License at
109.14 - * http://www.netbeans.org/cddl-gplv2.html
109.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
109.16 - * specific language governing permissions and limitations under the
109.17 - * License. When distributing the software, include this License Header
109.18 - * Notice in each file and include the License file at
109.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
109.20 - * particular file as subject to the "Classpath" exception as provided
109.21 - * by Sun in the GPL Version 2 section of the License file that
109.22 - * accompanied this code. If applicable, add the following below the
109.23 - * License Header, with the fields enclosed by brackets [] replaced by
109.24 - * your own identifying information:
109.25 - * "Portions Copyrighted [year] [name of copyright owner]"
109.26 - *
109.27 - * Contributor(s):
109.28 - *
109.29 - * The Original Software is NetBeans. The Initial Developer of the Original
109.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
109.31 - * Microsystems, Inc. All Rights Reserved.
109.32 - *
109.33 - * If you wish your version of this file to be governed by only the CDDL
109.34 - * or only the GPL Version 2, indicate your decision by adding
109.35 - * "[Contributor] elects to include this software in this distribution
109.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
109.37 - * single choice of license, a recipient has the option to distribute
109.38 - * your version of this file under either the CDDL, the GPL Version 2 or
109.39 - * to extend the choice of license to its licensees as provided above.
109.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
109.41 - * Version 2 license, then the option applies only if the new code is
109.42 - * made subject to such option by the copyright holder.
109.43 - */
109.44 -package org.openide.util.actions;
109.45 -
109.46 -
109.47 -/** An action that can be toggled on or off.
109.48 -* The actual "performing" of the action is the toggle itself, so
109.49 -* this action should be used by listening to the {@link #PROP_BOOLEAN_STATE} property.
109.50 -* <p>The default value of the state is <code>true</code> (on).
109.51 -*
109.52 -*
109.53 -* @author Ian Formanek, Petr Hamernik
109.54 -*/
109.55 -public abstract class BooleanStateAction extends SystemAction implements Presenter.Menu, Presenter.Popup,
109.56 - Presenter.Toolbar {
109.57 - /** serialVersionUID */
109.58 - static final long serialVersionUID = 6394800019181426199L;
109.59 -
109.60 - /** Name of property hold the state of the action. */
109.61 - public static final String PROP_BOOLEAN_STATE = "booleanState"; // NOI18N
109.62 -
109.63 - /* Returns a JMenuItem that presents the Action, that implements this
109.64 - * interface, in a MenuBar.
109.65 - * @return the JMenuItem representation for the Action
109.66 - */
109.67 - public javax.swing.JMenuItem getMenuPresenter() {
109.68 - return org.openide.util.actions.ActionPresenterProvider.getDefault().createMenuPresenter(this);
109.69 - }
109.70 -
109.71 - /* Returns a JMenuItem that presents the Action, that implements this
109.72 - * interface, in a Popup Menu.
109.73 - * The default implmentation returns the same JMenuItem as the getMenuPresenter.
109.74 - * @return the JMenuItem representation for the Action
109.75 - */
109.76 - public javax.swing.JMenuItem getPopupPresenter() {
109.77 - return org.openide.util.actions.ActionPresenterProvider.getDefault().createPopupPresenter(this);
109.78 - }
109.79 -
109.80 - /* Returns a Component that presents the Action, that implements this
109.81 - * interface, in a ToolBar.
109.82 - * @return the Component representation for the Action
109.83 - */
109.84 - public java.awt.Component getToolbarPresenter() {
109.85 - return org.openide.util.actions.ActionPresenterProvider.getDefault().createToolbarPresenter(this);
109.86 - }
109.87 -
109.88 - /** Get the current state.
109.89 - * @return <code>true</code> if on
109.90 - */
109.91 - public boolean getBooleanState() {
109.92 - return getProperty(PROP_BOOLEAN_STATE).equals(Boolean.TRUE);
109.93 - }
109.94 -
109.95 - /** Set the current state.
109.96 - * Fires a change event, which should be used to affect other components when
109.97 - * its state is toggled.
109.98 - * @param value <code>true</code> to turn on, <code>false</code> to turn off
109.99 - */
109.100 - public void setBooleanState(boolean value) {
109.101 - Boolean newValue = value ? Boolean.TRUE : Boolean.FALSE;
109.102 - Boolean oldValue = (Boolean) putProperty(PROP_BOOLEAN_STATE, newValue);
109.103 -
109.104 - firePropertyChange(PROP_BOOLEAN_STATE, oldValue, newValue);
109.105 - }
109.106 -
109.107 - /* Initializes its own properties (and let superclass initialize
109.108 - * too).
109.109 - */
109.110 - protected void initialize() {
109.111 - putProperty(PROP_BOOLEAN_STATE, Boolean.TRUE);
109.112 - super.initialize();
109.113 - }
109.114 -
109.115 - /* Implementation of method of javax.swing.Action interface.
109.116 - * Changes the boolean state.
109.117 - *
109.118 - * @param ev ignored
109.119 - */
109.120 - public void actionPerformed(java.awt.event.ActionEvent ev) {
109.121 - setBooleanState(!getBooleanState());
109.122 - }
109.123 -}
110.1 --- a/openide.util/src/org/openide/util/actions/CallableSystemAction.java Wed Jan 27 17:46:23 2010 -0500
110.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
110.3 @@ -1,164 +0,0 @@
110.4 -/*
110.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
110.6 - *
110.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
110.8 - *
110.9 - * The contents of this file are subject to the terms of either the GNU
110.10 - * General Public License Version 2 only ("GPL") or the Common
110.11 - * Development and Distribution License("CDDL") (collectively, the
110.12 - * "License"). You may not use this file except in compliance with the
110.13 - * License. You can obtain a copy of the License at
110.14 - * http://www.netbeans.org/cddl-gplv2.html
110.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
110.16 - * specific language governing permissions and limitations under the
110.17 - * License. When distributing the software, include this License Header
110.18 - * Notice in each file and include the License file at
110.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
110.20 - * particular file as subject to the "Classpath" exception as provided
110.21 - * by Sun in the GPL Version 2 section of the License file that
110.22 - * accompanied this code. If applicable, add the following below the
110.23 - * License Header, with the fields enclosed by brackets [] replaced by
110.24 - * your own identifying information:
110.25 - * "Portions Copyrighted [year] [name of copyright owner]"
110.26 - *
110.27 - * Contributor(s):
110.28 - *
110.29 - * The Original Software is NetBeans. The Initial Developer of the Original
110.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
110.31 - * Microsystems, Inc. All Rights Reserved.
110.32 - *
110.33 - * If you wish your version of this file to be governed by only the CDDL
110.34 - * or only the GPL Version 2, indicate your decision by adding
110.35 - * "[Contributor] elects to include this software in this distribution
110.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
110.37 - * single choice of license, a recipient has the option to distribute
110.38 - * your version of this file under either the CDDL, the GPL Version 2 or
110.39 - * to extend the choice of license to its licensees as provided above.
110.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
110.41 - * Version 2 license, then the option applies only if the new code is
110.42 - * made subject to such option by the copyright holder.
110.43 - */
110.44 -
110.45 -package org.openide.util.actions;
110.46 -
110.47 -import java.awt.Toolkit;
110.48 -import java.awt.event.ActionEvent;
110.49 -import java.util.Set;
110.50 -import java.util.logging.Logger;
110.51 -import org.openide.util.WeakSet;
110.52 -
110.53 -/** Not preferred anymore, use <a href="@org-openide-awt@/org/openide/awt/Actions.html#alwaysEnabled(java.awt.event.ActionListener,%20java.lang.String,%20java.lang.String,%20boolean)">Actions.alwaysEnabled</a>
110.54 -* instead. To migrate your
110.55 -* <a href="@org-openide-modules@/org/openide/modules/doc-files/api.html#how-layer">
110.56 -* layer definition</a> use:
110.57 -* <pre>
110.58 -* <file name="your-pkg-action-id.instance">
110.59 -* <attr name="instanceCreate" methodvalue="org.openide.awt.Actions.alwaysEnabled"/>
110.60 -* <attr name="delegate" methodvalue="your.pkg.YourAction.factoryMethod"/>
110.61 -* <attr name="displayName" bundlevalue="your.pkg.Bundle#key"/>
110.62 -* <attr name="iconBase" stringvalue="your/pkg/YourImage.png"/>
110.63 -* <!-- if desired: <attr name="noIconInMenu" boolvalue="false"/> -->
110.64 -* </file>
110.65 -* </pre>
110.66 -*
110.67 -* @author Ian Formanek, Jaroslav Tulach, Jan Jancura, Petr Hamernik
110.68 -*/
110.69 -public abstract class CallableSystemAction extends SystemAction implements Presenter.Menu, Presenter.Popup,
110.70 - Presenter.Toolbar {
110.71 - /** serialVersionUID */
110.72 - static final long serialVersionUID = 2339794599168944156L;
110.73 -
110.74 - // ASYNCHRONICITY
110.75 - // Adapted from org.netbeans.core.ModuleActions by jglick
110.76 -
110.77 - /**
110.78 - * Set of action classes for which we have already issued a warning that
110.79 - * {@link #asynchronous} was not overridden to return false.
110.80 - */
110.81 - private static final Set<Class> warnedAsynchronousActions = new WeakSet<Class>();
110.82 - private static final boolean DEFAULT_ASYNCH = !Boolean.getBoolean(
110.83 - "org.openide.util.actions.CallableSystemAction.synchronousByDefault"
110.84 - );
110.85 -
110.86 - /* Returns a JMenuItem that presents the Action, that implements this
110.87 - * interface, in a MenuBar.
110.88 - * @return the JMenuItem representation for the Action
110.89 - */
110.90 - public javax.swing.JMenuItem getMenuPresenter() {
110.91 - return org.openide.util.actions.ActionPresenterProvider.getDefault().createMenuPresenter(this);
110.92 - }
110.93 -
110.94 - /* Returns a JMenuItem that presents the Action, that implements this
110.95 - * interface, in a Popup Menu.
110.96 - * @return the JMenuItem representation for the Action
110.97 - */
110.98 - public javax.swing.JMenuItem getPopupPresenter() {
110.99 - return org.openide.util.actions.ActionPresenterProvider.getDefault().createPopupPresenter(this);
110.100 - }
110.101 -
110.102 - /* Returns a Component that presents the Action, that implements this
110.103 - * interface, in a ToolBar.
110.104 - * @return the Component representation for the Action
110.105 - */
110.106 - public java.awt.Component getToolbarPresenter() {
110.107 - return org.openide.util.actions.ActionPresenterProvider.getDefault().createToolbarPresenter(this);
110.108 - }
110.109 -
110.110 - /** Actually perform the action.
110.111 - * This is the method which should be called programmatically.
110.112 - * Presenters in <a href="@org-openide-awt@/org/openide/awt/Actions.html">Actions</a> use this.
110.113 - * <p>See {@link SystemAction#actionPerformed} for a note on
110.114 - * threading usage: in particular, do not access GUI components
110.115 - * without explicitly asking for the AWT event thread!
110.116 - */
110.117 - public abstract void performAction();
110.118 -
110.119 - /* Implementation of method of javax.swing.Action interface.
110.120 - * Delegates the execution to performAction method.
110.121 - *
110.122 - * @param ev the action event
110.123 - */
110.124 - public void actionPerformed(ActionEvent ev) {
110.125 - if (isEnabled()) {
110.126 - org.openide.util.actions.ActionInvoker.invokeAction(
110.127 - this, ev, asynchronous(), new Runnable() {
110.128 - public void run() {
110.129 - performAction();
110.130 - }
110.131 - }
110.132 - );
110.133 - } else {
110.134 - // Should not normally happen.
110.135 - Toolkit.getDefaultToolkit().beep();
110.136 - }
110.137 - }
110.138 -
110.139 - /**
110.140 - * If true, this action should be performed asynchronously in a private thread.
110.141 - * If false, it will be performed synchronously as called in the event thread.
110.142 - * <p>The default value is true for compatibility reasons; subclasses are strongly
110.143 - * encouraged to override it to be false, and to either do their work promptly
110.144 - * in the event thread and return, or to somehow do work asynchronously (for example
110.145 - * using {@link org.openide.util.RequestProcessor#getDefault}).
110.146 - * <p class="nonnormative">You may currently set the global default to false
110.147 - * by setting the system property
110.148 - * <code>org.openide.util.actions.CallableSystemAction.synchronousByDefault</code>
110.149 - * to <code>true</code>.</p>
110.150 - * <p class="nonnormative">When true, the current implementation also provides for a wait cursor during
110.151 - * the execution of the action. Subclasses which override to return false should
110.152 - * consider directly providing a wait or busy cursor if the nature of the action
110.153 - * merits it.</p>
110.154 - * @return true if this action should automatically be performed asynchronously
110.155 - * @since 4.11
110.156 - */
110.157 - protected boolean asynchronous() {
110.158 - if (warnedAsynchronousActions.add(getClass())) {
110.159 - Logger.getLogger(CallableSystemAction.class.getName()).warning(
110.160 - "Warning - " + getClass().getName() +
110.161 - " should override CallableSystemAction.asynchronous() to return false"
110.162 - );
110.163 - }
110.164 -
110.165 - return DEFAULT_ASYNCH;
110.166 - }
110.167 -}
111.1 --- a/openide.util/src/org/openide/util/actions/CallbackSystemAction.java Wed Jan 27 17:46:23 2010 -0500
111.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
111.3 @@ -1,749 +0,0 @@
111.4 -/*
111.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
111.6 - *
111.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
111.8 - *
111.9 - * The contents of this file are subject to the terms of either the GNU
111.10 - * General Public License Version 2 only ("GPL") or the Common
111.11 - * Development and Distribution License("CDDL") (collectively, the
111.12 - * "License"). You may not use this file except in compliance with the
111.13 - * License. You can obtain a copy of the License at
111.14 - * http://www.netbeans.org/cddl-gplv2.html
111.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
111.16 - * specific language governing permissions and limitations under the
111.17 - * License. When distributing the software, include this License Header
111.18 - * Notice in each file and include the License file at
111.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
111.20 - * particular file as subject to the "Classpath" exception as provided
111.21 - * by Sun in the GPL Version 2 section of the License file that
111.22 - * accompanied this code. If applicable, add the following below the
111.23 - * License Header, with the fields enclosed by brackets [] replaced by
111.24 - * your own identifying information:
111.25 - * "Portions Copyrighted [year] [name of copyright owner]"
111.26 - *
111.27 - * Contributor(s):
111.28 - *
111.29 - * The Original Software is NetBeans. The Initial Developer of the Original
111.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2008 Sun
111.31 - * Microsystems, Inc. All Rights Reserved.
111.32 - *
111.33 - * If you wish your version of this file to be governed by only the CDDL
111.34 - * or only the GPL Version 2, indicate your decision by adding
111.35 - * "[Contributor] elects to include this software in this distribution
111.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
111.37 - * single choice of license, a recipient has the option to distribute
111.38 - * your version of this file under either the CDDL, the GPL Version 2 or
111.39 - * to extend the choice of license to its licensees as provided above.
111.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
111.41 - * Version 2 license, then the option applies only if the new code is
111.42 - * made subject to such option by the copyright holder.
111.43 - */
111.44 -
111.45 -package org.openide.util.actions;
111.46 -
111.47 -import java.awt.Component;
111.48 -import java.awt.Toolkit;
111.49 -import java.awt.event.ActionEvent;
111.50 -import java.beans.PropertyChangeEvent;
111.51 -import java.beans.PropertyChangeListener;
111.52 -import java.beans.PropertyChangeSupport;
111.53 -import java.lang.ref.Reference;
111.54 -import java.lang.ref.WeakReference;
111.55 -import java.util.ArrayList;
111.56 -import java.util.Collection;
111.57 -import java.util.Collections;
111.58 -import java.util.Iterator;
111.59 -import java.util.List;
111.60 -import java.util.logging.Level;
111.61 -import java.util.logging.Logger;
111.62 -import javax.swing.Action;
111.63 -import javax.swing.ActionMap;
111.64 -import org.openide.util.ContextAwareAction;
111.65 -import org.openide.util.Lookup;
111.66 -import org.openide.util.LookupListener;
111.67 -import org.openide.util.Mutex;
111.68 -import org.openide.util.Utilities;
111.69 -import org.openide.util.WeakListeners;
111.70 -import org.openide.util.WeakSet;
111.71 -
111.72 -/** Not preferred anymore, the replacement is
111.73 -* <a href="@org-openide-awt@/org/openide/awt/Actions.html#callback(java.lang.String,%20javax.swing.Action,%20boolean,%20java.lang.String,%20java.lang.String,%20boolean)">Actions.callback</a> factory method.
111.74 -* To migrate to the new API just remove the definition of your action in
111.75 -* <a href="@org-openide-modules@/org/openide/modules/doc-files/api.html#how-layer">
111.76 -* layer file</a> and replace it with:
111.77 -* <pre>
111.78 -* <file name="action-pkg-ClassName.instance">
111.79 -* <attr name="instanceCreate" methodvalue="org.openide.awt.Actions.callback"/>
111.80 -* <attr name="key" stringvalue="KeyInActionMap"/>
111.81 -* <attr name="surviveFocusChange" boolvalue="false"/> <!-- defaults to false -->
111.82 -* <attr name="fallback" newvalue="action.pkg.DefaultAction"/> <!-- may be missing -->
111.83 -* <attr name="displayName" bundlevalue="your.pkg.Bundle#key"/>
111.84 -* <attr name="iconBase" stringvalue="your/pkg/YourImage.png"/>
111.85 -* <!-- if desired: <attr name="noIconInMenu" boolvalue="false"/> -->
111.86 -* </file>
111.87 -* </pre>
111.88 -*
111.89 -*
111.90 -* @author Ian Formanek, Jaroslav Tulach, Petr Hamernik
111.91 -*/
111.92 -public abstract class CallbackSystemAction extends CallableSystemAction implements ContextAwareAction {
111.93 - /** action performer */
111.94 - private static final String PROP_ACTION_PERFORMER = "actionPerformer"; // NOI18N
111.95 -
111.96 - /** a list of all actions that has survive focus change set to false */
111.97 - private static final WeakSet<Class<? extends CallbackSystemAction>> notSurviving = new WeakSet<Class<? extends CallbackSystemAction>>(37);
111.98 -
111.99 - /** a list of actions surviving focus change */
111.100 - private static final WeakSet<Class<? extends CallbackSystemAction>> surviving = new WeakSet<Class<? extends CallbackSystemAction>>(37);
111.101 -
111.102 - /** key to access listener */
111.103 - private static final Object LISTENER = new Object();
111.104 - static final long serialVersionUID = -6305817805474624653L;
111.105 -
111.106 - /** logging */
111.107 - private static final Logger err = Logger.getLogger(
111.108 - "org.openide.util.actions.CallbackSystemAction"
111.109 - ); // NOI18N
111.110 -
111.111 - /** Initialize the action to have no performer.
111.112 - */
111.113 - protected void initialize() {
111.114 - super.initialize();
111.115 - updateEnabled();
111.116 - setSurviveFocusChange(false);
111.117 - }
111.118 -
111.119 - /** Get the current action performer.
111.120 - * @return the current action performer, or <code>null</code> if there is currently no performer
111.121 - * @deprecated use TopComponent.getActionMap() as described in the javadoc
111.122 - */
111.123 - @Deprecated
111.124 - public ActionPerformer getActionPerformer() {
111.125 - return (ActionPerformer) getProperty(PROP_ACTION_PERFORMER);
111.126 - }
111.127 -
111.128 - /** Set the action performer.
111.129 - * The specified value can be <code>null</code>, which means that the action will have no performer
111.130 - * and is disabled. ({@link #isEnabled} will return <code>false</code> regardless its previous state.)
111.131 - * <P>
111.132 - * This method is <em>too dynamic</em> it depends on the actuall order of callers and
111.133 - * is for example very fragile with respect to focus switching and correct delivering of
111.134 - * focus change events. That is why an alternative based on
111.135 - * <a href="http://openide.netbeans.org/proposals/actions/design.html#callback">ActionMap proposal</a>
111.136 - * has been developed.
111.137 - * <P>
111.138 - * So if you are providing a <a href="@org-openide-windows@/org/openide/windows/TopComponent.html">TopComponent</a>
111.139 - * and want to provide
111.140 - * your own handling of <a href="@org-openide-actions@/org/openide/actions/CopyAction.html">CopyAction</a> use following code:
111.141 - * <PRE>
111.142 - * TopComponent tc = ...;
111.143 - * javax.swing.Action yourCopyAction = ...; // the action to invoke instead of Copy
111.144 - *
111.145 - * CopyAction globalCopyAction = SystemAction.get (CopyAction.class);
111.146 - * Object key = globalCopyAction.getActionMapKey(); // key is a special value defined by all CallbackSystemActions
111.147 - *
111.148 - * // and finally:
111.149 - * tc.getActionMap ().put (key, yourCopyAction);
111.150 - * </PRE>
111.151 - * This code registers <code>yourCopyAction</code> with <code>tc</code>
111.152 - * top component, so whenever a <code>globalCopyAction</code> is invoked,
111.153 - * your action is being delegated to.
111.154 - *
111.155 - * @param performer the new action performer or <code>null</code> to disable
111.156 - *
111.157 - * @deprecated use TopComponent.getActionMap() as described in the javadoc
111.158 - */
111.159 - @Deprecated
111.160 - public void setActionPerformer(ActionPerformer performer) {
111.161 - putProperty(PROP_ACTION_PERFORMER, performer);
111.162 - updateEnabled();
111.163 - }
111.164 -
111.165 - /** Updates the enabled state by checking performer and ActionMap
111.166 - */
111.167 - private void updateEnabled() {
111.168 - Action action = GlobalManager.getDefault().findGlobalAction(
111.169 - getActionMapKey(), getSurviveFocusChange()
111.170 - );
111.171 -
111.172 - if (action != null) {
111.173 - setEnabled(action.isEnabled());
111.174 -
111.175 - synchronized (LISTENER) {
111.176 - ActionDelegateListener l = (ActionDelegateListener) getProperty(LISTENER);
111.177 -
111.178 - if ((l == null) || (l.get() != this)) {
111.179 - l = new ActionDelegateListener(this, action);
111.180 - putProperty(LISTENER, l);
111.181 - } else {
111.182 - l.attach(action);
111.183 - }
111.184 - }
111.185 - } else {
111.186 - if (getActionPerformer() != null) {
111.187 - // we have performer
111.188 - setEnabled(true);
111.189 - } else {
111.190 - setEnabled(false);
111.191 - }
111.192 -
111.193 - clearListener();
111.194 - }
111.195 - }
111.196 -
111.197 - /** Clears the listener.
111.198 - */
111.199 - private void clearListener() {
111.200 - synchronized (LISTENER) {
111.201 - // remove listener on any action
111.202 - ActionDelegateListener l = (ActionDelegateListener) getProperty(LISTENER);
111.203 -
111.204 - if (l != null) {
111.205 - l.clear();
111.206 - putProperty(LISTENER, null);
111.207 - }
111.208 - }
111.209 - }
111.210 -
111.211 - /** Perform the action. Tries the performer and then scans the ActionMap
111.212 - * of selected topcomponent.
111.213 - */
111.214 - public void actionPerformed(final ActionEvent ev) {
111.215 - // First try global context action.
111.216 - final Action action = GlobalManager.getDefault().findGlobalAction(getActionMapKey(), getSurviveFocusChange());
111.217 -
111.218 - if (action != null) {
111.219 - if (action.isEnabled()) {
111.220 - action.actionPerformed(ev);
111.221 - } else {
111.222 - Toolkit.getDefaultToolkit().beep();
111.223 - }
111.224 -
111.225 - return;
111.226 - }
111.227 -
111.228 - final Object ap = getActionPerformer();
111.229 -
111.230 - if (ap != null) {
111.231 - org.openide.util.actions.ActionInvoker.invokeAction(
111.232 - this, ev, asynchronous(), new Runnable() {
111.233 - public void run() {
111.234 - if (ap == getActionPerformer()) {
111.235 - getActionPerformer().performAction(CallbackSystemAction.this);
111.236 - }
111.237 - }
111.238 - }
111.239 - );
111.240 -
111.241 - return;
111.242 - }
111.243 -
111.244 - Toolkit.getDefaultToolkit().beep();
111.245 - }
111.246 -
111.247 - /** Perform the action.
111.248 - * This default implementation calls the assigned action performer if it
111.249 - * exists, otherwise does nothing.
111.250 - * @deprecated This only uses {@link ActionPerformer}. Use {@link #actionPerformed} instead.
111.251 - */
111.252 - @Deprecated
111.253 - public void performAction() {
111.254 - ActionPerformer ap = getActionPerformer();
111.255 -
111.256 - if (ap != null) {
111.257 - ap.performAction(this);
111.258 - }
111.259 - }
111.260 -
111.261 - /** Getter for action map key, which is used to find action from provided
111.262 - * context (i.e. <code>ActionMap</code> provided by the context),
111.263 - * which acts as a callback.
111.264 - * Override this method in subclasses to provide 'nice' key.
111.265 - * @return key which is used to find the action which performs callback,
111.266 - * default returned key is a class name.
111.267 - * @since 3.29 */
111.268 - public Object getActionMapKey() {
111.269 - return getClass().getName();
111.270 - }
111.271 -
111.272 - /** Test whether the action will survive a change in focus.
111.273 - * By default, it will not.
111.274 - * @return <code>true</code> if the enabled state of the action survives focus changes
111.275 - */
111.276 - public boolean getSurviveFocusChange() {
111.277 - getProperty(null); // force initialization
111.278 -
111.279 - return !notSurviving.contains(getClass());
111.280 - }
111.281 -
111.282 - /** Implements <code>ContextAwareAction</code> interface method. */
111.283 - public Action createContextAwareInstance(Lookup actionContext) {
111.284 - return new DelegateAction(this, actionContext);
111.285 - }
111.286 -
111.287 - /** Set whether the action will survive a change in focus.
111.288 - * If <code>false</code>, then the action will be automatically
111.289 - * disabled (using {@link #setActionPerformer}) when the window
111.290 - * focus changes.
111.291 - *
111.292 - * @param b <code>true</code> to survive focus changes, <code>false</code> to be sensitive to them
111.293 - */
111.294 - public void setSurviveFocusChange(boolean b) {
111.295 - synchronized (notSurviving) {
111.296 - if (b) {
111.297 - notSurviving.remove(getClass());
111.298 - surviving.add(getClass());
111.299 - } else {
111.300 - notSurviving.add(getClass());
111.301 - surviving.remove(getClass());
111.302 - }
111.303 - }
111.304 - }
111.305 -
111.306 - /** Array of actions from a set of classes.
111.307 - */
111.308 - private static List<CallbackSystemAction> toInstances(java.util.Set<Class<? extends CallbackSystemAction>> s) {
111.309 - List<CallbackSystemAction> actions;
111.310 -
111.311 - synchronized (notSurviving) {
111.312 - actions = new ArrayList<CallbackSystemAction>(s.size());
111.313 -
111.314 - for (Class<? extends CallbackSystemAction> c : s) {
111.315 -
111.316 - CallbackSystemAction a = SystemAction.findObject(c, false);
111.317 -
111.318 - if (a != null) {
111.319 - actions.add(a);
111.320 - }
111.321 - }
111.322 - }
111.323 -
111.324 - return actions;
111.325 - }
111.326 -
111.327 - /** Clears all action performers for those that has setSurviveFocusChange
111.328 - * on true.
111.329 - */
111.330 - private static void clearActionPerformers() {
111.331 - List<CallbackSystemAction> actions = toInstances(notSurviving);
111.332 -
111.333 - // clear the performers out of any loop
111.334 - for (CallbackSystemAction a : actions) {
111.335 - a.setActionPerformer(null);
111.336 - }
111.337 -
111.338 - actions = toInstances(surviving);
111.339 -
111.340 - // clear the performers out of any loop
111.341 - for (CallbackSystemAction a : actions) {
111.342 -
111.343 - if (err.isLoggable(Level.FINE)) {
111.344 - err.fine("updateEnabled: " + a); // NOI18N
111.345 - }
111.346 -
111.347 - a.updateEnabled();
111.348 - }
111.349 - }
111.350 -
111.351 - /** Listener on a global context.
111.352 - */
111.353 - private static final class GlobalManager implements LookupListener {
111.354 - private static GlobalManager instance;
111.355 - private Lookup.Result<ActionMap> result;
111.356 - private List<Reference<ActionMap>> actionMaps = new ArrayList<Reference<ActionMap>>(2);
111.357 - private final ActionMap survive = new ActionMap();
111.358 -
111.359 - private GlobalManager() {
111.360 - result = Utilities.actionsGlobalContext().lookup(new Lookup.Template<ActionMap>(ActionMap.class));
111.361 - result.addLookupListener(this);
111.362 - resultChanged(null);
111.363 - }
111.364 -
111.365 - public synchronized static GlobalManager getDefault() {
111.366 - if (instance != null) {
111.367 - return instance;
111.368 - }
111.369 -
111.370 - instance = new GlobalManager();
111.371 -
111.372 - return instance;
111.373 - }
111.374 -
111.375 - public Action findGlobalAction(Object key, boolean surviveFocusChange) {
111.376 - // search action in all action maps from global context
111.377 - Action a = null;
111.378 - for (Reference<ActionMap> ref : actionMaps) {
111.379 - ActionMap am = ref.get();
111.380 - a = am == null ? null : am.get(key);
111.381 - if (a != null) {
111.382 - break;
111.383 - }
111.384 - }
111.385 -
111.386 - if (surviveFocusChange) {
111.387 - if (a == null) {
111.388 - a = survive.get(key);
111.389 -
111.390 - if (a != null) {
111.391 - a = ((WeakAction) a).getDelegate();
111.392 - }
111.393 -
111.394 - if (err.isLoggable(Level.FINE)) {
111.395 - err.fine("No action for key: " + key + " using delegate: " + a); // NOI18N
111.396 - }
111.397 - } else {
111.398 - if (err.isLoggable(Level.FINE)) {
111.399 - err.fine("New action for key: " + key + " put: " + a);
111.400 - }
111.401 -
111.402 - survive.put(key, new WeakAction(a));
111.403 - }
111.404 - }
111.405 -
111.406 - if (err.isLoggable(Level.FINE)) {
111.407 - err.fine("Action for key: " + key + " is: " + a); // NOI18N
111.408 - }
111.409 -
111.410 - return a;
111.411 - }
111.412 -
111.413 - /** Change all that do not survive ActionMap change */
111.414 - public void resultChanged(org.openide.util.LookupEvent ev) {
111.415 - Collection<? extends ActionMap> ams = result.allInstances();
111.416 -
111.417 - if (err.isLoggable(Level.FINE)) {
111.418 - err.fine("changed maps : " + ams); // NOI18N
111.419 - err.fine("previous maps: " + actionMaps); // NOI18N
111.420 - }
111.421 -
111.422 - // do nothing if maps are actually the same
111.423 - if (ams.size() == actionMaps.size()) {
111.424 - boolean theSame = true;
111.425 - int i = 0;
111.426 - for (Iterator<? extends ActionMap> newMaps = ams.iterator(); newMaps.hasNext(); i++) {
111.427 - ActionMap oldMap = actionMaps.get(i).get();
111.428 - if (oldMap == null || oldMap != newMaps.next()) {
111.429 - theSame = false;
111.430 - break;
111.431 - }
111.432 - }
111.433 - if (theSame) {
111.434 - return;
111.435 - }
111.436 - }
111.437 -
111.438 - // update actionMaps
111.439 - List<Reference<ActionMap>> tempActionMaps = new ArrayList<Reference<ActionMap>>(2);
111.440 - for (ActionMap actionMap : ams) {
111.441 - tempActionMaps.add(new WeakReference<ActionMap>(actionMap));
111.442 - }
111.443 - actionMaps = tempActionMaps;
111.444 -
111.445 - if (err.isLoggable(Level.FINE)) {
111.446 - err.fine("clearActionPerformers"); // NOI18N
111.447 - }
111.448 -
111.449 - Mutex.EVENT.readAccess(new Runnable() {
111.450 - public void run() {
111.451 - clearActionPerformers();
111.452 - }
111.453 - });
111.454 - }
111.455 - }
111.456 - // end of LookupListener
111.457 -
111.458 - /** An action that holds a weak reference to other action.
111.459 - */
111.460 - private static final class WeakAction extends WeakReference<Action> implements Action {
111.461 - public WeakAction(Action delegate) {
111.462 - super(delegate);
111.463 - }
111.464 -
111.465 - public Action getDelegate() {
111.466 - return get();
111.467 - }
111.468 -
111.469 - public Object getValue(String key) {
111.470 - throw new UnsupportedOperationException();
111.471 - }
111.472 -
111.473 - public void putValue(String key, Object value) {
111.474 - throw new UnsupportedOperationException();
111.475 - }
111.476 -
111.477 - public void actionPerformed(ActionEvent e) {
111.478 - throw new UnsupportedOperationException();
111.479 - }
111.480 -
111.481 - public void removePropertyChangeListener(PropertyChangeListener listener) {
111.482 - throw new UnsupportedOperationException();
111.483 - }
111.484 -
111.485 - public void addPropertyChangeListener(PropertyChangeListener listener) {
111.486 - throw new UnsupportedOperationException();
111.487 - }
111.488 -
111.489 - public void setEnabled(boolean b) {
111.490 - throw new UnsupportedOperationException();
111.491 - }
111.492 -
111.493 - public boolean isEnabled() {
111.494 - throw new UnsupportedOperationException();
111.495 - }
111.496 - }
111.497 -
111.498 - /** A class that listens on changes in enabled state of an action
111.499 - * and updates the state of the action according to it.
111.500 - */
111.501 - private static final class ActionDelegateListener extends WeakReference<CallbackSystemAction> implements PropertyChangeListener {
111.502 - private Reference<Action> delegate;
111.503 -
111.504 - public ActionDelegateListener(CallbackSystemAction c, Action delegate) {
111.505 - super(c);
111.506 - this.delegate = new WeakReference<Action>(delegate);
111.507 - delegate.addPropertyChangeListener(this);
111.508 - }
111.509 -
111.510 - public void clear() {
111.511 - Action a;
111.512 -
111.513 - Reference<Action> d = delegate;
111.514 - a = d == null ? null : d.get();
111.515 -
111.516 - if (a == null) {
111.517 - return;
111.518 - }
111.519 -
111.520 - delegate = null;
111.521 -
111.522 - a.removePropertyChangeListener(this);
111.523 - }
111.524 -
111.525 - public void attach(Action action) {
111.526 - Reference<Action> d = delegate;
111.527 -
111.528 - if ((d != null) && (d.get() == action)) {
111.529 - return;
111.530 - }
111.531 -
111.532 - Action prev = d.get();
111.533 -
111.534 - // reattaches to different action
111.535 - if (prev != null) {
111.536 - prev.removePropertyChangeListener(this);
111.537 - }
111.538 -
111.539 - this.delegate = new WeakReference<Action>(action);
111.540 - action.addPropertyChangeListener(this);
111.541 - }
111.542 -
111.543 - public void propertyChange(java.beans.PropertyChangeEvent evt) {
111.544 - synchronized (LISTENER) {
111.545 - Reference<Action> d = delegate;
111.546 -
111.547 - if ((d == null) || (d.get() == null)) {
111.548 - return;
111.549 - }
111.550 - }
111.551 -
111.552 - CallbackSystemAction c = get();
111.553 -
111.554 - if (c != null) {
111.555 - c.updateEnabled();
111.556 - }
111.557 - }
111.558 - }
111.559 -
111.560 - /** A delegate action that is usually associated with a specific lookup and
111.561 - * extract the nodes it operates on from it. Otherwise it delegates to the
111.562 - * regular NodeAction.
111.563 - */
111.564 - private static final class DelegateAction extends Object implements Action,
111.565 - LookupListener, Presenter.Menu, Presenter.Popup, Presenter.Toolbar, PropertyChangeListener {
111.566 - /** action to delegate too */
111.567 - private CallbackSystemAction delegate;
111.568 -
111.569 - /** lookup we are associated with (or null) */
111.570 - private Lookup.Result<ActionMap> result;
111.571 -
111.572 - /** previous state of enabled */
111.573 - private boolean enabled;
111.574 -
111.575 - /** support for listeners */
111.576 - private PropertyChangeSupport support = new PropertyChangeSupport(this);
111.577 -
111.578 - /** listener to check listen on state of action(s) we delegate to */
111.579 - private PropertyChangeListener weakL;
111.580 -
111.581 - /** last action we were listening to */
111.582 - private Reference<Action> lastRef;
111.583 -
111.584 - public DelegateAction(CallbackSystemAction a, Lookup actionContext) {
111.585 - this.delegate = a;
111.586 - this.weakL = org.openide.util.WeakListeners.propertyChange(this, null);
111.587 - this.enabled = a.getActionPerformer() != null;
111.588 -
111.589 - this.result = actionContext.lookup(new Lookup.Template<ActionMap>(ActionMap.class));
111.590 - this.result.addLookupListener(WeakListeners.create(LookupListener.class, this, this.result));
111.591 - resultChanged(null);
111.592 - }
111.593 -
111.594 - /** Overrides superclass method, adds delegate description. */
111.595 - public String toString() {
111.596 - return super.toString() + "[delegate=" + delegate + "]"; // NOI18N
111.597 - }
111.598 -
111.599 - /** Invoked when an action occurs.
111.600 - */
111.601 - public void actionPerformed(final java.awt.event.ActionEvent e) {
111.602 - final Action a = findAction();
111.603 -
111.604 - if (a != null) {
111.605 - Runnable run = new Runnable() {
111.606 - public void run() {
111.607 - a.actionPerformed(e);
111.608 - }
111.609 - };
111.610 - org.openide.util.actions.ActionInvoker.invokeAction(delegate, e, delegate.asynchronous(), run);
111.611 - } else {
111.612 - // XXX #30303 if the action falls back to the old behaviour
111.613 - // it may not be performed in case it is in dialog and
111.614 - // is not transmodal.
111.615 - // This is just a hack, see TopComponent.processKeyBinding.
111.616 - Object source = e.getSource();
111.617 -
111.618 - if (
111.619 - source instanceof Component &&
111.620 - javax.swing.SwingUtilities.getWindowAncestor((Component) source) instanceof java.awt.Dialog
111.621 - ) {
111.622 - Object value = delegate.getValue("OpenIDE-Transmodal-Action"); // NOI18N
111.623 -
111.624 - if (!Boolean.TRUE.equals(value)) {
111.625 - return;
111.626 - }
111.627 - }
111.628 -
111.629 - delegate.actionPerformed(e);
111.630 - }
111.631 - }
111.632 -
111.633 - public boolean isEnabled() {
111.634 - Action a = findAction();
111.635 -
111.636 - if (a == null) {
111.637 - a = delegate;
111.638 - }
111.639 -
111.640 - // 40915 - hold last action weakly
111.641 - Action last = lastRef == null ? null : lastRef.get();
111.642 -
111.643 - if (a != last) {
111.644 - if (last != null) {
111.645 - last.removePropertyChangeListener(weakL);
111.646 - }
111.647 -
111.648 - lastRef = new WeakReference<Action>(a);
111.649 - a.addPropertyChangeListener(weakL);
111.650 - }
111.651 -
111.652 - return a.isEnabled();
111.653 - }
111.654 -
111.655 - public void addPropertyChangeListener(PropertyChangeListener listener) {
111.656 - support.addPropertyChangeListener(listener);
111.657 - }
111.658 -
111.659 - public void removePropertyChangeListener(PropertyChangeListener listener) {
111.660 - support.removePropertyChangeListener(listener);
111.661 - }
111.662 -
111.663 - public void putValue(String key, Object o) {
111.664 - }
111.665 -
111.666 - public Object getValue(String key) {
111.667 - return delegate.getValue(key);
111.668 - }
111.669 -
111.670 - public void setEnabled(boolean b) {
111.671 - }
111.672 -
111.673 - public void resultChanged(org.openide.util.LookupEvent ev) {
111.674 - boolean newEnabled = isEnabled();
111.675 -
111.676 - if (newEnabled != enabled) {
111.677 - support.firePropertyChange(PROP_ENABLED, enabled, newEnabled);
111.678 - enabled = newEnabled;
111.679 - }
111.680 - }
111.681 -
111.682 - public void propertyChange(PropertyChangeEvent evt) {
111.683 - resultChanged(null);
111.684 - }
111.685 -
111.686 - /*** Finds an action that we should delegate to
111.687 - * @return the action or null
111.688 - */
111.689 - private Action findAction() {
111.690 - Collection<? extends ActionMap> c = result != null ? result.allInstances() : Collections.<ActionMap>emptySet();
111.691 -
111.692 - if (!c.isEmpty()) {
111.693 - Object key = delegate.getActionMapKey();
111.694 - for (ActionMap map : c) {
111.695 - Action action = map.get(key);
111.696 - if (action != null) {
111.697 - return action;
111.698 - }
111.699 - }
111.700 - }
111.701 -
111.702 - return null;
111.703 - }
111.704 -
111.705 - public javax.swing.JMenuItem getMenuPresenter() {
111.706 - if (isMethodOverridden(delegate, "getMenuPresenter")) { // NOI18N
111.707 -
111.708 - return delegate.getMenuPresenter();
111.709 - } else {
111.710 - return org.openide.util.actions.ActionPresenterProvider.getDefault().createMenuPresenter(this);
111.711 - }
111.712 - }
111.713 -
111.714 - public javax.swing.JMenuItem getPopupPresenter() {
111.715 - if (isMethodOverridden(delegate, "getPopupPresenter")) { // NOI18N
111.716 -
111.717 - return delegate.getPopupPresenter();
111.718 - } else {
111.719 - return org.openide.util.actions.ActionPresenterProvider.getDefault().createPopupPresenter(this);
111.720 - }
111.721 - }
111.722 -
111.723 - public java.awt.Component getToolbarPresenter() {
111.724 - if (isMethodOverridden(delegate, "getToolbarPresenter")) { // NOI18N
111.725 -
111.726 - return delegate.getToolbarPresenter();
111.727 - } else {
111.728 - return org.openide.util.actions.ActionPresenterProvider.getDefault().createToolbarPresenter(this);
111.729 - }
111.730 - }
111.731 -
111.732 - private boolean isMethodOverridden(CallableSystemAction d, String name) {
111.733 - try {
111.734 - java.lang.reflect.Method m = d.getClass().getMethod(name, new Class[0]);
111.735 -
111.736 - return m.getDeclaringClass() != CallableSystemAction.class;
111.737 - } catch (java.lang.NoSuchMethodException ex) {
111.738 - ex.printStackTrace();
111.739 - throw new IllegalStateException("Error searching for method " + name + " in " + d); // NOI18N
111.740 - }
111.741 - }
111.742 -
111.743 - protected void finalize() {
111.744 - Action last = lastRef == null ? null : lastRef.get();
111.745 -
111.746 - if (last != null) {
111.747 - last.removePropertyChangeListener(weakL);
111.748 - }
111.749 - }
111.750 - }
111.751 - // end of DelegateAction
111.752 -}
112.1 --- a/openide.util/src/org/openide/util/doc-files/api.html Wed Jan 27 17:46:23 2010 -0500
112.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
112.3 @@ -1,1233 +0,0 @@
112.4 -<!--
112.5 -DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
112.6 -
112.7 -Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
112.8 -
112.9 -
112.10 -The contents of this file are subject to the terms of either the GNU
112.11 -General Public License Version 2 only ("GPL") or the Common
112.12 -Development and Distribution License("CDDL") (collectively, the
112.13 -"License"). You may not use this file except in compliance with the
112.14 -License. You can obtain a copy of the License at
112.15 -http://www.netbeans.org/cddl-gplv2.html
112.16 -or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
112.17 -specific language governing permissions and limitations under the
112.18 -License. When distributing the software, include this License Header
112.19 -Notice in each file and include the License file at
112.20 -nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
112.21 -particular file as subject to the "Classpath" exception as provided
112.22 -by Sun in the GPL Version 2 section of the License file that
112.23 -accompanied this code. If applicable, add the following below the
112.24 -License Header, with the fields enclosed by brackets [] replaced by
112.25 -your own identifying information:
112.26 -"Portions Copyrighted [year] [name of copyright owner]"
112.27 -
112.28 -Contributor(s):
112.29 -
112.30 -The Original Software is NetBeans. The Initial Developer of the Original
112.31 -Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
112.32 -Microsystems, Inc. All Rights Reserved.
112.33 -
112.34 -If you wish your version of this file to be governed by only the CDDL
112.35 -or only the GPL Version 2, indicate your decision by adding
112.36 -"[Contributor] elects to include this software in this distribution
112.37 -under the [CDDL or GPL Version 2] license." If you do not indicate a
112.38 -single choice of license, a recipient has the option to distribute
112.39 -your version of this file under either the CDDL, the GPL Version 2 or
112.40 -to extend the choice of license to its licensees as provided above.
112.41 -However, if you add GPL Version 2 code and therefore, elected the GPL
112.42 -Version 2 license, then the option applies only if the new code is
112.43 -made subject to such option by the copyright holder.
112.44 --->
112.45 -
112.46 -<html>
112.47 -<head>
112.48 -<title>Utility Classes</title>
112.49 -<link rel="Stylesheet" href="../../../../prose.css" type="text/css" title="NetBeans Open APIs Style">
112.50 -</head>
112.51 -<body>
112.52 -
112.53 -<p class="overviewlink"><a href="@TOP@overview-summary.html">Overview</a></p>
112.54 -
112.55 -<h1>Utility Classes</h1>
112.56 -
112.57 -Not all of the classes in this package are of interest for all module
112.58 -writers, but some of them may or even are as they are used through out
112.59 -our sources.
112.60 -
112.61 -<h2>Package <a href="../package-summary.html"><code>org.openide.util</code></a></h2>
112.62 -
112.63 -<ol>
112.64 - <li><a href="@org-openide-util-lookup@/org/openide/util/Lookup.html">Lookup</a> and its associated
112.65 - <a href="@org-openide-util-lookup@/org/openide/util/lookup/package-summary.html">support package</a> as that
112.66 - is the <em>adaptable</em> interface that objects can provide if
112.67 - they wish to offer dynamic capabilities.
112.68 - </li>
112.69 -
112.70 - <li><a href="../NbBundle.html">NbBundle</a> as our specialized support
112.71 - for localization and replacement to
112.72 - <a href="@JDK@/java/util/ResourceBundle.html">ResourceBundle</a>.
112.73 - </li>
112.74 -
112.75 - <li><a href="../Task.html"><code>Task</code></a> and especially
112.76 - <a href="../RequestProcessor.html"><code>RequestProcessor</code></a> which
112.77 - is our way to manage pools of thread workers and execute asynchronous
112.78 - computations.
112.79 - </li>
112.80 -
112.81 - <li>
112.82 - <a href="../HelpCtx.html"><code>HelpCtx</code></a> to specify help ids for
112.83 - various UI components
112.84 - </li>
112.85 -
112.86 - <li>
112.87 - <a href="../Utilities.html"><code>Utilities</code></a> which contain
112.88 - a lot of methods of possible interest. For example
112.89 - <a href="../Utilities.html#actionsGlobalContext()"><code>actionsGlobalContext</code></a>,
112.90 - <a href="../Utilities.html#loadImage(java.lang.String)"><code>loadImage</code></a>,
112.91 - <a href="../Utilities.html#mergeImages(java.awt.Image,%20java.awt.Image,%20int,%20int)"><code>mergeImage</code></a>,
112.92 - <a href="../Utilities.html#topologicalSort(java.util.Collection,%20java.util.Map)"><code>topologicalSort</code></a>,
112.93 - <a href="../Utilities.html#activeReferenceQueue()"><code>activeReferenceQueue</code></a>,
112.94 - <a href="../Utilities.html#translate(java.lang.String)"><code>translate</code></a>.
112.95 - </li>
112.96 -
112.97 - <li>
112.98 - <a href="../Enumerations.html"><code>Enumerations</code></a> provide
112.99 - enhacened support for manipulation with
112.100 - <a href="@JDK@/java/util/Enumeration.html">Enumeration</a>s and especially
112.101 - their on-demand generation.
112.102 - </li>
112.103 -</ol>
112.104 -
112.105 -<!--
112.106 -<li><a href="../io/package-summary.html"><code>org.openide.util.io</code></a>:
112.107 -
112.108 -a few extensions to the Java I/O system.
112.109 -
112.110 -<li><a href="../../xml/package-summary.html"><code>org.openide.xml</code></a>:
112.111 -
112.112 -general XML parsing, entity registration, and so on.
112.113 --->
112.114 -
112.115 -</a><h2>Services Registration and Lookup API</h2>
112.116 -
112.117 -
112.118 -<p>For lookup, this centers around
112.119 -
112.120 -<a href="@org-openide-util-lookup@/org/openide/util/Lookup.html"><code>Lookup</code></a>
112.121 -
112.122 -and helper implementations in
112.123 -
112.124 -<a href="@org-openide-util-lookup@/org/openide/util/lookup/package-summary.html"><code>org.openide.util.lookup</code></a>.
112.125 -
112.126 -
112.127 -
112.128 -<h3>Contents</h3>
112.129 -
112.130 -<ul>
112.131 -
112.132 -<li><a href="#lookup">Lookup</a>
112.133 -<ul>
112.134 -<li><a href="#instances">Working with Instances</a>
112.135 -<li><a href="#instance-folders">Folders of Instances</a>
112.136 -<li><a href="#service-lookup">Lookup and Service Installation</a>
112.137 -<li><a href="#lookup-ids">Persisting Lookup Information</a>
112.138 -<li><a href="#lookup-impl">Creating Lookups</a>
112.139 -<li><a href="#settings">Settings</a>
112.140 -<li><a href="#lookup-ui">UI for Services</a>
112.141 -</ul>
112.142 -
112.143 -</ul>
112.144 -
112.145 -
112.146 -<h2><a name="lookup">Lookup</a></h2>
112.147 -
112.148 -<div class="nonnormative">
112.149 -
112.150 -The whole NetBeans platform is moving toward
112.151 -installation of services via XML layer or (via the <code>@ServiceProvider</code> annotation on classes) <code>META-INF/services</code>.
112.152 -Layer-based installation is more flexible in many ways.
112.153 -
112.154 -<p>The need for having a standard interface to access such
112.155 -registrations
112.156 -gave rise to the <em>lookup</em> system first
112.157 -introduced in NetBeans 3.2 and expanded upon for NetBeans 3.3. The
112.158 -center of this API from the client perspective is very simple - you
112.159 -can look up a class, and get an instance of that class (or a
112.160 -collection of them). The service provider side of it is more complex
112.161 -but useful lookup implementations are already provided in the
112.162 -core system; for common cases you can register an object into lookup just by
112.163 -adding one simple file to an XML layer or <code>META-INF/services/classname</code>
112.164 -in your module JAR file.
112.165 -
112.166 -<p>This section of the Services API will first discuss what
112.167 -<em>instances</em> are and how to create them from files, as this is
112.168 -the core concept for service providers. It will discuss how you can
112.169 -manually retrieve sets of instances as a client, which is not used
112.170 -very frequently in new code but helps to understand what lookup is
112.171 -doing behind the scenes. Then lookup itself is discussed, and how the
112.172 -standard instance lookup works and how it relates to JDK's
112.173 -<a href="http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.html#Service%20Provider">
112.174 -standard for service provider registration</a>.
112.175 -Lookup templates, which separate the
112.176 -provision of instances from the provision of categories, will be
112.177 -explained.
112.178 -
112.179 -</div>
112.180 -
112.181 -<h3><a name="instances">Working with Instances</a></h3>
112.182 -
112.183 -Central to the management of services and many other aspects of
112.184 -NetBeans' configuration is the notion of
112.185 -<em>instances</em>. An instance is just any Java object, generally
112.186 -of a particular type appropriate to its use, which is provided from
112.187 -some object (generally, a data object) using
112.188 -
112.189 -<code>InstanceCookie</code>.
112.190 -
112.191 -As an example, menu items may be added by inserting data objects
112.192 -that provide this cookie into the proper folder, and having the
112.193 -instance be a system action (or other things). Or an XML DTD may be
112.194 -registered by placing an object with an instance of
112.195 -<code>org.xml.sax.EntityResolver</code> in the proper folder.
112.196 -
112.197 -<p>Where do these instances come from? Technically, it is up to you
112.198 -to decide how to provide <code>InstanceCookie</code>; you could if
112.199 -really necessary create your own data loader that provides it
112.200 -according to some unusual scheme, and add files recognized by that
112.201 -loader to the right folder. Practically, the APIs provide
112.202 -implementations of this cookie sufficient for normal purposes.
112.203 -
112.204 -<p>The most common way to provide an instance is using
112.205 -
112.206 -<code>InstanceDataObject</code>.
112.207 -
112.208 -This is a type of data object whose sole purpose is to provide the
112.209 -instance cookie. It typically does so based on a class name you
112.210 -supply. There are several styles of instance file; all are empty (i.e.
112.211 -the file contents are of zero length, and just the file name and
112.212 -attributes matter). There are then other ways of providing instances
112.213 -which rely on the file contents. Here are the methods of providing
112.214 -instances defined in the APIs:
112.215 -
112.216 -<dl>
112.217 -
112.218 -<dt><em>Default instance - <code>InstanceDataObject</code></em>
112.219 -
112.220 -<dd><p>If there is a file with the extension <samp>*.instance</samp>, then its
112.221 -name (minus extension) will be converted to a class name by replacing dashes
112.222 -with dots; and a fresh instance of that class will be created and used as the
112.223 -instance. For example, <samp>com-mycom-mymodule-MyAction.instance</samp>
112.224 -produces an instance of the class <code>com.mycom.mymodule.MyAction</code>.</p>
112.225 -
112.226 -<p>Since reflection is used to create the new instance, just as in the
112.227 -realm of JavaBeans, the class must be loadable from your module or
112.228 -otherwise from within NetBeans (technically, via the classloader found
112.229 -by querying Lookup for <code>ClassLoader</code>);
112.230 -public; and have a public no-argument constructor.
112.231 -(Or be a
112.232 -
112.233 -<a href="../SharedClassObject.html"><code>SharedClassObject</code></a>.)
112.234 -
112.235 -This form is often
112.236 -used for <em>singleton</em> classes such as system actions: there is
112.237 -no need to specify any parameters to the constructor, any instance
112.238 -will suffice.</p>
112.239 -
112.240 -
112.241 -<dt><em>Default instance with separate class - <code>InstanceDataObject</code></em>
112.242 -
112.243 -<dd><p>Rather than shoving the class name into
112.244 -the file name, you can name the file more normally and specify the
112.245 -class with a file attribute. Then the class name is specified as
112.246 -a string-valued attribute on the instance named
112.247 -<code>instanceClass</code>. For example, a keyboard shortcut
112.248 -could be registered as follows in an XML layer:</p>
112.249 -
112.250 -<pre>
112.251 -<<font class="function-name">file</font> <font class="variable-name">name</font>=<font class="constant">"C-F6.instance"</font>>
112.252 - <<font class="function-name">attr</font> <font class="variable-name">name</font>=<font class="constant">"instanceClass"</font> <font class="variable-name">stringvalue</font>=<font class="constant">"com.mycom.mymodule.MyAction"</font>/>
112.253 -</<font class="function-name">file</font>>
112.254 -</pre>
112.255 -
112.256 -<p>In addition to <code>instanceClass</code> you may specify an
112.257 -additional attribute <code>instanceOf</code> giving the name of a
112.258 -superclass (or implemented interface) of the instance class. In fact
112.259 -it may be a comma-separated list of superclasses and interfaces. While
112.260 -its purpose is explained more fully
112.261 -
112.262 -<a href="#instance-folders">below</a>,
112.263 -
112.264 -essentially it lets you give the system a hint as to what this
112.265 -instance is for before your instance class is even loaded into the VM.
112.266 -For example:</p>
112.267 -
112.268 -<pre>
112.269 -<<font class="function-name">file</font> <font class="variable-name">name</font>=<font class="constant">"com-me-some-service.instance"</font>>
112.270 - <<font class="function-name">attr</font> <font class="variable-name">name</font>=<font class="constant">"instanceClass"</font> <font class="variable-name">stringvalue</font>=<font class="constant">"com.me.FactoryForEverything"</font>/>
112.271 - <<font class="function-name">attr</font> <font class="variable-name">name</font>=<font class="constant">"instanceOf"</font>
112.272 - <font class="variable-name">stringvalue</font>=<font class="constant">"org.xml.sax.EntityResolver,org.openide.cookies.ExecCookie"</font>/>
112.273 -</<font class="function-name">file</font>>
112.274 -</pre>
112.275 -
112.276 -<dt><a name="ido-methodvalue"></a><em>Non-default instance - <code>InstanceDataObject</code></em>
112.277 -
112.278 -<dd><p>A powerful way of providing instances is to use the expressiveness
112.279 -of the XML layer syntax to handle the instance creation. In this case
112.280 -the file attribute <code>instanceCreate</code> can be defined and the
112.281 -attribute value becomes the instance. Typically the attribute value
112.282 -would be specified using the <code>methodvalue</code> syntax of
112.283 -layers. For example:</p>
112.284 -
112.285 -<pre>
112.286 -<<font class="function-name">file</font> <font class="variable-name">name</font>=<font class="constant">"com-me-some-service.instance"</font>>
112.287 - <<font class="function-name">attr</font> <font class="variable-name">name</font>=<font class="constant">"instanceClass"</font> <font class="variable-name">stringvalue</font>=<font class="constant">"com.me.FactoryForEverything"</font>/>
112.288 - <<font class="function-name">attr</font> <font class="variable-name">name</font>=<font class="constant">"instanceCreate"</font> <font class="variable-name">methodvalue</font>=<font class="constant">"com.me.FactoryForEverything.configure"</font>/>
112.289 - <<font class="function-name">attr</font> <font class="variable-name">name</font>=<font class="constant">"myParam"</font> <font class="variable-name">urlvalue</font>=<font class="constant">"nbres:/com/me/config-1.properties"</font>/>
112.290 - <<font class="function-name">attr</font> <font class="variable-name">name</font>=<font class="constant">"instanceOf"</font>
112.291 - <font class="variable-name">stringvalue</font>=<font class="constant">"org.xml.sax.EntityResolver,org.openide.cookies.ExecCookie"</font>/>
112.292 -</<font class="function-name">file</font>>
112.293 -</pre>
112.294 -
112.295 -<p>According to the general system for
112.296 -
112.297 -<code>XMLFileSystem</code>,
112.298 -
112.299 -you now need a method <code>configure</code> in
112.300 -<code>FactoryForEverything</code> which must be static; the method
112.301 -need not be public (if you do not want other Java code to see it). It
112.302 -may take a file object as argument if you wish - this will be the
112.303 -instance file; typically you use this to pass extra configuration from
112.304 -the layer, useful if you want to create multiple instances with the
112.305 -same creation method. So for example you might implement such a method
112.306 -like this:</p>
112.307 -
112.308 -<pre>
112.309 -<font class="keyword">public</font> <font class="keyword">class</font> <font class="type">FactoryForEverything</font> <font class="keyword">extends</font> <font class="type">SomeBaseFactory</font>
112.310 - <font class="keyword">implements</font> <font class="type">EntityResolver</font>, <font class="type">ExecCookie</font> {
112.311 - <font class="keyword">public</font> <font class="type">FactoryForEverything</font>(<font class="type">Map</font> <font class="variable-name">props</font>) {
112.312 - <font class="comment">// ...
112.313 -</font> }
112.314 - <font class="comment">// ...
112.315 -</font> <font class="comment">// Called directly from XML layer. Pass URL to
112.316 -</font> <font class="comment">// properties file from attr 'myParam'.
112.317 -</font> <font class="keyword">private</font> <font class="keyword">static</font> <font class="type">Object</font> <font class="function-name">configure</font>(<font class="type">FileObject</font> <font class="variable-name">inst</font>) <font class="keyword">throws</font> <font class="type">IOException</font> {
112.318 - <font class="type">URL</font> <font class="variable-name">u</font> = (<font class="type">URL</font>)inst.getAttribute(<font class="string">"myParam"</font>);
112.319 - <font class="type">Properties</font> <font class="variable-name">p</font> = <font class="keyword">new</font> <font class="type">Properties</font>();
112.320 - p.load(u.openStream());
112.321 - <font class="keyword">return</font> <font class="keyword">new</font> <font class="type">FactoryForEverything</font>(p);
112.322 - }
112.323 -}
112.324 -</pre>
112.325 -
112.326 -<dt><em>Serialized beans</em>
112.327 -
112.328 -<dd><p>A simple way to provide an instance is to serialize it as a
112.329 -JavaBean, into a file with the extension <samp>*.ser</samp>. This is
112.330 -not very useful from a layer, because you should avoid putting
112.331 -binary data into a layer, but may be useful in some circumstances.</p>
112.332 -
112.333 -<dt><a name="xml-instances"><em>XML-based instances</em></a></dt>
112.334 -
112.335 -
112.336 -<a href="../../xml/EntityCatalog.html"><code>EntityCatalog</code></a>
112.337 -
112.338 -
112.339 -<div class="nonnormative">
112.340 -
112.341 -<p>Again, modules may also have additional ways of providing instances
112.342 -from files. For example, currently the <code>utilities</code> module
112.343 -enables any URL file (<samp>*.url</samp>) to be used directly in a
112.344 -menu, as the URL file provides an instance of
112.345 -<code>Presenter.Menu</code>.</p>
112.346 -
112.347 -<p>As an interactive demonstration of these things, first go into
112.348 -<b>Filesystem Settings</b> and make the system filesystem (first in
112.349 -the list) visible; then explore its contents in <b>Filesystems</b>,
112.350 -going into some subdirectory of <samp>Menu</samp>. Note the various
112.351 -actions and menu separators; these are all by default instance data
112.352 -objects.
112.353 -You may find some of these on disk in your installation directory
112.354 -under <samp>system/</samp> if you have customized them, but by default
112.355 -they live in memory only.
112.356 -You may copy-and-paste these instances from one place to another;
112.357 -create new ones on disk and watch them be recognized and inserted
112.358 -into the menus after a few seconds; and you may also choose
112.359 -Customize Bean (which really customizes the provided instance) on
112.360 -(say) a toolbar separator (under <code>Toolbars</code>) to change
112.361 -the separator size, and serialize the result to a new
112.362 -<code>*.ser</code> file which should then create a toolbar
112.363 -separator.
112.364 -
112.365 -</div>
112.366 -
112.367 -<h3><a name="instance-folders">Folders of Instances</a></h3>
112.368 -
112.369 -
112.370 -<h4><a name="instancecookie-of"><code>InstanceCookie.Of</code> and lazy class loading</a></h4>
112.371 -
112.372 -Now it is time to mention the purpose of
112.373 -<code>InstanceCookie.Of</code>. Suppose that there are two generic
112.374 -interfaces under consideration: e.g. <code>javax.swing.Action</code>
112.375 -and <code>org.xml.sax.EntityResolver</code>. For each interface, there
112.376 -is code to find registered instances, all under the
112.377 -<samp>Services/</samp> folder. Furthermore, using either of these
112.378 -interfaces is relatively rare, and might not happen at all during a
112.379 -NetBeans session; and the implementations of the instances are complicated
112.380 -and involve a lot of code, so it is undesirable (for performance
112.381 -reasons) to load these implementations unless and until they are
112.382 -really needed. If you write the layers simply like this:
112.383 -
112.384 -<pre>
112.385 -<<font class="function-name">filesystem</font>>
112.386 - <<font class="function-name">folder</font> <font class="variable-name">name</font>=<font class="string">"Services"</font>>
112.387 - <<font class="function-name">folder</font> <font class="variable-name">name</font>=<font class="string">"Hidden"</font>>
112.388 - <<font class="function-name">file</font> <font class="variable-name">name</font>=<font class="string">"com-me-MyAction.instance"</font>/>
112.389 - <<font class="function-name">file</font> <font class="variable-name">name</font>=<font class="string">"com-me-MyResolver.instance"</font>/>
112.390 - </<font class="function-name">folder</font>>
112.391 - </<font class="function-name">folder</font>>
112.392 -</<font class="function-name">filesystem</font>>
112.393 -</pre>
112.394 -
112.395 -everything will work, <em>but</em> this is inefficient. Consider some
112.396 -piece of code asking for all actions. The search through the services
112.397 -folder for actions would ask each of these files if it provides an
112.398 -instance cookie assignable to <code>javax.swing.Action</code>. For
112.399 -<samp>com-me-MyAction.instance</samp>, this will load the class
112.400 -<code>com.me.MyAction</code>, determine that it implements
112.401 -<code>Action</code>, and thus create a <code>MyAction</code> instance
112.402 -and return it; so far so good. But when
112.403 -<samp>com-me-MyResolver.instance</samp> is encountered, it will again
112.404 -load <code>com.me.MyResolver</code>, only to find that this does not
112.405 -implement <code>Action</code> and skip the instance. The behavior is
112.406 -correct, but now the <code>MyResolver</code> class has been loaded
112.407 -into the VM even though no one will ever use it (unless a resolver
112.408 -search is made). This will degrade startup time and memory usage (and
112.409 -thus performance).
112.410 -
112.411 -<p>So the better solution is to mark each file in advance, saying what
112.412 -interfaces it is intended to provide in its instance:
112.413 -
112.414 -<pre>
112.415 -<<font class="function-name">filesystem</font>>
112.416 - <<font class="function-name">folder</font> <font class="variable-name">name</font>=<font class="string">"Services"</font>>
112.417 - <<font class="function-name">folder</font> <font class="variable-name">name</font>=<font class="string">"Hidden"</font>>
112.418 - <<font class="function-name">file</font> <font class="variable-name">name</font>=<font class="string">"com-me-MyAction.instance"</font>>
112.419 - <<font class="function-name">attr</font> <font class="variable-name">name</font>=<font class="string">"instanceOf"</font> <font class="variable-name">stringvalue</font>=<font class="string">"javax.swing.Action"</font>/>
112.420 - </<font class="function-name">file</font>>
112.421 - <<font class="function-name">file</font> <font class="variable-name">name</font>=<font class="string">"com-me-MyResolver.instance"</font>>
112.422 - <<font class="function-name">attr</font> <font class="variable-name">name</font>=<font class="string">"instanceOf"</font> <font class="variable-name">stringvalue</font>=<font class="string">"org.xml.sax.EntityResolver"</font>/>
112.423 - </<font class="function-name">file</font>>
112.424 - </<font class="function-name">folder</font>>
112.425 - </<font class="function-name">folder</font>>
112.426 -</<font class="function-name">filesystem</font>>
112.427 -</pre>
112.428 -
112.429 -<p>
112.430 -Now the folder instance processor for <code>Action</code> will pass
112.431 -over <samp>com-me-MyResolver.instance</samp> without needing to load
112.432 -<code>com.me.MyResolver</code>, since it sees that its interfaces are
112.433 -declared, and <code>Action</code> is not among them. Of course, the
112.434 -interface classes - <code>Action</code> and
112.435 -<code>EntityResolver</code> - need to be loaded right away, but they
112.436 -were probably already loaded anyway, so this is acceptable.
112.437 -</p>
112.438 -
112.439 -<p><strong>Caution:</strong> if you do supply an
112.440 -<code>instanceOf</code> attribute, but it does <em>not</em> list all
112.441 -of the implemented interfaces and superclasses of the actual
112.442 -implementation class (including that implementation class itself,
112.443 -which is not implied), a lookup query on one of the missing
112.444 -superclasses <em>may or may not</em> succeed. So you should include in
112.445 -<code>instanceOf</code> any superclasses and interfaces that you think
112.446 -someone might use in a lookup query, possibly including the actual
112.447 -implementation class.</p>
112.448 -
112.449 -<h3><a name="service-lookup">Lookup and Service Installation</a></h3>
112.450 -
112.451 -The client side of the lookup system centers around one class,
112.452 -
112.453 -<a href="@org-openide-util-lookup@/org/openide/util/Lookup.html"><code>Lookup</code></a>.
112.454 -
112.455 -In the simplest usage, all that is needed is to get some single
112.456 -instance of a given class (or subclass). For example, if some kind of
112.457 -service has been defined as an interface or abstract class, and you
112.458 -wish to find the implementation of it, you
112.459 -may simply use:
112.460 -
112.461 -<pre>
112.462 -<font class="type">MyService</font> <font class="variable-name">impl</font> = (<font class="type">MyService</font>)Lookup.getDefault().<a href="@org-openide-util-lookup@/org/openide/util/Lookup.html#lookup(java.lang.Class)">lookup</a>(MyService.<font class="keyword">class</font>);
112.463 -<font class="keyword">if</font> (impl == <font class="constant">null</font>) <font class="comment">/* nothing registered */</font> ...
112.464 -impl.useIt();
112.465 -</pre>
112.466 -
112.467 -Such implementation has to be registered by some module to the system.
112.468 -Either via layer as described above or as a JDK's
112.469 -<a href="http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.html#Service%20Provider">
112.470 -service provider</a>. If some module wants to register for example
112.471 -<font class="type">org.me.MyService</font> it shall provide file name
112.472 -<font class="function-name">META-INF/services/org.me.MyService</FONT> in its own JAR
112.473 -with single line containing name of the implementation class (for example
112.474 -<font class="type">org.you.MyServiceImpl</FONT>).
112.475 -This is normally done more easily by using the <code>@ServiceProvider</code> annotation in <code>MyService.java</code>.
112.476 -The lookup infrastructure
112.477 -will then load the implementation class and call its default constructor
112.478 -to answer the query in the above example.
112.479 -<P>
112.480 -
112.481 -<div class="nonnormative">
112.482 - The Lookup supports two small extensions to the
112.483 - <a href="http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.html#Service%20Provider">JDK's
112.484 - standard</a>. It allows a module to remove class registered by
112.485 - another one. That is why it is possible to write a module that
112.486 - disables the <font class="type">org.you.MyServiceImpl</font> implementation
112.487 - and provides its own. This the expected content of its
112.488 - <font class="function-name">META-INF/services/org.me.MyService</FONT> file:
112.489 - <PRE>
112.490 - # remove the other implementation (by prefixing the line with <em>#-</EM>)
112.491 - #-<font class="type">org.you.MyServiceImpl</FONT>
112.492 -
112.493 - # provide my own
112.494 - org.alien.MyServiceAlienImpl
112.495 - </PRE>
112.496 - The reason why the removal line starts with <em>#-</em> is to keep
112.497 - compatibility with JDK's implementation. The <em>#</em> means comment
112.498 - and thus JDK will not interpret the line and will not get confused by
112.499 - the <em>-</em> before class name.
112.500 -
112.501 - <p>Second extension allows ordering of items. The class implementing
112.502 - the interface can be followed by advisory position attribute. If
112.503 - multiple implementations are defined in one file then each can be
112.504 - followed by its own positioning attribute. When querying
112.505 - on an interface, items with a smaller position are guaranteed
112.506 - to be returned before items with a larger position. Items with no defined
112.507 - position are returned last. Example of content of
112.508 - <font class="function-name">META-INF/services/org.me.MyService</font>
112.509 - file could be:
112.510 - <pre>
112.511 - <font class="type">org.you.MyServiceImpl</font>
112.512 - #position=20
112.513 - <font class="type">org.you.MyMoreImportantServiceImpl</font>
112.514 - #position=10
112.515 - </pre>
112.516 - The <font class="function-name">MyMoreImportantServiceImpl</font>
112.517 - will be returned in lookup before the
112.518 - <font class="function-name">MyServiceImpl</font>.
112.519 - It is recommended to pick up larger numbers so that there is
112.520 - gap for other modules if they need to get in front of your item. And,
112.521 - again, to keep compatibility the position attribute must starts with
112.522 - comment delimiter.</p>
112.523 -<p>Both extensions are supported by <code>@ServiceProvider</code>.</p>
112.524 -</DIV>
112.525 -
112.526 -<P>
112.527 -If more than one implementation has been registered, the "first" will
112.528 -be returned. For example, if the implementations were present in the
112.529 -<samp>Services</samp> folder as <samp>*.instance</samp> files, then
112.530 -folder order would control this.
112.531 -
112.532 -<p>As mentioned above, the NetBeans default lookup searches in the
112.533 -<samp>Services</samp> folder and its subfolders for instances whose
112.534 -class matches the requested class. Technically, it looks for data
112.535 -objects with <code>InstanceCookie.Of</code> claiming to match the
112.536 -requested superclass, or plain <code>InstanceCookie</code> whose
112.537 -<code>instanceClass</code> is assignable to it.
112.538 -
112.539 -<p>Note that you may use this method to find singleton instances of
112.540 -subclasses of
112.541 -
112.542 -<a href="../SharedClassObject.html"><code>SharedClassObject</code></a>
112.543 -
112.544 -that have been registered in lookup (as is normally the case for
112.545 -
112.546 -system options).
112.547 -
112.548 -However for this purpose it is simpler to use the static finder method
112.549 -
112.550 -<a href="../SharedClassObject.html#findObject(java.lang.Class,%20boolean)"><code>SharedClassObject.findObject(Class, true)</code></a>
112.551 -
112.552 -which is guaranteed to find the singleton whether it was registered in
112.553 -lookup or not (if necessary it will first
112.554 -
112.555 -<a href="#settings">initialize</a>
112.556 -
112.557 -the object according to saved state).
112.558 -
112.559 -<p>In many situations it is normal for there to be more than one
112.560 -registered implementation of a service. In such a case you use a more
112.561 -general method:
112.562 -
112.563 -<pre>
112.564 -<font class="type"><a href="@org-openide-util-lookup@/org/openide/util/Lookup.Template.html">Lookup.Template</a></font> <font class="variable-name">templ</font> = <font class="keyword">new</font> <font class="type">Lookup.Template</font>(MyService.<font class="keyword">class</font>);
112.565 -<font class="keyword">final</font> <font class="type"><a href="@org-openide-util-lookup@/org/openide/util/Lookup.Result.html">Lookup.Result</a></font> <font class="variable-name">result</font> = Lookup.getDefault().lookup(templ);
112.566 -<font class="type">Collection</font> <font class="variable-name">impls</font> = result.allInstances(); <font class="comment">// Collection<MyService>
112.567 -// use Java Collections API to get iterator, ...
112.568 -// Pay attention to subsequent changes in the result.
112.569 -</font>result.addLookupListener(<font class="keyword">new</font> <font class="type"><a href="@org-openide-util-lookup@/org/openide/util/LookupListener.html">LookupListener</a></font>() {
112.570 - <font class="keyword">public</font> <font class="type">void</font> <font class="function-name">resultChanged</font>(<font class="type">LookupEvent</font> <font class="variable-name">ev</font>) {
112.571 - <font class="comment">// Now it is different.
112.572 -</font> <font class="type">Collection</font> <font class="variable-name">impls2</font> = result.allInstances();
112.573 - <font class="comment">// use the new list of instances...
112.574 -</font> }
112.575 -});
112.576 -</pre>
112.577 -
112.578 -Here you receive a collection of all instances matching your query,
112.579 -again in the order found if this matters. You can also listen to
112.580 -changes in the list (additions, deletions, and reorderings). It is
112.581 -fine to keep a <code>Lookup.Result</code> for a long period of time as
112.582 -it may implement its own caching scheme and only really compute the
112.583 -instances when <code>allInstances</code> is called; in fact it may be
112.584 -more efficient to keep a result, and listen for changes in it, than to
112.585 -repeatedly call <code>lookup</code> and create fresh result objects.
112.586 -
112.587 -<p>When a lookup query is finished - for example when
112.588 -<code>Lookup.Result.allInstances()</code> returns some
112.589 -<code>Collection</code> of instances - it is guaranteed that all
112.590 -objects registered in the same thread prior to the call to
112.591 -<code>lookup()</code> or prior to some change notification on the
112.592 -<code>Lookup.Result</code>, will be returned. Specifically, lookup
112.593 -instances registered via module layer will be available by the time
112.594 -<code>ModuleInstall.restored()</code> (or <code>.installed()</code>)
112.595 -is called. There are two situations in which lookup results may be
112.596 -incomplete: when you are currently inside the dynamic scope of some
112.597 -method providing a lookup instance itself; and when you are
112.598 -dynamically inside a <code>DataLoader</code> method involved in
112.599 -recognizing data objects.
112.600 -
112.601 -<h3><a name="lookup-ids">Persisting Lookup Information</a></h3>
112.602 -
112.603 -In some circumstances it is necessary to not only find registered
112.604 -objects, but to select some of them and make this selection
112.605 -persistent. For example, some setting may have as its value a choice
112.606 -among available services matching some interface; the value needs to
112.607 -be persisted, but it is the identity of the choice, rather than the
112.608 -full state of the instance itself, which must be stored.
112.609 -
112.610 -<p>In such cases it is possible to use code like this:
112.611 -
112.612 -<pre>
112.613 -<font class="type">Lookup.Template</font> <font class="variable-name">templ</font> = <font class="keyword">new</font> <font class="type">Lookup.Template</font>(MyService.<font class="keyword">class</font>);
112.614 -<font class="type">Lookup.Result</font> <font class="variable-name">result</font> = Lookup.getDefault().lookup(templ);
112.615 -<font class="type">Iterator</font> <font class="variable-name">it</font> = result.allItems().iterator();
112.616 -<font class="keyword">while</font> (it.hasNext()) {
112.617 - <font class="type"><a href="@org-openide-util-lookup@/org/openide/util/Lookup.Item.html">Lookup.Item</a></font> <font class="variable-name">item</font> = (<font class="type">Lookup.Item</font>)it.next();
112.618 - <font class="type">String</font> <font class="variable-name">displayName</font> = item.getDisplayName();
112.619 - <font class="keyword">if</font> (<font class="comment">/* user accepts displayName as the right one */</font>) {
112.620 - <font class="type">MyService</font> <font class="variable-name">instance</font> = (<font class="type">MyService</font>)item.getInstance();
112.621 - <font class="comment">// use instance for now, and ...
112.622 -</font> <font class="type">String</font> <font class="variable-name">id</font> = item.getId();
112.623 - someSettings.setChosenService(id);
112.624 - <font class="keyword">break</font>;
112.625 - }
112.626 -}
112.627 -<font class="comment">// later...
112.628 -</font><font class="type">String</font> <font class="variable-name">storedID</font> = someSettings.getChosenService();
112.629 -<font class="type">Lookup.Template</font> <font class="variable-name">templ</font> = <font class="keyword">new</font> <font class="type"><a href="@org-openide-util-lookup@/org/openide/util/Lookup.Template.html#Lookup.Template(java.lang.Class,java.lang.String,java.lang.Object)">Lookup.Template</a></font>(MyService.<font class="keyword">class</font>, storedID, <font class="constant">null</font>);
112.630 -<font class="type">Iterator</font> <font class="variable-name">it</font> = Lookup.getDefault().lookup(templ).allInstances().iterator();
112.631 -<font class="keyword">if</font> (! it.hasNext()) <font class="comment">/* failed to find it... */</font>
112.632 -<font class="type">MyService</font> <font class="variable-name">instance</font> = (<font class="type">MyService</font>)it.next();
112.633 -<font class="comment">// use instance again
112.634 -</font></pre>
112.635 -
112.636 -The ID permits you to track which instance from all those available in
112.637 -the lookup result was last selected by the user, and find the "same"
112.638 -instance later, perhaps after a restart of NetBeans. The exact form of
112.639 -the ID is the private knowledge of the implementor of the lookup, but
112.640 -typically if the instance has been provided via layer the ID will
112.641 -mention the name of the file from which it was derived.
112.642 -
112.643 -<h3><a name="lookup-impl">Creating Lookups</a></h3>
112.644 -
112.645 -There are a number of reasons to create your own lookup
112.646 -implementation. For one thing, the lookup system which scans the
112.647 -<samp>Services/</samp> folder will recognize instances of subclasses
112.648 -of <code>Lookup</code> specially by <em>proxying</em> to them. This
112.649 -can be very powerful because you may register just one layer file
112.650 -which points to your custom lookup, which in turn may provide an
112.651 -unlimited number of actual instances/items for queries (and compute
112.652 -them in a manner other than registration by files). Another reason is
112.653 -to associate a context with a data object using
112.654 -
112.655 -<code>Environment.Provider</code>;
112.656 -
112.657 -for example the data object might be an XML file and this provider
112.658 -might be registered with the file by means of the public ID of the
112.659 -doctype (informally, the DTD). Here the provider has an associated
112.660 -lookup which can serve requests for cookies and such things.
112.661 -See more information about <a href="#xml-instances">associating lookups
112.662 -with XML files</a>.
112.663 -
112.664 -<p>The simplest way to create a fresh lookup is to base it on other
112.665 -existing ones.
112.666 -
112.667 -<a href="@org-openide-util-lookup@/org/openide/util/lookup/ProxyLookup.html"><code>ProxyLookup</code></a>
112.668 -
112.669 -accepts a list of other lookup implementations (in the constructor and
112.670 -also changeable later). The results it provides are constructed by
112.671 -merging together the results of the delegate lookups.
112.672 -
112.673 -<p>
112.674 -<a name="folderlookup"></a>
112.675 -
112.676 -If you want to use the common mechanism of finding instances in
112.677 -folders (or subfolders) and serving these as the results,
112.678 -
112.679 -<a href="@org-openide-util-lookup@/org/openide/util/lookup/Lookups.html#forPath(java.lang.String)">Lookups.forPath(String)</a>
112.680 -
112.681 -makes this possible: you need only provide a name of a folder to look in, and
112.682 -use
112.683 -
112.684 -<code>Lookups.forPath(theFolderName)</code>
112.685 -
112.686 -to retrieve a lookup implementation which will scan this folder and
112.687 -its subfolders for data objects with <code>InstanceCookie</code>
112.688 -matching the lookup template. Furthermore, any instance cookies whose
112.689 -instance class is assignable to <code>Lookup</code> will be treated
112.690 -specially: they will be proxied to, so these sub-lookups may provide
112.691 -additional instances if they match the lookup template. In order to
112.692 -get the full functionality associated with such a lookup it is wise
112.693 -to request presence of <code>org.netbeans.modules.settings > 1.13</code>
112.694 -as that is the module that does most of the work behind <code>Lookups.forPath</code>.
112.695 -To register <code>javax.xml.parsers.DocumentBuilderFactory</code> into
112.696 -<code>Lookups.forName("my/xml/app/data")</code> add the above described dependency
112.697 -and put following code in your layer file:
112.698 -<pre>
112.699 -<folder name="my">
112.700 - <folder name="xml">
112.701 - <folder name="app">
112.702 - <folder name="data">
112.703 - <file name="ThisIsMyRegistration.instance>
112.704 - <attr name="instanceCreate" newvalue="pkg.ClassNameOfYourImpl"/>
112.705 - </file>
112.706 - </folder>
112.707 - </folder>
112.708 - </folder>
112.709 -</folder>
112.710 -</pre>
112.711 -
112.712 -<p>
112.713 -In fact the <code>Lookups.forPath</code> can be used in completely
112.714 -standalone mode. This is not very recommended in the NetBeans IDE, but
112.715 -can be found pretty useful when using this library in standalone applications:
112.716 -<code>Lookups.forPath(path)</code> scans all instances registered in the
112.717 -<a href="#service-lookup">META-INF/services style</a> just it uses
112.718 -<code>META-INF/namedservices/path</code> prefix instead.
112.719 -(<code>@ServiceProvider</code> supports this mode.)
112.720 -As a result to
112.721 -perform a successfull search for all <code>javax.xml.parsers.DocumentBuilderFactory</code>
112.722 -inside <code>Lookups.forName("my/xml/app/data")</code> one can register the
112.723 -implementation into <code>META-INF/namedservices/my/xml/app/data/javax.xml.parsers.DocumentBuilderFactory</code>.
112.724 -</p>
112.725 -
112.726 -<p>The most powerful way to provide a lookup is to directly define
112.727 -what instances and items it should provide, by subclassing. For this,
112.728 -
112.729 -<a href="@org-openide-util-lookup@/org/openide/util/lookup/AbstractLookup.html"><code>AbstractLookup</code></a>
112.730 -
112.731 -is recommended as it is easiest to use.
112.732 -
112.733 -<p>The simplest way to use <code>AbstractLookup</code> is to use its
112.734 -public constructor (in which case you need not subclass it). Here you
112.735 -provide an
112.736 -
112.737 -<a href="@org-openide-util-lookup@/org/openide/util/lookup/AbstractLookup.Content.html"><code>AbstractLookup.Content</code></a>
112.738 -
112.739 -object which you have created and hold on to privately, and which
112.740 -keeps track of instances and permits them to be registered and
112.741 -deregistered. Often
112.742 -
112.743 -<a href="@org-openide-util-lookup@/org/openide/util/lookup/InstanceContent.html"><code>InstanceContent</code></a>
112.744 -
112.745 -is used as the content implementation. To add something to the lookup,
112.746 -simply use
112.747 -
112.748 -<a href="@org-openide-util-lookup@/org/openide/util/lookup/InstanceContent.html#add(java.lang.Object)"><code>add(Object)</code></a>
112.749 -
112.750 -(and <code>remove(Object)</code> for the reverse). These may be called
112.751 -at any time and will update the set of registered instances (firing
112.752 -result changes as needed).
112.753 -
112.754 -<p>In case it is expensive to actually compute the object in the
112.755 -lookup, but there is some cheap "key" which can easily generate it,
112.756 -you may instead register the key by passing in an
112.757 -
112.758 -<a href="@org-openide-util-lookup@/org/openide/util/lookup/InstanceContent.Convertor.html"><code>InstanceContent.Convertor</code></a>.
112.759 -
112.760 -This convertor translates the key to the real instance that the lookup
112.761 -client sees, if and when needed. For example, if you have a long list
112.762 -of class names and wish to register default instances of each class,
112.763 -you might actually register the class name as the key, and supply a
112.764 -convertor which really loads the class and instantiates it. This makes
112.765 -it easy to set up the lookup, but nothing is really loaded until
112.766 -someone asks for it.
112.767 -
112.768 -<h3><a name="settings">Settings</a></h3>
112.769 -
112.770 -<em>Settings</em> require special support in the lookup system: these
112.771 -are objects (perhaps singletons but not necessarily) which should be
112.772 -made available to lookup, yet whose content can be changed and stored
112.773 -to disk (typically as a result of user interaction with the GUI).
112.774 -<samp>*.instance</samp> files and similar constructions are fine for
112.775 -registering fixed objects from layer - "fixed" in the sense that while
112.776 -the user might copy, delete, move, or reorder them, the actual object
112.777 -they provide is statically determined and does not generally have a
112.778 -means of being modified. In contrast, settings have nontrivial
112.779 -content. A typical setting is a system options,
112.780 -simply a singleton bean with a set of properties and a structured GUI
112.781 -presentation driven by <code>BeanInfo</code>.
112.782 -
112.783 -<p>In order to save such settings, an XML file is normally used, and
112.784 -the APIs provide a convenient
112.785 -
112.786 -<a href="http://www.netbeans.org/dtds/sessionsettings-1_0.dtd">DTD</a>
112.787 -
112.788 -for settings which can be represented as a single bean. In typical
112.789 -usage, the module layer declares an initial settings file which
112.790 -instructs lookup to create a <em>default instance</em> of the settings
112.791 -class. This might look like the following:
112.792 -
112.793 -<pre>
112.794 -<?<font class="keyword">xml</font> <font class="variable-name">version</font>=<font class="string">"1.0"</font>?>
112.795 -<!<font class="keyword">DOCTYPE</font> <font class="type">settings</font> <font class="keyword">PUBLIC</font> <font class="string">"-//NetBeans//DTD Session settings 1.0//EN"</font> <font class="string">"http://www.netbeans.org/dtds/sessionsettings-1_0.dtd"</font>>
112.796 -<<font class="function-name">settings</font> <font class="variable-name">version</font>=<font class="string">"1.0"</font>>
112.797 - <<font class="function-name">module</font> <font class="variable-name">name</font>=<font class="string">"com.foo/1"</font> <font class="variable-name">spec</font>=<font class="string">"1.0"</font>/>
112.798 - <<font class="function-name">instanceof</font> <font class="variable-name">class</font>=<font class="string">"org.openide.options.SystemOption"</font>/>
112.799 - <<font class="function-name">instanceof</font> <font class="variable-name">class</font>=<font class="string">"com.foo.MyOption"</font>/>
112.800 - <<font class="function-name">instance</font> <font class="variable-name">class</font>=<font class="string">"com.foo.MyOption"</font>/>
112.801 -</<font class="function-name">settings</font>>
112.802 -</pre>
112.803 -
112.804 -Such a file might be placed in
112.805 -<samp>Services/com-foo-my-settings.xml</samp> (the exact name inside
112.806 -the <samp>Services</samp> folder is not important but ought to be
112.807 -globally unique to avoid conflicts with other modules). It provides
112.808 -an <code>InstanceCookie</code> with the settings object as instance.
112.809 -
112.810 -<p>The interesting parts of this file are:
112.811 -
112.812 -<ul>
112.813 -
112.814 -<li>The <samp><instance/></samp> element which declares that the
112.815 -actual object will be a default instance of the class
112.816 -<samp>com.foo.MyOption</samp>, i.e. created via default public
112.817 -constructor.
112.818 -
112.819 -<li>Various <samp><instanceof/></samp> elements which specify
112.820 -what lookup templates will find this instance. Giving these elements
112.821 -permits the system to defer creating the setting instance until it is
112.822 -actually requested (that is, using
112.823 -
112.824 -<a href="#instancecookie-of"><code>InstanceCookie.Of</code></a>).
112.825 -
112.826 -It is only necessary to indicate superclasses and interfaces that you
112.827 -actually expect someone to look up when searching for this setting,
112.828 -but be careful that you know what these might be. The actual class
112.829 -of the instance itself should be listed as well.
112.830 -
112.831 -<li>An optional but recommended <samp><module/></samp> element
112.832 -that declares which module provides this setting. You give the full
112.833 -code name (including a slash followed by the major release version, if applicable)
112.834 -of the module and its specification version. The purpose of
112.835 -this element becomes apparent if the user ever customizes the setting
112.836 -file, thus writing the changes to disk (for example in the
112.837 -<samp>system/Services/</samp> folder), and then uninstalls the module:
112.838 -keeping the name of the declaring module in the file ensures that with
112.839 -the module uninstalled, the system will quietly ignore the stale
112.840 -setting rather than trying to blithely load the settings class and
112.841 -failing with a <code>ClassNotFoundException</code>. If the module is
112.842 -subsequently reinstalled, the setting will automatically become active
112.843 -again (regain its <code>InstanceCookie</code>). Similarly, settings will
112.844 -not be loaded if they were written by a newer version of the module than
112.845 -the one currently installed - module-supplied settings should be readable
112.846 -by newer versions of the module, but generally not older ones.
112.847 -
112.848 -</ul>
112.849 -
112.850 -<p>There are actually three ways that the instance may be declared:</p>
112.851 -
112.852 -<ol>
112.853 -
112.854 -<li><p>Using <samp><instance/></samp> as above to generate a
112.855 -default instance. This is most common.</p>
112.856 -
112.857 -<li><p>You may pass an additional attribute <code>method</code>
112.858 -indicating a static method to call to produce
112.859 -the instance, rather than using a default constructor.
112.860 -The method may either be a simple name, in which case it is assumed
112.861 -to be a method in the class given by <code>class</code>, or you
112.862 -may give a full class name followed by a dot and method name to invoke
112.863 -a static method from some other class.
112.864 -The method may
112.865 -optionally take a <code>FileObject</code> argument which will be the
112.866 -settings file itself. This is analogous to the mechanism used for
112.867 -creating complex <samp>*.instance</samp> files. For example:</p>
112.868 -
112.869 -<pre>
112.870 -<<font class="function-name">file</font> <font class="variable-name">name</font>=<font class="string">"some-difficult-to-make-instance.settings"</font>>
112.871 - <![<font class="keyword">CDATA</font>[<?<font class="keyword">xml</font> <font class="variable-name">version</font>=<font class="string">"1.0"</font> <font class="variable-name">encoding</font>=<font class="string">"UTF-8"</font>?>
112.872 -<!<font class="keyword">DOCTYPE</font> <font class="type">settings</font> <font class="keyword">PUBLIC</font>
112.873 - <font class="string">"-//NetBeans//DTD Session settings 1.0//EN"</font>
112.874 - <font class="string">"http://www.netbeans.org/dtds/sessionsettings-1_0.dtd"</font>>
112.875 -<<font class="function-name">settings</font> <font class="variable-name">version</font>=<font class="string">"1.0"</font>>
112.876 - <<font class="function-name">module</font> <font class="variable-name">name</font>=<font class="string">"my.module/1"</font> <font class="variable-name">spec</font>=<font class="string">"1.0"</font>/>
112.877 - <<font class="function-name">instanceof</font> <font class="variable-name">class</font>=<font class="string">"javax.swing.Action"</font>/>
112.878 - <<font class="function-name">instanceof</font> <font class="variable-name">class</font>=<font class="string">"my.module.MyAction"</font>/>
112.879 - <<font class="function-name">instance</font> <font class="variable-name">class</font>=<font class="string">"my.module.MyAction"</font> <font class="variable-name">method</font>=<font class="string">"createAction"</font>/>
112.880 -</<font class="function-name">settings</font>>
112.881 -]]>
112.882 - <<font class="function-name">attr</font> <font class="variable-name">name</font>=<font class="string">"param"</font> <font class="variable-name">stringvalue</font>=<font class="string">"someval"</font>/>
112.883 -</<font class="function-name">file</font>>
112.884 -</pre>
112.885 -
112.886 -<pre>
112.887 -<font class="keyword">package</font> <font class="constant">my</font>.<font class="constant">module</font>;
112.888 -<font class="keyword">public</font> <font class="keyword">class</font> <font class="type">MyAction</font> <font class="keyword">extends</font> <font class="type">javax.swing.AbstractAction</font> {
112.889 - <font class="keyword">public</font> <font class="type">MyAction</font>(<font class="type">String</font> <font class="variable-name">name</font>) {<font class="comment">/* ... */</font>}
112.890 - <font class="comment">// ...
112.891 -</font> <font class="keyword">public</font> <font class="keyword">static</font> <font class="type">MyAction</font> <font class="function-name">createAction</font>(<font class="type">FileObject</font> <font class="variable-name">fo</font>) {
112.892 - <font class="keyword">return</font> <font class="keyword">new</font> <font class="type">MyAction</font>((<font class="type">String</font>)fo.getAttribute(<font class="string">"param"</font>));
112.893 - }
112.894 -}
112.895 -</pre>
112.896 -
112.897 -<p>This will result in an instance of <code>MyAction</code> being
112.898 -created with name <samp>someval</samp>.</p>
112.899 -
112.900 -<li><p>You may use the <samp><serialdata></samp> element. Its
112.901 -textual contents are a hexadecimal dump (whitespace ignored) of the
112.902 -raw serialized bytes of an object to serve as the instance. Naturally
112.903 -this is the least preferred mechanism as it is not human-readable.</p>
112.904 -
112.905 -</ol>
112.906 -
112.907 -<p class="nonnormative">(You can configure your persistance style by using
112.908 -<a href="@org-netbeans-modules-settings@/org/netbeans/api/settings/ConvertAsProperties.html">@ConvertAsProperties</a> or
112.909 -<a href="@org-netbeans-modules-settings@/org/netbeans/api/settings/ConvertAsJavaBean.html">@ConvertAsJavaBean</a>
112.910 -instead).</p>
112.911 -
112.912 -<p>A client can find the current setting in a couple of ways:
112.913 -
112.914 -<ul>
112.915 -
112.916 -<li>In the common case of <code>SystemOption</code>, you may simply
112.917 -call
112.918 -
112.919 -<a href="../SharedClassObject.html#findObject(java.lang.Class,%20boolean)"><code>SharedClassObject.findObject(Class, true)</code></a>
112.920 -
112.921 -which will either provide a previously initialized singleton, or find
112.922 -the setting in lookup if possible and read any customized state before
112.923 -returning it. You may then use property change listeners as needed to
112.924 -listen for changes.
112.925 -
112.926 -<li>Just ask the system lookup for the settings class (or a relevant
112.927 -superclass). This can be used to retrieve non-singleton settings; use
112.928 -the lookup result to track changes in the list of setting instances,
112.929 -and some ad-hoc method to track runtime changes in individual
112.930 -instances.
112.931 -
112.932 -</ul>
112.933 -
112.934 -<p>How does the customization of setting instances work? After finding a
112.935 -setting instance via this DTD, the system will automatically look for
112.936 -a beans-style event set of type <code>PropertyChangeListener</code>,
112.937 -and add its own listener. If the bean changes state (either
112.938 -programmatically or as a result of user manipulation), the property
112.939 -change will cause the new state to be written out to the original XML
112.940 -file, keeping the same name. (Normally this would mean the XML would
112.941 -be written to disk in the user directory.)</p>
112.942 -
112.943 -<p class="nonnormative">(Historically the state of an object is simply
112.944 - serialized into
112.945 -the XML file using <samp><serialdata></samp>, meaning the class
112.946 -must be <code>Serializable</code>, but you can choose different form
112.947 -of persistance by using
112.948 -<a href="@org-netbeans-modules-settings@/org/netbeans/api/settings/ConvertAsProperties.html">@ConvertAsProperties</a> or
112.949 -<a href="@org-netbeans-modules-settings@/org/netbeans/api/settings/ConvertAsJavaBean.html">@ConvertAsJavaBean</a>
112.950 -instead).</p>
112.951 -
112.952 -<p>Conversely, changes to the setting file on disk should trigger a
112.953 -reload of the state and modification of the in-memory bean (or
112.954 -creation of a new instance cookie with a new bean).</p>
112.955 -
112.956 -<h3><a name="lookup-ui">UI for Services</a></h3>
112.957 -
112.958 -<p>There are several things you can do to not only have services and
112.959 -lookup function programmatically but also look good and behave nicely
112.960 -within the user's view of configuration options and settings.</p>
112.961 -
112.962 -<h4><a name="service-templates">Service Templates</a></h4>
112.963 -
112.964 -<p>For many kinds of services, especially <code>ServiceType</code>s
112.965 -but also others, it is necessary to permit the user to create new
112.966 -instances of the service. Generally two criteria should be met for
112.967 -such services:</p>
112.968 -
112.969 -<ol>
112.970 -
112.971 -<li>The service is not a singleton, so it is meaningful to have more
112.972 -than one instance.
112.973 -
112.974 -<li>The service has some user-configurable properties, so it is useful
112.975 -to have more than one instance.
112.976 -
112.977 -</ol>
112.978 -
112.979 -<p>Creation of new service instances may be supported simply by
112.980 -producing a template residing beneath
112.981 -<samp>Templates/Services/</samp>. If the service normally resides in a
112.982 -subfolder of services, for example <samp>Services/Executor/</samp>,
112.983 -then the template should correspondingly be placed in
112.984 -<samp>Templates/Services/Executor/</samp>.</p>
112.985 -
112.986 -<div class="nonnormative">
112.987 -
112.988 -<p>The template should work like regular source code templates do: a
112.989 -file giving the initial structure of the service (typically a
112.990 -<samp>*.settings</samp> file), with the file attribute
112.991 -<code>template</code> set to <samp>true</samp>, and optionally a
112.992 -<code>templateWizardDescription</code> and
112.993 -<code>templateWizardURL</code>. For example:</p>
112.994 -
112.995 -<pre>
112.996 -<<font class="function-name">folder</font> <font class="variable-name">name</font>=<font class="string">"Templates"</font>>
112.997 - <<font class="function-name">folder</font> <font class="variable-name">name</font>=<font class="string">"Services"</font>>
112.998 - <<font class="function-name">folder</font> <font class="variable-name">name</font>=<font class="string">"Executor"</font>>
112.999 - <<font class="function-name">file</font> <font class="variable-name">name</font>=<font class="string">"my-module-executor.settings"</font> <font class="variable-name">url</font>=<font class="string">"executor.settings"</font>>
112.1000 - <<font class="function-name">attr</font> <font class="variable-name">name</font>=<font class="string">"template"</font> <font class="variable-name">boolvalue</font>=<font class="string">"true"</font>/>
112.1001 - <font class="comment"><!-- SystemFileSystem.localizedName and SystemFileSystem.icon as usual --></font>
112.1002 - </<font class="function-name">file</font>>
112.1003 - </<font class="function-name">folder</font>>
112.1004 - </<font class="function-name">folder</font>>
112.1005 -</<font class="function-name">folder</font>>
112.1006 -</pre>
112.1007 -
112.1008 -<p>If the user selects <b>New From Template</b> on the
112.1009 -corresponding options folder, the template will be available.</p>
112.1010 -
112.1011 -</div>
112.1012 -
112.1013 -<!-- XXX is the file attribute 'simple'=false supported? Yarda says it was a hack only -->
112.1014 -
112.1015 -<h4><a name="service-mirroring">Services display area and mirroring</a></h4>
112.1016 -
112.1017 -<p>In addition to providing services, it is desirable to display them
112.1018 -to the user as well. This is done, as is customary in other aspects of
112.1019 -NetBeans configuration, by displaying customized variants of the data
112.1020 -nodes coming from the system filesystem. The root folder for
112.1021 -displaying options is called <samp>UI/Services/</samp>. Its subfolders
112.1022 -govern the display of the options available in the system.</p>
112.1023 -
112.1024 -<p>As a rule, it is undesirable to place any actual settings in this
112.1025 -folder (nor would they be recognized by the default lookup anyway).
112.1026 -That is because the organization of this folder is driven by UI needs,
112.1027 -without regards to API maintenance or compatibility of persisted user
112.1028 -settings. So this folder solely <em>mirrors</em> configuration
112.1029 -available elsewhere. You may freely reorganize the mirror according to
112.1030 -current UI needs: existing modules plugging into services areas will
112.1031 -continue to work unmodified, and existing user customizations stored
112.1032 -to disk will continue to apply, since both of these act on the
112.1033 -original files (which should <em>not</em> be moved frivolously).</p>
112.1034 -
112.1035 -<div class="nonnormative">
112.1036 -
112.1037 -<p>While technically you could place anything you wish in the UI
112.1038 -folder, in practice a few types of things are used:</p>
112.1039 -
112.1040 -<ul>
112.1041 -
112.1042 -<li><p>Symbolic links to settings files displayed elsewhere. In
112.1043 -NetBeans' old-style options, these will appear as the real setting. For example:</p>
112.1044 -
112.1045 -<pre>
112.1046 -<<font class="function-name">folder</font> <font class="variable-name">name</font>=<font class="string">"UI"</font>>
112.1047 - <<font class="function-name">folder</font> <font class="variable-name">name</font>=<font class="string">"Services"</font>>
112.1048 - <<font class="function-name">folder</font> <font class="variable-name">name</font>=<font class="string">"Editing"</font>>
112.1049 - <<font class="function-name">file</font> <font class="variable-name">name</font>=<font class="string">"my-module-config.shadow"</font>>
112.1050 - <<font class="function-name">attr</font> <font class="variable-name">name</font>=<font class="string">"originalFile"</font> <font class="variable-name">stringvalue</font>=<font class="string">"Services/my-module-Config.settings"</font>/>
112.1051 - <<font class="function-name">attr</font> <font class="variable-name">name</font>=<font class="string">"originalFileSystem"</font> <font class="variable-name">stringvalue</font>=<font class="string">"SystemFileSystem"</font>/>
112.1052 - </<font class="function-name">file</font>>
112.1053 - </<font class="function-name">folder</font>>
112.1054 - </<font class="function-name">folder</font>>
112.1055 -</<font class="function-name">folder</font>>
112.1056 -</pre>
112.1057 -
112.1058 -<!-- XXX this info should be in a normative section -->
112.1059 -<p>The attribute "originalFileSystem" can be omitted. In this case the search for the
112.1060 -linked file will be done on the Filesystem on which the link resides, which
112.1061 -is wanted for the usages on SystemFileSystem. The link file should have zero length.<BR>
112.1062 -Note that any localized display name
112.1063 -and icon should be set on the original settings file; they will be
112.1064 -picked up automatically by the shadow.</p>
112.1065 -
112.1066 -The older style of linking using the CDATA section is still supported:
112.1067 -
112.1068 -<pre>
112.1069 -<<font class="function-name">folder</font> <font class="variable-name">name</font>=<font class="string">"UI"</font>>
112.1070 - <<font class="function-name">folder</font> <font class="variable-name">name</font>=<font class="string">"Services"</font>>
112.1071 - <<font class="function-name">folder</font> <font class="variable-name">name</font>=<font class="string">"Editing"</font>>
112.1072 - <<font class="function-name">file</font> <font class="variable-name">name</font>=<font class="string">"my-module-config.shadow"</font>>
112.1073 - <![<font class="keyword">CDATA</font>[Services/my-module-Config.settings
112.1074 -SystemFileSystem
112.1075 -]]>
112.1076 - </<font class="function-name">file</font>>
112.1077 - </<font class="function-name">folder</font>>
112.1078 - </<font class="function-name">folder</font>>
112.1079 -</<font class="function-name">folder</font>>
112.1080 -</pre>
112.1081 -
112.1082 -<p>Here the shadow file consists of two lines, the first being the
112.1083 -path to the real settings, the second always being
112.1084 -<samp>SystemFileSystem</samp>.
112.1085 -
112.1086 -<li><p>Links to other kinds of files, such as folders, whether part of
112.1087 -the services lookup area or not. For example:</p>
112.1088 -
112.1089 -<pre>
112.1090 -<<font class="function-name">folder</font> <font class="variable-name">name</font>=<font class="string">"UI"</font>>
112.1091 - <<font class="function-name">folder</font> <font class="variable-name">name</font>=<font class="string">"Services"</font>>
112.1092 - <<font class="function-name">folder</font> <font class="variable-name">name</font>=<font class="string">"IDEConfiguration"</font>>
112.1093 - <<font class="function-name">folder</font> <font class="variable-name">name</font>=<font class="string">"LookAndFeel"</font>>
112.1094 - <<font class="function-name">file</font> <font class="variable-name">name</font>=<font class="string">"my-module-stuff.shadow"</font>>
112.1095 - <<font class="function-name">attr</font> <font class="variable-name">name</font>=<font class="string">"originalFile"</font> <font class="variable-name">stringvalue</font>=<font class="string">"Stuff"</font>/>
112.1096 - </<font class="function-name">file</font>>
112.1097 - </<font class="function-name">folder</font>>
112.1098 - </<font class="function-name">folder</font>>
112.1099 - </<font class="function-name">folder</font>>
112.1100 -</<font class="function-name">folder</font>>
112.1101 -<<font class="function-name">folder</font> <font class="variable-name">name</font>=<font class="string">"Stuff"</font>>
112.1102 - <<font class="function-name">attr</font> <font class="variable-name">name</font>=<font class="string">"SystemFileSystem.localizingBundle"</font> <font class="variable-name">stringvalue</font>=<font class="string">"my.module.Bundle"</font>/>
112.1103 - <<font class="function-name">attr</font> <font class="variable-name">name</font>=<font class="string">"SystemFileSystem.icon"</font> <font class="variable-name">urlvalue</font>=<font class="string">"nbresloc:/my/module/stuff.gif"</font>/>
112.1104 - <font class="comment"><!-- perhaps some files to display here, perhaps not --></font>
112.1105 -</<font class="function-name">folder</font>>
112.1106 -</pre>
112.1107 -
112.1108 -<p>This defines a folder <samp>Stuff</samp> in the system filesystem
112.1109 -which may be used for some kind of special configuration, and displays
112.1110 -it in options.</p>
112.1111 -
112.1112 -<li><p>Specialized nodes. In some cases you do not wish to display a
112.1113 -particular folder but want to have complete control over the literal
112.1114 -display of the option. In such a case you need only include a
112.1115 -<samp>*.instance</samp> file with an instance of the node (or its
112.1116 -handle, if you prefer), as the node delegate of this object will be (a
112.1117 -clone of) the node you provide. For example:</p>
112.1118 -
112.1119 -<pre>
112.1120 -<<font class="function-name">folder</font> <font class="variable-name">name</font>=<font class="string">"UI"</font>>
112.1121 - <<font class="function-name">folder</font> <font class="variable-name">name</font>=<font class="string">"Services"</font>>
112.1122 - <<font class="function-name">folder</font> <font class="variable-name">name</font>=<font class="string">"Building"</font>>
112.1123 - <font class="comment"><!-- Some subclass of org.openide.nodes.Node: --></font>
112.1124 - <<font class="function-name">file</font> <font class="variable-name">name</font>=<font class="string">"my-module-ConfigurationNode.instance"</font>/>
112.1125 - </<font class="function-name">folder</font>>
112.1126 - </<font class="function-name">folder</font>>
112.1127 -</<font class="function-name">folder</font>>
112.1128 -</pre>
112.1129 -
112.1130 -</ul>
112.1131 -
112.1132 -</div>
112.1133 -
112.1134 -<p>No particular substructure of <samp>UI/Services/</samp> is defined
112.1135 -by the APIs. For optimal UI integration you may wish to examine the
112.1136 -categories used by other modules and try to reuse an existing category
112.1137 -appropriate to your needs.</p>
112.1138 -
112.1139 -<p>In some cases it is necessary to <em>hide</em> a service file, or a
112.1140 -whole folder of services. While you can place files into
112.1141 -<samp>Services/</samp> and simply not make any corresponding mirror in
112.1142 -<samp>UI/Services/</samp>, you may wish to create services or
112.1143 -subfolders inside existing displayable folders (for purposes of
112.1144 -lookup, generally) yet not have them be visible in the UI. In this
112.1145 -case you should mark the file or subfolder with the file attribute
112.1146 -<code>hidden</code> (set to boolean <samp>true</samp>).</p>
112.1147 -
112.1148 -<h4><a name="services-proped">Property editor for services</a></h4>
112.1149 -
112.1150 -<p>If you wish to permit the user to select a service as part of the
112.1151 -Property Sheet (from a node property, or as a
112.1152 -<code>PropertyPanel</code>, providing general GUI embeddability), this
112.1153 -is supported. You should use the property editor assigned to
112.1154 -<code>java.lang.Object</code> (<em>not</em> your desired service
112.1155 -interface). Various hints defined in the Explorer API
112.1156 -permit you to control the result.</p>
112.1157 -
112.1158 -<div class="nonnormative">
112.1159 -
112.1160 -<p>As an example, here is a node property permitting you to ask the
112.1161 -user to select a value of type <code>my.module.Thing</code>, being
112.1162 -some interface or abstract superclass, where some instances are
112.1163 -registered to lookup, conventionally in the
112.1164 -<samp>Services/Things/</samp> folder which the module has provided:</p>
112.1165 -
112.1166 -<pre>
112.1167 -<font class="keyword">public</font> <font class="keyword">abstract</font> <font class="keyword">class</font> <font class="type">ThingProperty</font> <font class="keyword">extends</font> <font class="type">PropertySupport.ReadWrite</font> {
112.1168 - <font class="keyword">protected</font> <font class="type">ThingProperty</font>(<font class="type">String</font> <font class="variable-name">name</font>, <font class="type">String</font> <font class="variable-name">displayName</font>, <font class="type">String</font> <font class="variable-name">shortDescription</font>) <font class="keyword">throws</font> <font class="type">IOException</font> {
112.1169 - <font class="keyword">super</font>(name, Object.<font class="keyword">class</font>, displayName, shortDescription);
112.1170 - setValue(<font class="string">"superClass"</font>, Thing.<font class="keyword">class</font>); <font class="comment">// NOI18N
112.1171 -</font> setValue(<font class="string">"nullValue"</font>, NbBundle.getMessage(ThingProperty.<font class="keyword">class</font>, <font class="string">"LBL_no_thing"</font>)); <font class="comment">// NOI18N
112.1172 -</font> <font class="type">DataFolder</font> <font class="variable-name">thingsFolder</font> = DataFolder.create(
112.1173 - DataFolder.findFolder(Repository.getDefault().getDefaultFileSystem().getRoot()),
112.1174 - <font class="string">"Services/Things"</font> <font class="comment">// NOI18N
112.1175 -</font> );
112.1176 - setValue(<font class="string">"node"</font>, thingsFolder.getNodeDelegate()); <font class="comment">// NOI18N
112.1177 -</font> }
112.1178 - <font class="keyword">public</font> <font class="keyword">final</font> <font class="type">Object</font> <font class="function-name">getValue</font>() {
112.1179 - <font class="keyword">return</font> getThing();
112.1180 - }
112.1181 - <font class="keyword">public</font> <font class="keyword">final</font> <font class="type">void</font> <font class="function-name">setValue</font>(<font class="type">Object</font> <font class="variable-name">o</font>) {
112.1182 - <font class="keyword">if</font> (o != <font class="constant">null</font>) {
112.1183 - <font class="type">Lookup.Template</font> <font class="variable-name">templ</font> = <font class="keyword">new</font> <font class="type">Lookup.Template</font>(Thing.<font class="keyword">class</font>, o, <font class="constant">null</font>);
112.1184 - <font class="type">Iterator</font> <font class="variable-name">it</font> = Lookup.getDefault().lookup(templ).allItems().iterator();
112.1185 - <font class="keyword">if</font> (it.hasNext()) {
112.1186 - setThingID(((<font class="type">Lookup.Item</font>)it.next()).getId());
112.1187 - } <font class="keyword">else</font> {
112.1188 - <font class="comment">// Thing was registered but is not persistable.
112.1189 -</font> setThingID(<font class="constant">null</font>);
112.1190 - }
112.1191 - } <font class="keyword">else</font> {
112.1192 - setThingID(<font class="constant">null</font>);
112.1193 - }
112.1194 - }
112.1195 - <font class="keyword">public</font> <font class="keyword">final</font> <font class="type">boolean</font> <font class="function-name">supportsDefaultValue</font>() {
112.1196 - <font class="keyword">return</font> <font class="constant">true</font>;
112.1197 - }
112.1198 - <font class="keyword">public</font> <font class="keyword">final</font> <font class="type">void</font> <font class="function-name">restoreDefaultValue</font>() {
112.1199 - setValue(<font class="constant">null</font>);
112.1200 - }
112.1201 - <font class="comment">// May be used by code wishing to get the actual Thing (or null):
112.1202 -</font> <font class="keyword">public</font> <font class="keyword">final</font> <font class="type">Thing</font> <font class="function-name">getThing</font>() {
112.1203 - <font class="type">String</font> <font class="variable-name">id</font> = getThingID();
112.1204 - <font class="keyword">if</font> (id != <font class="constant">null</font>) {
112.1205 - <font class="type">Lookup.Template</font> <font class="variable-name">templ</font> = <font class="keyword">new</font> <font class="type">Lookup.Template</font>(Thing.<font class="keyword">class</font>, <font class="constant">null</font>, id);
112.1206 - <font class="type">Iterator</font> <font class="variable-name">it</font> = Lookup.getDefault().lookup(templ).allInstances().iterator();
112.1207 - <font class="keyword">if</font> (it.hasNext()) {
112.1208 - <font class="keyword">return</font> (<font class="type">Thing</font>)it.next();
112.1209 - } <font class="keyword">else</font> {
112.1210 - <font class="comment">// Invalid ID.
112.1211 -</font> <font class="keyword">return</font> <font class="constant">null</font>;
112.1212 - }
112.1213 - } <font class="keyword">else</font> {
112.1214 - <font class="keyword">return</font> <font class="constant">null</font>;
112.1215 - }
112.1216 - }
112.1217 - <font class="comment">// Subclasses implement to actually read/write Thing persistent IDs (or null):
112.1218 -</font> <font class="keyword">protected</font> <font class="keyword">abstract</font> <font class="type">String</font> <font class="function-name">getThingID</font>();
112.1219 - <font class="keyword">protected</font> <font class="keyword">abstract</font> <font class="type">void</font> <font class="function-name">setThingID</font>(<font class="type">String</font> <font class="variable-name">id</font>);
112.1220 -}
112.1221 -</pre>
112.1222 -
112.1223 -<p>A property extending this class would in the current UI display a
112.1224 -pull-down list of all <code>Thing</code> implementations available in
112.1225 -lookup; the custom property editor dialog would display the
112.1226 -<samp>Things</samp> folder with anything contained inside it for the
112.1227 -user to select from, provided it in fact had an instance assignable to
112.1228 -<code>Thing</code>. The special null value is explicitly permitted
112.1229 -here and would be displayed with the label given in the bundle.</p>
112.1230 -
112.1231 -</div>
112.1232 -
112.1233 -
112.1234 -<hr>@FOOTER@
112.1235 -</body>
112.1236 -</html>
113.1 --- a/openide.util/test/unit/src/org/openide/util/LookupUsesRequestProcessorTest.java Wed Jan 27 17:46:23 2010 -0500
113.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
113.3 @@ -1,99 +0,0 @@
113.4 -/*
113.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
113.6 - *
113.7 - * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
113.8 - *
113.9 - * The contents of this file are subject to the terms of either the GNU
113.10 - * General Public License Version 2 only ("GPL") or the Common
113.11 - * Development and Distribution License("CDDL") (collectively, the
113.12 - * "License"). You may not use this file except in compliance with the
113.13 - * License. You can obtain a copy of the License at
113.14 - * http://www.netbeans.org/cddl-gplv2.html
113.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
113.16 - * specific language governing permissions and limitations under the
113.17 - * License. When distributing the software, include this License Header
113.18 - * Notice in each file and include the License file at
113.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
113.20 - * particular file as subject to the "Classpath" exception as provided
113.21 - * by Sun in the GPL Version 2 section of the License file that
113.22 - * accompanied this code. If applicable, add the following below the
113.23 - * License Header, with the fields enclosed by brackets [] replaced by
113.24 - * your own identifying information:
113.25 - * "Portions Copyrighted [year] [name of copyright owner]"
113.26 - *
113.27 - * If you wish your version of this file to be governed by only the CDDL
113.28 - * or only the GPL Version 2, indicate your decision by adding
113.29 - * "[Contributor] elects to include this software in this distribution
113.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
113.31 - * single choice of license, a recipient has the option to distribute
113.32 - * your version of this file under either the CDDL, the GPL Version 2 or
113.33 - * to extend the choice of license to its licensees as provided above.
113.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
113.35 - * Version 2 license, then the option applies only if the new code is
113.36 - * made subject to such option by the copyright holder.
113.37 - *
113.38 - * Contributor(s):
113.39 - *
113.40 - * Portions Copyrighted 2009 Sun Microsystems, Inc.
113.41 - */
113.42 -
113.43 -package org.openide.util;
113.44 -
113.45 -import java.io.IOException;
113.46 -import java.net.URL;
113.47 -import java.util.Collections;
113.48 -import java.util.Enumeration;
113.49 -import org.netbeans.junit.NbTestCase;
113.50 -import org.netbeans.junit.RandomlyFails;
113.51 -import org.openide.util.lookup.Lookups;
113.52 -
113.53 -/**
113.54 - *
113.55 - * @author Jaroslav Tulach <jtulach@netbeans.org>
113.56 - */
113.57 -public class LookupUsesRequestProcessorTest extends NbTestCase
113.58 -implements LookupListener {
113.59 - int cnt;
113.60 -
113.61 - public LookupUsesRequestProcessorTest(String s) {
113.62 - super(s);
113.63 - }
113.64 -
113.65 - @RandomlyFails // NB-Core-Build #3891: Count is now 1 expected:<1> but was:<0>
113.66 - public void testMetaInfLookupDeliversEventsInRPThread() throws InterruptedException {
113.67 - ClassLoader l = new MyCL();
113.68 - Lookup lkp = Lookups.metaInfServices(l);
113.69 - Lookup.Result<Runnable> result = lkp.lookupResult(Runnable.class);
113.70 - result.addLookupListener(this);
113.71 -
113.72 - assertNull("No runnables found", lkp.lookup(Runnable.class));
113.73 - assertNotNull("Thread found", lkp.lookup(Thread.class));
113.74 - assertNotNull("Now runnable found", lkp.lookup(Runnable.class));
113.75 - assertEquals("Count is now 1", 1, cnt);
113.76 - }
113.77 -
113.78 - public void resultChanged(LookupEvent unused) {
113.79 - if (Thread.currentThread().getName().contains("request-processor")) {
113.80 - cnt++;
113.81 - return;
113.82 - }
113.83 - fail("Changes shall be delivered in request processor thread. But was: " + Thread.currentThread().getName());
113.84 - }
113.85 -
113.86 -
113.87 - private static final class MyCL extends ClassLoader {
113.88 -
113.89 - @Override
113.90 - protected Enumeration<URL> findResources(String path) throws IOException {
113.91 - if (path.equals("META-INF/services/java.lang.Thread")) {
113.92 - return Collections.enumeration(
113.93 - Collections.singleton(
113.94 - LookupUsesRequestProcessorTest.class.getResource(LookupUsesRequestProcessorTest.class.getSimpleName() + ".resource")
113.95 - )
113.96 - );
113.97 - }
113.98 - return super.findResources(path);
113.99 - }
113.100 -
113.101 - }
113.102 -}
114.1 --- a/openide.util/test/unit/src/org/openide/util/UtilitiesTest.java Wed Jan 27 17:46:23 2010 -0500
114.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
114.3 @@ -1,660 +0,0 @@
114.4 -/*
114.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
114.6 - *
114.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
114.8 - *
114.9 - * The contents of this file are subject to the terms of either the GNU
114.10 - * General Public License Version 2 only ("GPL") or the Common
114.11 - * Development and Distribution License("CDDL") (collectively, the
114.12 - * "License"). You may not use this file except in compliance with the
114.13 - * License. You can obtain a copy of the License at
114.14 - * http://www.netbeans.org/cddl-gplv2.html
114.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
114.16 - * specific language governing permissions and limitations under the
114.17 - * License. When distributing the software, include this License Header
114.18 - * Notice in each file and include the License file at
114.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
114.20 - * particular file as subject to the "Classpath" exception as provided
114.21 - * by Sun in the GPL Version 2 section of the License file that
114.22 - * accompanied this code. If applicable, add the following below the
114.23 - * License Header, with the fields enclosed by brackets [] replaced by
114.24 - * your own identifying information:
114.25 - * "Portions Copyrighted [year] [name of copyright owner]"
114.26 - *
114.27 - * Contributor(s):
114.28 - *
114.29 - * The Original Software is NetBeans. The Initial Developer of the Original
114.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
114.31 - * Microsystems, Inc. All Rights Reserved.
114.32 - *
114.33 - * If you wish your version of this file to be governed by only the CDDL
114.34 - * or only the GPL Version 2, indicate your decision by adding
114.35 - * "[Contributor] elects to include this software in this distribution
114.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
114.37 - * single choice of license, a recipient has the option to distribute
114.38 - * your version of this file under either the CDDL, the GPL Version 2 or
114.39 - * to extend the choice of license to its licensees as provided above.
114.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
114.41 - * Version 2 license, then the option applies only if the new code is
114.42 - * made subject to such option by the copyright holder.
114.43 - */
114.44 -
114.45 -package org.openide.util;
114.46 -
114.47 -import java.awt.Button;
114.48 -import java.awt.Canvas;
114.49 -import java.awt.Checkbox;
114.50 -import java.awt.CheckboxMenuItem;
114.51 -import java.awt.Choice;
114.52 -import java.awt.Component;
114.53 -import java.awt.Cursor;
114.54 -import java.awt.Desktop;
114.55 -import java.awt.Dialog;
114.56 -import java.awt.Dialog.ModalExclusionType;
114.57 -import java.awt.Dialog.ModalityType;
114.58 -import java.awt.Dimension;
114.59 -import java.awt.EventQueue;
114.60 -import java.awt.FileDialog;
114.61 -import java.awt.Font;
114.62 -import java.awt.FontMetrics;
114.63 -import java.awt.Frame;
114.64 -import java.awt.HeadlessException;
114.65 -import java.awt.Image;
114.66 -import java.awt.Label;
114.67 -import java.awt.Menu;
114.68 -import java.awt.MenuBar;
114.69 -import java.awt.MenuItem;
114.70 -import java.awt.Panel;
114.71 -import java.awt.Point;
114.72 -import java.awt.PopupMenu;
114.73 -import java.awt.PrintJob;
114.74 -import java.awt.ScrollPane;
114.75 -import java.awt.Scrollbar;
114.76 -import java.awt.TextArea;
114.77 -import java.awt.TextField;
114.78 -import java.awt.Toolkit;
114.79 -import java.awt.Window;
114.80 -import java.awt.datatransfer.Clipboard;
114.81 -import java.awt.dnd.DragGestureEvent;
114.82 -import java.awt.dnd.InvalidDnDOperationException;
114.83 -import java.awt.dnd.peer.DragSourceContextPeer;
114.84 -import java.awt.event.ActionEvent;
114.85 -import java.awt.event.ActionListener;
114.86 -import java.awt.event.KeyEvent;
114.87 -import java.awt.im.InputMethodHighlight;
114.88 -import java.awt.image.BufferedImage;
114.89 -import java.awt.image.ColorModel;
114.90 -import java.awt.image.ImageObserver;
114.91 -import java.awt.image.ImageProducer;
114.92 -import java.awt.peer.ButtonPeer;
114.93 -import java.awt.peer.CanvasPeer;
114.94 -import java.awt.peer.CheckboxMenuItemPeer;
114.95 -import java.awt.peer.CheckboxPeer;
114.96 -import java.awt.peer.ChoicePeer;
114.97 -import java.awt.peer.DesktopPeer;
114.98 -import java.awt.peer.DialogPeer;
114.99 -import java.awt.peer.FileDialogPeer;
114.100 -import java.awt.peer.FontPeer;
114.101 -import java.awt.peer.FramePeer;
114.102 -import java.awt.peer.LabelPeer;
114.103 -import java.awt.peer.ListPeer;
114.104 -import java.awt.peer.MenuBarPeer;
114.105 -import java.awt.peer.MenuItemPeer;
114.106 -import java.awt.peer.MenuPeer;
114.107 -import java.awt.peer.PanelPeer;
114.108 -import java.awt.peer.PopupMenuPeer;
114.109 -import java.awt.peer.ScrollPanePeer;
114.110 -import java.awt.peer.ScrollbarPeer;
114.111 -import java.awt.peer.TextAreaPeer;
114.112 -import java.awt.peer.TextFieldPeer;
114.113 -import java.awt.peer.WindowPeer;
114.114 -import java.io.File;
114.115 -import java.net.URL;
114.116 -import java.util.ArrayList;
114.117 -import java.util.Arrays;
114.118 -import java.util.List;
114.119 -import java.util.Locale;
114.120 -import java.util.Map;
114.121 -import java.util.Properties;
114.122 -import java.util.concurrent.Semaphore;
114.123 -import javax.swing.AbstractAction;
114.124 -import javax.swing.AbstractButton;
114.125 -import javax.swing.Action;
114.126 -import javax.swing.JButton;
114.127 -import javax.swing.JMenuItem;
114.128 -import javax.swing.JPopupMenu;
114.129 -import javax.swing.JSeparator;
114.130 -import javax.swing.KeyStroke;
114.131 -import junit.framework.Assert;
114.132 -import org.netbeans.junit.MockServices;
114.133 -import org.netbeans.junit.NbTestCase;
114.134 -import org.openide.util.actions.Presenter;
114.135 -import org.openide.util.lookup.AbstractLookup;
114.136 -import org.openide.util.lookup.InstanceContent;
114.137 -import org.openide.util.lookup.Lookups;
114.138 -import org.openide.util.lookup.implspi.NamedServicesProvider;
114.139 -import org.openide.util.actions.ActionPresenterProvider;
114.140 -import org.openide.util.test.MockLookup;
114.141 -
114.142 -/**
114.143 - * @author Jiri Rechtacek et al.
114.144 - */
114.145 -public class UtilitiesTest extends NbTestCase {
114.146 -
114.147 - public UtilitiesTest (String testName) {
114.148 - super (testName);
114.149 - }
114.150 -
114.151 - private String originalOsName;
114.152 -
114.153 - @Override
114.154 - protected void setUp() throws Exception {
114.155 - super.setUp();
114.156 - Utilities.resetOperatingSystem ();
114.157 - originalOsName = System.getProperty("os.name");
114.158 - }
114.159 -
114.160 - @Override
114.161 - protected void tearDown() throws Exception {
114.162 - System.setProperty("os.name", originalOsName);
114.163 - super.tearDown();
114.164 - }
114.165 -
114.166 - public void testGetOperatingSystemWinNT () {
114.167 - System.setProperty ("os.name", "Windows NT");
114.168 - //assertEquals ("System.getProperty (os.name) returns Windows NT", "Windows NT", System.getProperty ("os.name"));
114.169 - assertEquals ("Windows NT recognized as OS_WINNT", Utilities.OS_WINNT, Utilities.getOperatingSystem ());
114.170 - }
114.171 -
114.172 - public void testGetOperatingSystemFreebsd () {
114.173 - System.setProperty ("os.name", "FreeBSD");
114.174 - assertEquals ("System.getProperty (os.name) returns FreeBSD", "FreeBSD", System.getProperty ("os.name"));
114.175 - assertEquals ("System.getProperty (os.name) returns freebsd", "freebsd", System.getProperty ("os.name").toLowerCase (Locale.US));
114.176 - assertEquals ("FreeBSD recognized as OS_FREEBSD", Utilities.OS_FREEBSD, Utilities.getOperatingSystem ());
114.177 - }
114.178 -
114.179 - public void testGetOperatingSystemFreeBSDLowerCase () {
114.180 - System.setProperty ("os.name", "freebsd");
114.181 - assertEquals ("FreeBSD recognized as OS_FREEBSD", Utilities.OS_FREEBSD, Utilities.getOperatingSystem ());
114.182 - }
114.183 -
114.184 - public void testGetUnknownOperatingSystem () {
114.185 - System.setProperty ("os.name", "Unknown");
114.186 - if (File.pathSeparatorChar == ':') {
114.187 - assertTrue("Unknown os.name should be recognized as Unix.", Utilities.isUnix());
114.188 - } else {
114.189 - assertEquals("Unknown os.name not OS_OTHER.", Utilities.OS_OTHER, Utilities.getOperatingSystem());
114.190 - }
114.191 - }
114.192 -
114.193 - public void testWhatIsWinXP () {
114.194 - System.setProperty ("os.name", "Windows XP");
114.195 - assertTrue ("Windows XP isWindows", Utilities.isWindows ());
114.196 - assertFalse ("Windows XP not isUnix", Utilities.isUnix ());
114.197 - }
114.198 -
114.199 - public void testWhatIsLinux () {
114.200 - System.setProperty ("os.name", "Linux");
114.201 - assertFalse ("Linux not isWindows", Utilities.isWindows ());
114.202 - assertTrue ("Linux isUnix", Utilities.isUnix ());
114.203 - }
114.204 -
114.205 - public void testWhatIsMac () {
114.206 - System.setProperty ("os.name", "Mac OS X");
114.207 - assertFalse ("Mac not isWindows", Utilities.isWindows ());
114.208 - assertTrue ("Mac isMac", Utilities.isMac ());
114.209 - }
114.210 -
114.211 - public void testWhatIsFreeBSD () {
114.212 - System.setProperty ("os.name", "freebsd");
114.213 - assertFalse ("freebsd is not isWindows", Utilities.isWindows ());
114.214 - assertTrue ("freebsd isUnix", Utilities.isUnix ());
114.215 - }
114.216 -
114.217 - public void testCustomCursorNotSupported() {
114.218 - NoCustomCursorToolkit toolkit = new NoCustomCursorToolkit();
114.219 - CustomToolkitComponent c = new CustomToolkitComponent( toolkit );
114.220 - Image icon = new BufferedImage( 16, 16, BufferedImage.TYPE_BYTE_BINARY );
114.221 - Cursor cursor = Utilities.createCustomCursor( c, icon, "junittest" );
114.222 - assertTrue( "fallback to wait cursor", Cursor.getPredefinedCursor( Cursor.WAIT_CURSOR ).equals( cursor ) );
114.223 - assertTrue( "getBestCursorSize was called", toolkit.getBestCursorSizeCalled );
114.224 - assertFalse( "no custom cursor created", toolkit.createCustomCursorCalled );
114.225 - }
114.226 -
114.227 - public void testKeyConversions() throws Exception {
114.228 - assertEquals("CS-F1", Utilities.keyToString(KeyStroke.getKeyStroke(KeyEvent.VK_F1, KeyEvent.CTRL_MASK | KeyEvent.SHIFT_MASK)));
114.229 - assertEquals(KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, KeyEvent.ALT_MASK), Utilities.stringToKey("A-EQUALS"));
114.230 - // XXX stringToKeys, Mac support, various more exotic conditions...
114.231 - }
114.232 -
114.233 - public void testKeyConversionsPortable() throws Exception {
114.234 - if (Utilities.isMac()) {
114.235 - assertEquals("SD-D", Utilities.keyToString(KeyStroke.getKeyStroke(KeyEvent.VK_D, KeyEvent.SHIFT_MASK | KeyEvent.META_MASK), true));
114.236 - assertEquals("SO-D", Utilities.keyToString(KeyStroke.getKeyStroke(KeyEvent.VK_D, KeyEvent.SHIFT_MASK | KeyEvent.CTRL_MASK), true));
114.237 - assertEquals("A-RIGHT", Utilities.keyToString(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, KeyEvent.ALT_MASK), true));
114.238 - } else {
114.239 - assertEquals("SD-D", Utilities.keyToString(KeyStroke.getKeyStroke(KeyEvent.VK_D, KeyEvent.SHIFT_MASK | KeyEvent.CTRL_MASK), true));
114.240 - assertEquals("O-RIGHT", Utilities.keyToString(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, KeyEvent.ALT_MASK), true));
114.241 - }
114.242 - }
114.243 -
114.244 - public void testSpecialKeyworksOn14AsWell15 () throws Exception {
114.245 - KeyStroke ks = Utilities.stringToKey("C-CONTEXT_MENU");
114.246 - assertNotNull ("key stroke created", ks);
114.247 - KeyStroke alt = KeyStroke.getKeyStroke(ks.getKeyCode(), KeyEvent.ALT_MASK);
114.248 - String s = Utilities.keyToString(alt);
114.249 - assertEquals ("Correctly converted", "A-CONTEXT_MENU", s);
114.250 - }
114.251 -
114.252 - public void testSpecialKeyworksOn14AsWell15WithoutModificators () throws Exception {
114.253 - KeyStroke ks = Utilities.stringToKey("CONTEXT_MENU");
114.254 - assertNotNull ("key stroke created", ks);
114.255 - String s = Utilities.keyToString(ks);
114.256 - assertEquals ("Correctly converted", "CONTEXT_MENU", s);
114.257 - }
114.258 -
114.259 - public void testActionsToPopupWithLookup() throws Exception {
114.260 - MockServices.setServices(AwtBridgeImpl.class);
114.261 - final List<String> commands = new ArrayList<String>();
114.262 - class BasicAction extends AbstractAction {
114.263 - public BasicAction(String name) {
114.264 - super(name);
114.265 - }
114.266 - public void actionPerformed(ActionEvent e) {
114.267 - commands.add((String) getValue(Action.NAME));
114.268 - }
114.269 - }
114.270 - class ContextAction extends BasicAction implements ContextAwareAction {
114.271 - public ContextAction(String name) {
114.272 - super(name);
114.273 - }
114.274 - public Action createContextAwareInstance(final Lookup actionContext) {
114.275 - return new AbstractAction() {
114.276 - public void actionPerformed(ActionEvent e) {
114.277 - commands.add(ContextAction.this.getValue(Action.NAME) + "/" + actionContext.lookup(String.class));
114.278 - }
114.279 - };
114.280 - }
114.281 - }
114.282 - class SpecialMenuAction extends BasicAction implements Presenter.Popup {
114.283 - public SpecialMenuAction(String name) {
114.284 - super(name);
114.285 - }
114.286 - public JMenuItem getPopupPresenter() {
114.287 - JMenuItem item = new JMenuItem((String) getValue(Action.NAME));
114.288 - item.addActionListener(new ActionListener() {
114.289 - public void actionPerformed(ActionEvent e) {
114.290 - commands.add(((String) getValue(Action.NAME)) + "/popup");
114.291 - }
114.292 - });
114.293 - return item;
114.294 - }
114.295 - }
114.296 - Action duplicated = new BasicAction("duplicated");
114.297 - Action[] actions = new Action[] {
114.298 - null,
114.299 - null,
114.300 - new BasicAction("first"),
114.301 - duplicated,
114.302 - null,
114.303 - null,
114.304 - new BasicAction("second"),
114.305 - duplicated,
114.306 - null,
114.307 - new ContextAction("context"),
114.308 - new SpecialMenuAction("presenter"),
114.309 - null,
114.310 - new BasicAction("top"),
114.311 - new BasicAction("HIDDEN"),
114.312 - null,
114.313 - new BasicAction("bottom"),
114.314 - null,
114.315 - null,
114.316 - };
114.317 - Lookup l = Lookups.singleton("thing");
114.318 - JPopupMenu menu = Utilities.actionsToPopup(actions, l);
114.319 - for (Component element : menu.getComponents()) { // including separators
114.320 - if (element instanceof AbstractButton) {
114.321 - ((AbstractButton) element).doClick();
114.322 - } else {
114.323 - commands.add(null);
114.324 - }
114.325 - }
114.326 - String[] expectedCommands = new String[] {
114.327 - // leading separators must be stripped
114.328 - "first",
114.329 - "duplicated",
114.330 - null, // adjacent separators must be collapsed
114.331 - "second",
114.332 - // do not add the same action twice
114.333 - null,
114.334 - "context/thing", // ContextAwareAction was checked for
114.335 - "presenter/popup", // Presenter.Popup was checked for
114.336 - null,
114.337 - "top",
114.338 - // exclude HIDDEN because of AwtBridgeImpl.convertComponents
114.339 - // separator should however remain
114.340 - null,
114.341 - "bottom",
114.342 - // trailing separators must be stripped
114.343 - };
114.344 - assertEquals("correct generated menu", Arrays.asList(expectedCommands), commands);
114.345 - }
114.346 -
114.347 - public void testActionsForPath() throws Exception {
114.348 - MockLookup.setInstances(new NamedServicesProviderImpl());
114.349 - // #156829: ensure that no tree lock is acquired.
114.350 - final Semaphore ready = new Semaphore(0);
114.351 - final Semaphore done = new Semaphore(0);
114.352 - EventQueue.invokeLater(new Runnable() {
114.353 - public void run() {
114.354 - synchronized (new JSeparator().getTreeLock()) {
114.355 - ready.release();
114.356 - try {
114.357 - done.acquire();
114.358 - } catch (InterruptedException ex) {
114.359 - Exceptions.printStackTrace(ex);
114.360 - }
114.361 - }
114.362 - }
114.363 - });
114.364 - ready.acquire();
114.365 - try {
114.366 - assertEquals("[hello, null, there]", Utilities.actionsForPath("stuff").toString());
114.367 - } finally {
114.368 - done.release();
114.369 - }
114.370 - }
114.371 -
114.372 - private static class CustomToolkitComponent extends Component {
114.373 - private Toolkit customToolkit;
114.374 -
114.375 - public CustomToolkitComponent( Toolkit t ) {
114.376 - this.customToolkit = t;
114.377 - }
114.378 -
114.379 - public Toolkit getToolkit() {
114.380 - return customToolkit;
114.381 - }
114.382 - }
114.383 -
114.384 - private static class NoCustomCursorToolkit extends Toolkit {
114.385 - public FontMetrics getFontMetrics(Font font) {
114.386 - return Toolkit.getDefaultToolkit().getFontMetrics( font );
114.387 - }
114.388 -
114.389 - protected TextFieldPeer createTextField(TextField target) throws HeadlessException {
114.390 - throw new IllegalStateException("Method not implemented");
114.391 - }
114.392 -
114.393 - protected ListPeer createList(java.awt.List target) throws HeadlessException {
114.394 - throw new IllegalStateException("Method not implemented");
114.395 - }
114.396 -
114.397 - protected MenuBarPeer createMenuBar(MenuBar target) throws HeadlessException {
114.398 - throw new IllegalStateException("Method not implemented");
114.399 - }
114.400 -
114.401 - public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException {
114.402 - return Toolkit.getDefaultToolkit().createDragSourceContextPeer( dge );
114.403 - }
114.404 -
114.405 - public boolean prepareImage(Image image, int width, int height, ImageObserver observer) {
114.406 - return Toolkit.getDefaultToolkit().prepareImage( image, width, height, observer );
114.407 - }
114.408 -
114.409 - public int checkImage(Image image, int width, int height, ImageObserver observer) {
114.410 - return Toolkit.getDefaultToolkit().checkImage( image, width, height, observer );
114.411 - }
114.412 -
114.413 - protected PopupMenuPeer createPopupMenu(PopupMenu target) throws HeadlessException {
114.414 - throw new IllegalStateException("Method not implemented");
114.415 - }
114.416 -
114.417 - public PrintJob getPrintJob(Frame frame, String jobtitle, Properties props) {
114.418 - return Toolkit.getDefaultToolkit().getPrintJob( frame, jobtitle, props );
114.419 - }
114.420 -
114.421 - protected ButtonPeer createButton(Button target) throws HeadlessException {
114.422 - throw new IllegalStateException("Method not implemented");
114.423 - }
114.424 -
114.425 - public Image createImage(ImageProducer producer) {
114.426 - return Toolkit.getDefaultToolkit().createImage( producer );
114.427 - }
114.428 -
114.429 - protected CanvasPeer createCanvas(Canvas target) {
114.430 - throw new IllegalStateException("Method not implemented");
114.431 - }
114.432 -
114.433 - protected ScrollbarPeer createScrollbar(Scrollbar target) throws HeadlessException {
114.434 - throw new IllegalStateException("Method not implemented");
114.435 - }
114.436 -
114.437 - public Image getImage(String filename) {
114.438 - return Toolkit.getDefaultToolkit().getImage( filename );
114.439 - }
114.440 -
114.441 - public Image createImage(String filename) {
114.442 - return Toolkit.getDefaultToolkit().createImage( filename );
114.443 - }
114.444 -
114.445 - protected MenuPeer createMenu(Menu target) throws HeadlessException {
114.446 - throw new IllegalStateException("Method not implemented");
114.447 - }
114.448 -
114.449 - protected MenuItemPeer createMenuItem(MenuItem target) throws HeadlessException {
114.450 - throw new IllegalStateException("Method not implemented");
114.451 - }
114.452 -
114.453 - public Map mapInputMethodHighlight(InputMethodHighlight highlight) throws HeadlessException {
114.454 - return Toolkit.getDefaultToolkit().mapInputMethodHighlight( highlight );
114.455 - }
114.456 -
114.457 - public Image createImage(byte[] imagedata, int imageoffset, int imagelength) {
114.458 - return Toolkit.getDefaultToolkit().createImage( imagedata, imageoffset, imagelength );
114.459 - }
114.460 -
114.461 - public Image getImage(URL url) {
114.462 - return Toolkit.getDefaultToolkit().getImage( url );
114.463 - }
114.464 -
114.465 - protected CheckboxPeer createCheckbox(Checkbox target) throws HeadlessException {
114.466 - throw new IllegalStateException("Method not implemented");
114.467 - }
114.468 -
114.469 - public Image createImage(URL url) {
114.470 - return Toolkit.getDefaultToolkit().createImage( url );
114.471 - }
114.472 -
114.473 - protected TextAreaPeer createTextArea(TextArea target) throws HeadlessException {
114.474 - throw new IllegalStateException("Method not implemented");
114.475 - }
114.476 -
114.477 - protected FileDialogPeer createFileDialog(FileDialog target) throws HeadlessException {
114.478 - throw new IllegalStateException("Method not implemented");
114.479 - }
114.480 -
114.481 - protected ScrollPanePeer createScrollPane(ScrollPane target) throws HeadlessException {
114.482 - throw new IllegalStateException("Method not implemented");
114.483 - }
114.484 -
114.485 - protected DialogPeer createDialog(Dialog target) throws HeadlessException {
114.486 - throw new IllegalStateException("Method not implemented");
114.487 - }
114.488 -
114.489 - protected PanelPeer createPanel(Panel target) {
114.490 - throw new IllegalStateException("Method not implemented");
114.491 - }
114.492 -
114.493 - protected ChoicePeer createChoice(Choice target) throws HeadlessException {
114.494 - throw new IllegalStateException("Method not implemented");
114.495 - }
114.496 -
114.497 - protected FramePeer createFrame(Frame target) throws HeadlessException {
114.498 - throw new IllegalStateException("Method not implemented");
114.499 - }
114.500 -
114.501 - protected LabelPeer createLabel(Label target) throws HeadlessException {
114.502 - throw new IllegalStateException("Method not implemented");
114.503 - }
114.504 -
114.505 - protected FontPeer getFontPeer(String name, int style) {
114.506 - throw new IllegalStateException("Method not implemented");
114.507 - }
114.508 -
114.509 - protected CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem target) throws HeadlessException {
114.510 - throw new IllegalStateException("Method not implemented");
114.511 - }
114.512 -
114.513 - protected WindowPeer createWindow(Window target) throws HeadlessException {
114.514 - throw new IllegalStateException("Method not implemented");
114.515 - }
114.516 -
114.517 - public void sync() {
114.518 - Toolkit.getDefaultToolkit().sync();
114.519 - }
114.520 -
114.521 - protected EventQueue getSystemEventQueueImpl() {
114.522 - return Toolkit.getDefaultToolkit().getSystemEventQueue();
114.523 - }
114.524 -
114.525 - public Clipboard getSystemClipboard() throws HeadlessException {
114.526 - return Toolkit.getDefaultToolkit().getSystemClipboard();
114.527 - }
114.528 -
114.529 - public Dimension getScreenSize() throws HeadlessException {
114.530 - return Toolkit.getDefaultToolkit().getScreenSize();
114.531 - }
114.532 -
114.533 - public int getScreenResolution() throws HeadlessException {
114.534 - return Toolkit.getDefaultToolkit().getScreenResolution();
114.535 - }
114.536 -
114.537 - public String[] getFontList() {
114.538 - return Toolkit.getDefaultToolkit().getFontList();
114.539 - }
114.540 -
114.541 - public ColorModel getColorModel() throws HeadlessException {
114.542 - return Toolkit.getDefaultToolkit().getColorModel();
114.543 - }
114.544 -
114.545 - public void beep() {
114.546 - Toolkit.getDefaultToolkit().beep();
114.547 - }
114.548 -
114.549 - boolean createCustomCursorCalled = false;
114.550 - public Cursor createCustomCursor(Image cursor, Point hotSpot, String name) throws IndexOutOfBoundsException, HeadlessException {
114.551 -
114.552 - createCustomCursorCalled = true;
114.553 - return Toolkit.getDefaultToolkit().createCustomCursor(cursor, hotSpot, name);
114.554 - }
114.555 -
114.556 - boolean getBestCursorSizeCalled = false;
114.557 - public Dimension getBestCursorSize(int preferredWidth, int preferredHeight) throws HeadlessException {
114.558 - getBestCursorSizeCalled = true;
114.559 - return new Dimension(0,0);
114.560 - }
114.561 -
114.562 - @Override
114.563 - protected DesktopPeer createDesktopPeer(Desktop target) throws HeadlessException {
114.564 - throw new UnsupportedOperationException("Not supported yet.");
114.565 - }
114.566 -
114.567 - @Override
114.568 - public boolean isModalityTypeSupported(ModalityType modalityType) {
114.569 - throw new UnsupportedOperationException("Not supported yet.");
114.570 - }
114.571 -
114.572 - @Override
114.573 - public boolean isModalExclusionTypeSupported(ModalExclusionType modalExclusionType) {
114.574 - throw new UnsupportedOperationException("Not supported yet.");
114.575 - }
114.576 - }
114.577 -
114.578 - public static final class AwtBridgeImpl extends ActionPresenterProvider {
114.579 - public JPopupMenu createEmptyPopup() {
114.580 - return new JPopupMenu();
114.581 - }
114.582 - public JMenuItem createMenuPresenter(Action action) {
114.583 - return new JMenuItem(action);
114.584 - }
114.585 - public JMenuItem createPopupPresenter(Action action) {
114.586 - return new JMenuItem(action);
114.587 - }
114.588 - public Component createToolbarPresenter(Action action) {
114.589 - return new JButton(action);
114.590 - }
114.591 - public Component[] convertComponents(Component comp) {
114.592 - if (comp instanceof JMenuItem && "HIDDEN".equals(((JMenuItem) comp).getText())) {
114.593 - return new Component[0];
114.594 - } else {
114.595 - return new Component[] {comp};
114.596 - }
114.597 - }
114.598 - }
114.599 -
114.600 - private class NamedServicesProviderImpl extends NamedServicesProvider {
114.601 -
114.602 - public NamedServicesProviderImpl() {
114.603 - }
114.604 -
114.605 - public Lookup create(String path) {
114.606 - if (!path.equals("stuff/")) {
114.607 - return Lookup.EMPTY;
114.608 - }
114.609 - InstanceContent content = new InstanceContent();
114.610 - InstanceContent.Convertor<String, Action> actionConvertor = new InstanceContent.Convertor<String, Action>() {
114.611 -
114.612 - public Action convert(final String obj) {
114.613 - return new AbstractAction() {
114.614 -
114.615 - public void actionPerformed(ActionEvent e) {
114.616 - }
114.617 -
114.618 - @Override
114.619 - public String toString() {
114.620 - return obj;
114.621 - }
114.622 - };
114.623 - }
114.624 -
114.625 - public Class<? extends Action> type(String obj) {
114.626 - return AbstractAction.class;
114.627 - }
114.628 -
114.629 - public String id(String obj) {
114.630 - return obj;
114.631 - }
114.632 -
114.633 - public String displayName(String obj) {
114.634 - return id(obj);
114.635 - }
114.636 - };
114.637 - InstanceContent.Convertor<Boolean, JSeparator> separatorConvertor = new InstanceContent.Convertor<Boolean, JSeparator>() {
114.638 -
114.639 - public JSeparator convert(Boolean obj) {
114.640 - Assert.fail("should not be creating the JSeparator yet");
114.641 - return new JSeparator();
114.642 - }
114.643 -
114.644 - public Class<? extends JSeparator> type(Boolean obj) {
114.645 - return JSeparator.class;
114.646 - }
114.647 -
114.648 - public String id(Boolean obj) {
114.649 - return "sep";
114.650 - }
114.651 -
114.652 - public String displayName(Boolean obj) {
114.653 - return id(obj);
114.654 - }
114.655 - };
114.656 - content.add("hello", actionConvertor);
114.657 - content.add(true, separatorConvertor);
114.658 - content.add("there", actionConvertor);
114.659 - return new AbstractLookup(content);
114.660 - }
114.661 - }
114.662 -
114.663 -}
115.1 --- a/pom.xml Wed Jan 27 17:46:23 2010 -0500
115.2 +++ b/pom.xml Wed Feb 03 00:04:30 2010 +0100
115.3 @@ -32,7 +32,6 @@
115.4 <url>http://apidesign.org</url>
115.5 </organization>
115.6 <modules>
115.7 - <module>lookup</module>
115.8 <module>spring.lookup</module>
115.9 <module>anagramdemo</module>
115.10 </modules>
116.1 --- a/spring.lookup/pom.xml Wed Jan 27 17:46:23 2010 -0500
116.2 +++ b/spring.lookup/pom.xml Wed Feb 03 00:04:30 2010 +0100
116.3 @@ -50,20 +50,15 @@
116.4 </build>
116.5 <dependencies>
116.6 <dependency>
116.7 - <groupId>org.apidesign</groupId>
116.8 - <artifactId>lookup</artifactId>
116.9 - <version>7.22.0</version>
116.10 - </dependency>
116.11 - <dependency>
116.12 <groupId>org.netbeans.api</groupId>
116.13 <artifactId>org-netbeans-modules-nbjunit</artifactId>
116.14 - <version>RELEASE65</version>
116.15 + <version>RELEASE68</version>
116.16 <scope>test</scope>
116.17 </dependency>
116.18 <dependency>
116.19 <groupId>org.netbeans.modules</groupId>
116.20 <artifactId>org-netbeans-insane</artifactId>
116.21 - <version>RELEASE65</version>
116.22 + <version>RELEASE68</version>
116.23 <scope>test</scope>
116.24 </dependency>
116.25 <dependency>
116.26 @@ -81,6 +76,11 @@
116.27 <artifactId>spring-context</artifactId>
116.28 <version>2.5.6</version>
116.29 </dependency>
116.30 + <dependency>
116.31 + <groupId>org.netbeans.api</groupId>
116.32 + <artifactId>org-openide-util</artifactId>
116.33 + <version>RELEASE68</version>
116.34 + </dependency>
116.35 </dependencies>
116.36 <description>Provides mapping between Lookup library,
116.37 so it is directly usable with Spring Framework's