diff -r d95de723723c core.startup/apichanges.xml --- a/core.startup/apichanges.xml Sat Nov 03 16:15:52 2012 +0100 +++ b/core.startup/apichanges.xml Mon Nov 05 11:49:27 2012 +0100 @@ -56,6 +56,22 @@ + + + getDefault + + + + + +

+ Method shutDownAsync to allow asynchronous tasks to + accessp EDT. Also in ModuleInstaller and + ModuleManager. +

+
+ +
getDefault diff -r d95de723723c core.startup/manifest.mf --- a/core.startup/manifest.mf Sat Nov 03 16:15:52 2012 +0100 +++ b/core.startup/manifest.mf Mon Nov 05 11:49:27 2012 +0100 @@ -3,5 +3,5 @@ OpenIDE-Module-Localizing-Bundle: org/netbeans/core/startup/Bundle.properties OpenIDE-Module-Layer: org/netbeans/core/startup/layer.xml OpenIDE-Module-Provides: org.openide.modules.InstalledFileLocator -OpenIDE-Module-Specification-Version: 1.43 +OpenIDE-Module-Specification-Version: 1.44 diff -r d95de723723c core.startup/nbproject/project.xml --- a/core.startup/nbproject/project.xml Sat Nov 03 16:15:52 2012 +0100 +++ b/core.startup/nbproject/project.xml Mon Nov 05 11:49:27 2012 +0100 @@ -55,7 +55,7 @@ 1 - 2.51 + 2.56 diff -r d95de723723c core.startup/src/org/netbeans/core/startup/ModuleSystem.java --- a/core.startup/src/org/netbeans/core/startup/ModuleSystem.java Sat Nov 03 16:15:52 2012 +0100 +++ b/core.startup/src/org/netbeans/core/startup/ModuleSystem.java Mon Nov 05 11:49:27 2012 +0100 @@ -57,6 +57,8 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; import java.util.jar.Attributes; import java.util.jar.Manifest; import java.util.logging.Level; @@ -71,6 +73,7 @@ import org.openide.filesystems.FileSystem; import org.openide.filesystems.FileUtil; import org.openide.modules.ModuleInfo; +import org.openide.modules.OnStop; import org.openide.util.Exceptions; import org.openide.util.Utilities; @@ -309,8 +312,29 @@ * Some of them may refuse. */ public boolean shutDown(final Runnable midHook) { + try { + return shutDownAsync(midHook).get(); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + return false; + } + /** Initializes the shutdown, asks modules to confirm shut down, if some + * of the refure, returns false immediately. If they + * agree, run midHook code and asks modules to really shut down. + * Returns even {@link OnStop} code may not have finished yet. One + * can wait for the returned future till all post clean up hooks are + * finished. + * + * @since 1.44 + * @param midHook the code to run when the shutdown is approved + * @return future for tracking final progress of shutdown and obtaining + * the final value + */ + public Future shutDownAsync(final Runnable midHook) { mgr.mutexPrivileged().enterWriteAccess(); - boolean res; Runnable both = new Runnable() { @Override public void run() { @@ -318,8 +342,9 @@ Stamps.getModulesJARs().shutdown(); } }; + Future res; try { - res = mgr.shutDown(both); + res = mgr.shutDownAsync(both); } finally { mgr.mutexPrivileged().exitWriteAccess(); } diff -r d95de723723c core.startup/src/org/netbeans/core/startup/NbInstaller.java --- a/core.startup/src/org/netbeans/core/startup/NbInstaller.java Sat Nov 03 16:15:52 2012 +0100 +++ b/core.startup/src/org/netbeans/core/startup/NbInstaller.java Mon Nov 05 11:49:27 2012 +0100 @@ -89,10 +89,12 @@ import org.openide.util.SharedClassObject; import org.openide.util.NbBundle; import org.openide.util.Task; +import org.openide.util.TaskListener; import org.openide.util.Utilities; import org.openide.util.lookup.InstanceContent; import org.xml.sax.SAXException; + /** Concrete implementation of the module installation functionality. * This class can pay attention to the details of manifest format, * details of how to install particular sections and layers and so on. @@ -712,10 +714,15 @@ return onStartStop.closing(modules); } + @Override public void close(List modules) { + closeAsync(modules).waitFinished(); + } + + @Override + public Task closeAsync(List modules) { Util.err.fine("close: " + modules); ev.log(Events.CLOSE); - WarmUpSupport.waitFinished(); moduleList.shutDown(); List waitFor = onStartStop.startClose(modules); // [PENDING] this may need to write out changed ModuleInstall externalized @@ -738,11 +745,9 @@ } } } - for (Task t : waitFor) { - t.waitFinished(); - } + waitFor.add(WarmUpSupport.waitTask()); + return new ProxyTask(waitFor); } - private static String cacheCnb; private static Set cacheDeps; @Override diff -r d95de723723c core.startup/src/org/netbeans/core/startup/ProxyTask.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core.startup/src/org/netbeans/core/startup/ProxyTask.java Mon Nov 05 11:49:27 2012 +0100 @@ -0,0 +1,70 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2012 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 2012 Sun Microsystems, Inc. + */ +package org.netbeans.core.startup; + +import java.util.Collection; +import org.openide.util.Task; +import org.openide.util.TaskListener; + +/** + * + * @author Jaroslav Tulach + */ +final class ProxyTask extends Task implements TaskListener { + private int cnt; + + public ProxyTask(Collection waitFor) { + super(null); + this.cnt = waitFor.size(); + notifyRunning(); + for (Task t : waitFor) { + t.addTaskListener(this); + } + } + + @Override + public synchronized void taskFinished(Task task) { + if (--cnt == 0) { + notifyFinished(); + } + } +} diff -r d95de723723c core.startup/src/org/netbeans/core/startup/WarmUpSupport.java --- a/core.startup/src/org/netbeans/core/startup/WarmUpSupport.java Sat Nov 03 16:15:52 2012 +0100 +++ b/core.startup/src/org/netbeans/core/startup/WarmUpSupport.java Mon Nov 05 11:49:27 2012 +0100 @@ -47,7 +47,6 @@ import java.util.Collection; import java.util.logging.Level; import java.util.logging.Logger; -import javax.swing.JDialog; import org.openide.util.Lookup; import org.openide.util.RequestProcessor; import org.openide.util.Task; @@ -77,31 +76,8 @@ return TASK; } - static void waitFinished() { - for (;;) { - try { - if (TASK.waitFinished(5000)) { - return; - } - } catch (InterruptedException ex) { - err.log(Level.WARNING, null, ex); - } - createInnerEDTForAWhile(); - } - } - - private static void createInnerEDTForAWhile() { - final JDialog jd = new JDialog(); - jd.setBounds(100000, 10000, 0, 0); - jd.setModal(true); - RequestProcessor.getDefault().post(new Runnable() { - @Override - public void run() { - jd.setVisible(false); - } - }, 1000); - jd.setVisible(true); - jd.dispose(); + static Task waitTask() { + return TASK; } // ------- diff -r d95de723723c core.startup/test/unit/src/org/netbeans/core/startup/ProxyTaskTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core.startup/test/unit/src/org/netbeans/core/startup/ProxyTaskTest.java Mon Nov 05 11:49:27 2012 +0100 @@ -0,0 +1,90 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2012 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 2012 Sun Microsystems, Inc. + */ +package org.netbeans.core.startup; + +import java.util.ArrayList; +import java.util.List; +import org.junit.Test; +import static org.junit.Assert.*; +import org.openide.util.Task; + +/** + * + * @author Jaroslav Tulach + */ +public class ProxyTaskTest { + + public ProxyTaskTest() { + } + + @Test + public void testSomeMethod() throws Exception { + T t1 = new T(); + T t2 = new T(); + + List l = new ArrayList(); + l.add(t1); + l.add(Task.EMPTY); + l.add(t2); + + Task p = new ProxyTask(l); + + assertFalse("Not finished yet", p.waitFinished(100)); + + t2.done(); + + assertFalse("Still not finished yet", p.waitFinished(100)); + + t1.done(); + p.waitFinished(); + } + + class T extends Task { + public T() { + notifyRunning(); + } + public void done() { + notifyFinished(); + } + } + +} diff -r d95de723723c core.startup/test/unit/src/org/netbeans/core/startup/WarmUpSupportTask.java --- a/core.startup/test/unit/src/org/netbeans/core/startup/WarmUpSupportTask.java Sat Nov 03 16:15:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2012 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 2012 Sun Microsystems, Inc. - */ -package org.netbeans.core.startup; - -import java.awt.EventQueue; -import java.util.concurrent.CountDownLatch; -import java.util.logging.Level; -import java.util.logging.Logger; -import org.openide.util.lookup.ServiceProvider; - -/** - * - * @author Jaroslav Tulach - */ -@ServiceProvider(service=Runnable.class, path="WarmUp") -public class WarmUpSupportTask implements Runnable { - private static final Logger LOG = Logger.getLogger(WarmUpSupportTask.class.getName()); - @Override - public void run() { - if (EventQueue.isDispatchThread()) { - System.setProperty("warmup.success", "in edt"); - System.err.println("setting the property"); - return; - } - - int timeOut = Integer.getInteger("warmup.delay", -1); - if (timeOut > 0) { - LOG.log(Level.INFO, "Will timeout for {0} ms", timeOut); - ClassLoader l = Thread.currentThread().getContextClassLoader(); - try { - Class c = l.loadClass(WarmUpSupportTest.class.getName()); - CountDownLatch in = (CountDownLatch) c.getDeclaredField("in").get(null); - System.setProperty("warmup.success", "notify count down"); - in.countDown(); - - Thread.sleep(timeOut); - - System.setProperty("warmup.success", "before invokeAndWait"); - LOG.info("before invokeAndWait"); - EventQueue.invokeAndWait(this); - LOG.info("after invokeAndWait"); - } catch (Exception ex) { - System.setProperty("warmup.success", "exception " + ex.getMessage()); - throw new IllegalStateException(ex); - } - } - } -} diff -r d95de723723c core.startup/test/unit/src/org/netbeans/core/startup/WarmUpSupportTest.java --- a/core.startup/test/unit/src/org/netbeans/core/startup/WarmUpSupportTest.java Sat Nov 03 16:15:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,100 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2012 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 2012 Sun Microsystems, Inc. - */ -package org.netbeans.core.startup; - -import java.awt.EventQueue; -import java.util.concurrent.CountDownLatch; -import java.util.logging.Level; -import java.util.logging.Logger; -import junit.framework.Test; -import org.netbeans.junit.NbModuleSuite; -import org.netbeans.junit.NbTestCase; -import org.netbeans.junit.NbTestSuite; - -/** - * - * @author Jaroslav Tulach - */ -public class WarmUpSupportTest extends NbTestCase { - private static final Logger LOG = Logger.getLogger(WarmUpSupportTest.class.getName()); - public static final CountDownLatch in = new CountDownLatch(1); - - public WarmUpSupportTest(String s) { - super(s); - } - - @Override - protected int timeOut() { - return 30000; - } - - public static Test suite() { - System.setProperty("warmup.delay", "6000"); - System.setProperty("warmup.success", "not yet"); - NbTestSuite s = new NbTestSuite(); - s.addTest(NbModuleSuite.emptyConfiguration().addTest(WarmUpSupportTest.class, "testEmpty"). - gui(true).suite() - ); - s.addTest(new WarmUpSupportTest("testVerifyProperty")); - return s; - } - - public void testEmpty() throws Exception { - in.await(); - } - - public void testVerifyProperty() throws Exception { - LOG.info("testVerifyProperty"); - for (int i = 0; i < 10 && !"in edt".equals(System.getProperty("warmup.success")); i++) { - LOG.log(Level.INFO, "Jump to EDT, round {0}", i); - EventQueue.invokeAndWait(new Runnable() { - @Override - public void run() { - } - }); - LOG.info("Wait a second"); - Thread.sleep(1000); - LOG.info("Wait is over"); - } - assertEquals("The WarmUpSupportTask was executed", "in edt", System.getProperty("warmup.success")); - } -} diff -r d95de723723c o.n.bootstrap/manifest.mf --- a/o.n.bootstrap/manifest.mf Sat Nov 03 16:15:52 2012 +0100 +++ b/o.n.bootstrap/manifest.mf Mon Nov 05 11:49:27 2012 +0100 @@ -1,6 +1,6 @@ Manifest-Version: 1.0 OpenIDE-Module: org.netbeans.bootstrap/1 -OpenIDE-Module-Specification-Version: 2.55 +OpenIDE-Module-Specification-Version: 2.56 OpenIDE-Module-Localizing-Bundle: org/netbeans/Bundle.properties OpenIDE-Module-Recommends: org.netbeans.NetigsoFramework diff -r d95de723723c o.n.bootstrap/src/org/netbeans/ModuleInstaller.java --- a/o.n.bootstrap/src/org/netbeans/ModuleInstaller.java Sat Nov 03 16:15:52 2012 +0100 +++ b/o.n.bootstrap/src/org/netbeans/ModuleInstaller.java Mon Nov 05 11:49:27 2012 +0100 @@ -51,6 +51,7 @@ import java.util.jar.JarFile; import java.util.jar.Manifest; import org.openide.modules.Dependency; +import org.openide.util.Task; /** Responsible for actually installing the contents of module JARs into the IDE. * While the manager tracks which modules are enabled and their dependencies, @@ -125,6 +126,20 @@ */ public abstract void close(List modules); + /** Initializes closing sequence on given modules. Certain + * operations may remain unfinished and can be carried out in + * parallel. A {@link Task} is returned for callers to wait + * till closing sequence is successfully finished. + * + * @since 2.56 + * @param modules list of modules to close + * @return + */ + public Task closeAsync(List modules) { + close(modules); + return Task.EMPTY; + } + /** Optionally refine the dependencies for a module. * For example, an installer might decide to automatically add a dependency * on a "stock" library module for all client modules meeting some criterion. diff -r d95de723723c o.n.bootstrap/src/org/netbeans/ModuleManager.java --- a/o.n.bootstrap/src/org/netbeans/ModuleManager.java Sat Nov 03 16:15:52 2012 +0100 +++ b/o.n.bootstrap/src/org/netbeans/ModuleManager.java Mon Nov 05 11:49:27 2012 +0100 @@ -75,18 +75,25 @@ import java.util.Set; import java.util.StringTokenizer; import java.util.TreeSet; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.jar.Manifest; import java.util.logging.Level; import org.openide.LifecycleManager; import org.openide.modules.Dependency; import org.openide.modules.ModuleInfo; import org.openide.modules.Modules; +import org.openide.modules.OnStop; import org.openide.modules.Places; import org.openide.modules.SpecificationVersion; import org.openide.util.Enumerations; +import org.openide.util.Exceptions; import org.openide.util.Lookup; import org.openide.util.Mutex; import org.openide.util.NbBundle; +import org.openide.util.Task; import org.openide.util.TopologicalSortException; import org.openide.util.Union2; import org.openide.util.Utilities; @@ -1913,6 +1920,31 @@ * @since org.netbeans.core/1 1.11 */ public boolean shutDown(Runnable midHook) { + try { + return shutDownAsync(midHook).get(); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + return false; + } + /** Partially asynchronous support for shutdown of the system. + * First all modules are asked if they wish to close, in the proper order. + * Assuming they say yes, a hook is run, then they are informed of the close. + * If they did not agree to close, the hook is not run. + * All {@link OnStop} runnables are executed in asynchronously and + * one can wait for the result of such execution by observing the + * returned {@link Future}. + * + * @param midHook a hook to run before closing modules if they agree to close + * @return a future with final result. true if modules agreed the shutdown. + * false when they didn't. + * As soon as the get() method returns true + * the module system is properly shut down. + * @since 2.56 + */ + public Future shutDownAsync(Runnable midHook) { assertWritable(); Set unorderedModules = getEnabledModules(); Map> providersMap = new HashMap>(); @@ -1929,10 +1961,10 @@ Util.err.log(Level.WARNING, null, ex); } Util.err.warning("Cyclic module dependencies, will not shut down cleanly: " + deps); // NOI18N - return true; + return new TaskFuture(true, Task.EMPTY); } if (!TopSecurityManager.officialExit && !installer.closing(sortedModules)) { - return false; + return new TaskFuture(false, Task.EMPTY); } if (midHook != null) { try { @@ -1944,8 +1976,8 @@ } } netigso.shutdownFramework(); - installer.close(sortedModules); - return true; + Task task = installer.closeAsync(sortedModules); + return new TaskFuture(true, task); } static { Runtime.getRuntime().addShutdownHook(new Thread("close modules") { // NOI18N diff -r d95de723723c o.n.bootstrap/src/org/netbeans/TaskFuture.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/o.n.bootstrap/src/org/netbeans/TaskFuture.java Mon Nov 05 11:49:27 2012 +0100 @@ -0,0 +1,92 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2012 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 2012 Sun Microsystems, Inc. + */ +package org.netbeans; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import org.openide.util.Task; + +/** + * + * @author Jaroslav Tulach + */ +final class TaskFuture implements Future { + private final boolean result; + private final Task WAIT; + + public TaskFuture(boolean result, Task WAIT) { + this.result = result; + this.WAIT = WAIT; + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + return false; + } + + @Override + public boolean isCancelled() { + return false; + } + + @Override + public boolean isDone() { + return WAIT.isFinished(); + } + + @Override + public Boolean get() throws InterruptedException, ExecutionException { + WAIT.waitFinished(); + return result; + } + + @Override + public Boolean get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + if (!WAIT.waitFinished(unit.toMillis(timeout))) { + throw new TimeoutException(); + } + return result; + } + +} diff -r d95de723723c o.n.bootstrap/test/unit/src/org/netbeans/TaskFutureTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/o.n.bootstrap/test/unit/src/org/netbeans/TaskFutureTest.java Mon Nov 05 11:49:27 2012 +0100 @@ -0,0 +1,99 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2012 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 2012 Sun Microsystems, Inc. + */ +package org.netbeans; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import org.junit.Test; +import static org.junit.Assert.*; +import org.openide.util.Task; + +/** + * + * @author Jaroslav Tulach + */ +public class TaskFutureTest { + + public TaskFutureTest() { + } + + @Test + public void testTrueEmptyTask() throws Exception { + TaskFuture tf = new TaskFuture(true, Task.EMPTY); + assertTrue("Really true", tf.get()); + } + + @Test + public void testFalseEmptyTask() throws Exception { + TaskFuture tf = new TaskFuture(false, Task.EMPTY); + assertFalse("Really false", tf.get()); + } + + @Test + public void testRealTask() throws Exception { + class T extends Task { + public T() { + notifyRunning(); + } + public void done() { + notifyFinished(); + } + } + + T t = new T(); + assertFalse("Not finished yet", t.isFinished()); + + TaskFuture tf = new TaskFuture(false, t); + + + try { + tf.get(100, TimeUnit.MILLISECONDS); + fail("Should time out"); + } catch (TimeoutException timeoutException) { + // OK + } + t.done(); + + assertFalse("Really false", tf.get()); + } +} diff -r d95de723723c o.n.core/nbproject/project.xml --- a/o.n.core/nbproject/project.xml Sat Nov 03 16:15:52 2012 +0100 +++ b/o.n.core/nbproject/project.xml Mon Nov 05 11:49:27 2012 +0100 @@ -64,7 +64,7 @@ 1 - 1.30 + 1.44 diff -r d95de723723c o.n.core/src/org/netbeans/core/NbLifeExit.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/o.n.core/src/org/netbeans/core/NbLifeExit.java Mon Nov 05 11:49:27 2012 +0100 @@ -0,0 +1,187 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2012 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 2012 Sun Microsystems, Inc. + */ +package org.netbeans.core; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.netbeans.CLIHandler; +import org.netbeans.TopSecurityManager; +import org.netbeans.core.startup.CLIOptions; +import org.netbeans.core.startup.Main; +import org.netbeans.core.startup.layers.SessionManager; +import org.openide.util.Exceptions; +import org.openide.util.Lookup; +import org.openide.util.Mutex; +import org.openide.util.RequestProcessor; +import org.openide.util.Task; + +/** + * + * @author Jaroslav Tulach + */ +final class NbLifeExit implements Runnable { + private static final RequestProcessor RP = new RequestProcessor("Nb Exit"); // NOI18N + + private final int type; + private final int status; + private final Future waitFor; + + NbLifeExit(int type, int status) { + this(type, status, null); + } + + private NbLifeExit(int type, int status, Future waitFor) { + this.type = type; + this.status = status; + this.waitFor = waitFor; + } + + @Override + public void run() { + switch (type) { + case 0: + doExit(status); + break; + case 1: + doStopInfra(status); + break; + case 2: + int s = 3; + try { + if (waitFor.get()) { + s = 4; + } + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + Mutex.EVENT.readAccess(new NbLifeExit(s, status)); + break; + case 3: + case 4: + doApproved(type == 4, status); + break; + case 5: + if (!Boolean.getBoolean("netbeans.close.no.exit")) { // NOI18N + TopSecurityManager.exit(status); + } + break; + default: + throw new IllegalStateException("Type: " + type); // NOI18N + } + } + private static boolean doingExit = false; + + /** + * @return True if the IDE is shutting down. + */ + public static boolean isExiting() { + return doingExit; + } + + private static void doExit(int status) { + if (doingExit) { + return; + } + doingExit = true; + // save all open files + try { + if (System.getProperty("netbeans.close") != null || ExitDialog.showDialog()) { // NOI18N + Future res = Main.getModuleSystem().shutDownAsync(new NbLifeExit(1, status)); + RP.post(new NbLifeExit(2, status, res)); + } + } finally { + doingExit = false; + } + } + + private static void doStopInfra(int status) { + CLIHandler.stopServer(); + final WindowSystem windowSystem = Lookup.getDefault().lookup(WindowSystem.class); + boolean gui = CLIOptions.isGui(); + if (windowSystem != null && gui) { + windowSystem.hide(); + windowSystem.save(); + } + if (Boolean.getBoolean("netbeans.close.when.invisible")) { // NOI18N + // hook to permit perf testing of time to *apparently* shut down + TopSecurityManager.exit(status); + } + } + + private static void doApproved(boolean isApproved, int status) throws ThreadDeath { + if (isApproved) { + try { + try { + NbLoaderPool.store(); + } catch (IOException ioe) { + Logger.getLogger(NbLifecycleManager.class.getName()).log(Level.WARNING, null, ioe); + } + //#46940 -saving just once.. + // // save window system, [PENDING] remove this after the winsys will + // // persist its state automaticaly + // if (windowSystem != null) { + // windowSystem.save(); + // } + SessionManager.getDefault().close(); + } catch (ThreadDeath td) { + throw td; + } catch (Throwable t) { + // Do not let problems here prevent system shutdown. The module + // system is down; the IDE cannot be used further. + Exceptions.printStackTrace(t); + } + // #37231 Someone (e.g. Jemmy) can install its own EventQueue and then + // exit is dispatched through that proprietary queue and it + // can be refused by security check. So, we need to replan + // to RequestProcessor to avoid security problems. + Task exitTask = new Task(new NbLifeExit(5, status)); + RP.post(exitTask); + exitTask.waitFinished(); + } + } + +} // end of ExitActions diff -r d95de723723c o.n.core/src/org/netbeans/core/NbLifecycleManager.java --- a/o.n.core/src/org/netbeans/core/NbLifecycleManager.java Sat Nov 03 16:15:52 2012 +0100 +++ b/o.n.core/src/org/netbeans/core/NbLifecycleManager.java Mon Nov 05 11:49:27 2012 +0100 @@ -48,23 +48,15 @@ import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; -import org.netbeans.CLIHandler; -import org.netbeans.TopSecurityManager; -import org.netbeans.core.startup.CLIOptions; import org.netbeans.core.startup.ModuleLifecycleManager; -import org.netbeans.core.startup.layers.SessionManager; import org.openide.DialogDisplayer; import org.openide.LifecycleManager; import org.openide.NotifyDescriptor; import org.openide.awt.StatusDisplayer; import org.openide.cookies.SaveCookie; import org.openide.loaders.DataObject; -import org.openide.util.Exceptions; -import org.openide.util.Lookup; import org.openide.util.Mutex; import org.openide.util.NbBundle; -import org.openide.util.RequestProcessor; -import org.openide.util.Task; import org.openide.util.lookup.ServiceProvider; /** @@ -73,7 +65,7 @@ */ @ServiceProvider(service=LifecycleManager.class, supersedes="org.netbeans.core.startup.ModuleLifecycleManager") public final class NbLifecycleManager extends LifecycleManager { - + @Override public void saveAll() { ArrayList bad = new ArrayList(); DataObject[] modifs = DataObject.getRegistry().getModified(); @@ -105,115 +97,25 @@ StatusDisplayer.getDefault().setStatusText(NbBundle.getMessage(NbLifecycleManager.class, "MSG_AllSaved")); } + @Override public void exit() { // #37160 So there is avoided potential clash between hiding GUI in AWT // and accessing AWTTreeLock from saving routines (winsys). - Mutex.EVENT.readAccess(DO_EXIT); + exit(0); } + @Override public void exit(int status) { - ExitActions action = new ExitActions(0, status); + NbLifeExit action = new NbLifeExit(0, status); Mutex.EVENT.readAccess(action); } - - private static class ExitActions implements Runnable { - private final int type; - private final int status; - ExitActions(int type) { - this.type = type; - this.status = 0; - } - - ExitActions(int type, int status) { - this.type = type; - this.status = status; - } - - public void run() { - switch (type) { - case 0: - doExit(status); - break; - case 1: - CLIHandler.stopServer(); - final WindowSystem windowSystem = Lookup.getDefault().lookup(WindowSystem.class); - boolean gui = CLIOptions.isGui(); - if (windowSystem != null && gui) { - windowSystem.hide(); - windowSystem.save(); - } - if (Boolean.getBoolean("netbeans.close.when.invisible")) { - // hook to permit perf testing of time to *apparently* shut down - TopSecurityManager.exit(status); - } - break; - case 2: - if (!Boolean.getBoolean("netbeans.close.no.exit")) { // NOI18N - TopSecurityManager.exit(status); - } - break; - default: - throw new IllegalStateException("Type: " + type); // NOI18N - } - } - } // end of ExitActions - - private static boolean doingExit=false; - private static final Runnable DO_EXIT = new ExitActions(0); - - /** - * @return True if the IDE is shutting down. - */ + public static boolean isExiting() { - return doingExit; - } - - private static void doExit(int status) { - if (doingExit) { - return ; - } - doingExit = true; - // save all open files - try { - if ( System.getProperty ("netbeans.close") != null || ExitDialog.showDialog() ) { - if (org.netbeans.core.startup.Main.getModuleSystem().shutDown(new ExitActions(1, status))) { - try { - try { - NbLoaderPool.store(); - } catch (IOException ioe) { - Logger.getLogger(NbLifecycleManager.class.getName()).log(Level.WARNING, null, ioe); - } -//#46940 -saving just once.. -// // save window system, [PENDING] remove this after the winsys will -// // persist its state automaticaly -// if (windowSystem != null) { -// windowSystem.save(); -// } - SessionManager.getDefault().close(); - } catch (ThreadDeath td) { - throw td; - } catch (Throwable t) { - // Do not let problems here prevent system shutdown. The module - // system is down; the IDE cannot be used further. - Exceptions.printStackTrace(t); - } - // #37231 Someone (e.g. Jemmy) can install its own EventQueue and then - // exit is dispatched through that proprietary queue and it - // can be refused by security check. So, we need to replan - // to RequestProcessor to avoid security problems. - Task exitTask = new Task(new ExitActions(2, status)); - RequestProcessor.getDefault().post(exitTask); - exitTask.waitFinished(); - } - } - } finally { - doingExit = false; - } + return NbLifeExit.isExiting(); } @Override public void markForRestart() throws UnsupportedOperationException { new ModuleLifecycleManager().markForRestart(); } - }