diff -r e7499d50abe0 openide.util.lookup/apichanges.xml --- a/openide.util.lookup/apichanges.xml Tue Oct 14 15:26:47 2014 +0200 +++ b/openide.util.lookup/apichanges.xml Wed Oct 15 17:26:33 2014 +0200 @@ -49,6 +49,35 @@ Lookup API + + + A way to control Lookup.getDefault + + + + + The clients of + Lookup.getDefault() are mostly unaffected by this change, + just they need to be ready for the fact that the return + value of the method may no longer be fixed one, but can mutate + over time. + + +

+ One can use + Lookups.execute(yourLookup, yourRunnable) + to temporarily influence return value from + + Lookup.getDefault(). +

+
+ + +
Easy and robust way to register named services diff -r e7499d50abe0 openide.util.lookup/manifest.mf --- a/openide.util.lookup/manifest.mf Tue Oct 14 15:26:47 2014 +0200 +++ b/openide.util.lookup/manifest.mf Wed Oct 15 17:26:33 2014 +0200 @@ -1,5 +1,5 @@ Manifest-Version: 1.0 OpenIDE-Module: org.openide.util.lookup OpenIDE-Module-Localizing-Bundle: org/openide/util/lookup/Bundle.properties -OpenIDE-Module-Specification-Version: 8.26 +OpenIDE-Module-Specification-Version: 8.30 diff -r e7499d50abe0 openide.util.lookup/src/org/netbeans/modules/openide/util/GlobalLookup.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/openide.util.lookup/src/org/netbeans/modules/openide/util/GlobalLookup.java Wed Oct 15 17:26:33 2014 +0200 @@ -0,0 +1,65 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2014 Sun Microsystems, Inc. + */ +package org.netbeans.modules.openide.util; + +import org.openide.util.Lookup; + +public class GlobalLookup { + private static ThreadLocal CURRENT = new ThreadLocal(); + + private GlobalLookup() { + } + + public static void execute(Lookup defaultLookup, Runnable r) { + Lookup prev = CURRENT.get(); + try { + CURRENT.set(defaultLookup); + r.run(); + } finally { + CURRENT.set(prev); + } + } + + public static Lookup current() { + return CURRENT.get(); + } +} diff -r e7499d50abe0 openide.util.lookup/src/org/openide/util/Lookup.java --- a/openide.util.lookup/src/org/openide/util/Lookup.java Tue Oct 14 15:26:47 2014 +0200 +++ b/openide.util.lookup/src/org/openide/util/Lookup.java Wed Oct 15 17:26:33 2014 +0200 @@ -52,6 +52,7 @@ import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; +import org.netbeans.modules.openide.util.GlobalLookup; import org.openide.util.lookup.Lookups; import org.openide.util.lookup.ProxyLookup; import org.openide.util.lookup.ServiceProvider; @@ -110,6 +111,11 @@ * @see ServiceProvider */ public static synchronized Lookup getDefault() { + Lookup current = GlobalLookup.current(); + if (current != null) { + return current; + } + if (defaultLookup != null) { return defaultLookup; } diff -r e7499d50abe0 openide.util.lookup/src/org/openide/util/lookup/Lookups.java --- a/openide.util.lookup/src/org/openide/util/lookup/Lookups.java Tue Oct 14 15:26:47 2014 +0200 +++ b/openide.util.lookup/src/org/openide/util/lookup/Lookups.java Wed Oct 15 17:26:33 2014 +0200 @@ -45,6 +45,7 @@ package org.openide.util.lookup; import java.util.Arrays; +import org.netbeans.modules.openide.util.GlobalLookup; import org.openide.util.Lookup; import org.openide.util.lookup.implspi.NamedServicesProvider; @@ -279,6 +280,19 @@ public static Lookup.Item lookupItem(T instance, String id) { return new LookupItem(instance, id); } + + /** Temporarily (while the code is running) changes value + * of {@link Lookup#getDefault()} to here-in provided lookup. Useful in a + * multi user environment where different users and their requests should + * be associated with different content of default lookup. + * + * @param defaultLookup the lookup to be come default while code is running + * @param code the code to execute (synchronously) before the method returns + * @since 8.30 + */ + public static void execute(Lookup defaultLookup, Runnable code) { + GlobalLookup.execute(defaultLookup, code); + } private static class LookupItem extends Lookup.Item { private String id; diff -r e7499d50abe0 openide.util.lookup/test/unit/src/org/openide/util/lookup/LookupGetDefaultTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/LookupGetDefaultTest.java Wed Oct 15 17:26:33 2014 +0200 @@ -0,0 +1,70 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2014 Sun Microsystems, Inc. + */ +package org.openide.util.lookup; + +import org.netbeans.junit.NbTestCase; +import org.openide.util.Lookup; + +public class LookupGetDefaultTest extends NbTestCase { + + public LookupGetDefaultTest(String name) { + super(name); + } + + public void testCanChangeDefaultLookup() throws Exception { + Lookup prev = Lookup.getDefault(); + final Lookup my = new AbstractLookup(); + final Thread myThread = Thread.currentThread(); + final boolean[] ok = { false }; + + Lookups.execute(my, new Runnable() { + @Override + public void run() { + assertSame("Default lookup has been changed", my, Lookup.getDefault()); + assertSame("We are being executed in the same thread", myThread, Thread.currentThread()); + ok[0] = true; + } + }); + assertTrue("In my lookup code executed OK", ok[0]); + assertEquals("Current lookup back to normal", prev, Lookup.getDefault()); + } +} diff -r e7499d50abe0 openide.util/apichanges.xml --- a/openide.util/apichanges.xml Tue Oct 14 15:26:47 2014 +0200 +++ b/openide.util/apichanges.xml Wed Oct 15 17:26:33 2014 +0200 @@ -51,6 +51,25 @@ Actions API + + + RequestProcessor tasks remember correct lookup + + + + + +

+ RequestProcessor + is now + Lookups.execute aware and makes sure the executed task + uses the same default lookup as at the time of its + initial creation. +

+
+ + +
Platform dependent sound when invoking a disabled action. diff -r e7499d50abe0 openide.util/manifest.mf --- a/openide.util/manifest.mf Tue Oct 14 15:26:47 2014 +0200 +++ b/openide.util/manifest.mf Wed Oct 15 17:26:33 2014 +0200 @@ -1,5 +1,5 @@ Manifest-Version: 1.0 OpenIDE-Module: org.openide.util OpenIDE-Module-Localizing-Bundle: org/openide/util/Bundle.properties -OpenIDE-Module-Specification-Version: 8.40 +OpenIDE-Module-Specification-Version: 8.41 diff -r e7499d50abe0 openide.util/src/org/openide/util/RequestProcessor.java --- a/openide.util/src/org/openide/util/RequestProcessor.java Tue Oct 14 15:26:47 2014 +0200 +++ b/openide.util/src/org/openide/util/RequestProcessor.java Wed Oct 15 17:26:33 2014 +0200 @@ -79,6 +79,7 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.logging.Level; import java.util.logging.Logger; +import org.openide.util.lookup.Lookups; /** Request processor is {@link Executor} (since version 7.16) capable to * perform asynchronous requests in a dedicated thread pool. @@ -629,7 +630,7 @@ item.enqueued = true; } - Task askForWork(Processor worker, String debug) { + Task askForWork(Processor worker, String debug, Lookup[] lkp) { if (getQueue().isEmpty() || (stopped && !finishAwaitingTasks)) { // no more work in this burst, return him processors.remove(worker); Processor.put(worker, debug); @@ -639,6 +640,7 @@ Item i = getQueue().first(); getQueue().remove(i); Task t = i.getTask(); + lkp[0] = i.current; i.clear(worker); return t; @@ -1728,6 +1730,7 @@ private static int counter; private final RequestProcessor owner; private final int cnt; + final Lookup current; Object action; boolean enqueued; String message; @@ -1738,6 +1741,7 @@ action = task; owner = rp; cnt = counter++; + current = Lookup.getDefault(); } final Task getTask() { @@ -2015,9 +2019,10 @@ // while we have something to do for (;;) { + Lookup[] lkp = new Lookup[1]; // need the same sync as interruptTask synchronized (current.processorLock) { - todo = current.askForWork(this, debug); + todo = current.askForWork(this, debug, lkp); if (todo == null) { break; } @@ -2030,7 +2035,12 @@ em.log(Level.FINE, " Executing {0}", todo); // NOI18N } registerParallel(todo, current); - todo.run(); + if (lkp[0] == null || lkp[0] == Lookup.getDefault()) { + todo.run(); + } else { + Lookups.execute(lkp[0], todo); + } + lkp[0] = null; if (loggable) { em.log(Level.FINE, " Execution finished in {0}", getName()); // NOI18N diff -r e7499d50abe0 openide.util/test/unit/src/org/openide/util/RequestProcessorLookupGetDefaultTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/openide.util/test/unit/src/org/openide/util/RequestProcessorLookupGetDefaultTest.java Wed Oct 15 17:26:33 2014 +0200 @@ -0,0 +1,83 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2014 Sun Microsystems, Inc. + */ +package org.openide.util; + +import java.util.concurrent.TimeUnit; +import org.netbeans.junit.NbTestCase; +import org.openide.util.Lookup; +import org.openide.util.lookup.AbstractLookup; +import org.openide.util.lookup.InstanceContent; +import org.openide.util.lookup.Lookups; + +public class RequestProcessorLookupGetDefaultTest extends NbTestCase { + + public RequestProcessorLookupGetDefaultTest(String name) { + super(name); + } + + public void testChangeOfDefaultLookupAppliedToRPTask() throws Exception { + Lookup prev = Lookup.getDefault(); + final Lookup my = new AbstractLookup(new InstanceContent()); + final Thread myThread = Thread.currentThread(); + final RequestProcessor.Task[] task = { null }; + final boolean[] ok = { false }; + + Lookups.execute(my, new Runnable() { + @Override + public void run() { + assertSame("Default lookup has been changed", my, Lookup.getDefault()); + + if (task[0] == null) { + assertSame("We are being executed in the same thread", myThread, Thread.currentThread()); + // once again in the RP + task[0] = RequestProcessor.getDefault().post(this, 500); + } else { + ok[0] = true; + } + } + }); + assertNotNull("In my lookup code executed OK", task[0]); + assertEquals("Current lookup back to normal", prev, Lookup.getDefault()); + task[0].waitFinished(); + assertTrue("Even RP task had the right lookup", ok[0]); + } +}