--- a/jdk/src/share/classes/sun/awt/AppContext.java Wed Mar 20 11:50:11 2013 -0700
+++ b/jdk/src/share/classes/sun/awt/AppContext.java Thu Mar 21 02:13:49 2013 +0400
@@ -162,7 +162,8 @@
}
/* The main "system" AppContext, used by everything not otherwise
- contained in another AppContext.
+ contained in another AppContext. It is implicitly created for
+ standalone apps only (i.e. not applets)
*/
private static volatile AppContext mainAppContext = null;
@@ -204,25 +205,6 @@
*/
private static final AtomicInteger numAppContexts = new AtomicInteger(0);
- static {
- // On the main Thread, we get the ThreadGroup, make a corresponding
- // AppContext, and instantiate the Java EventQueue. This way, legacy
- // code is unaffected by the move to multiple AppContext ability.
- AccessController.doPrivileged(new PrivilegedAction<Void>() {
- public Void run() {
- ThreadGroup currentThreadGroup =
- Thread.currentThread().getThreadGroup();
- ThreadGroup parentThreadGroup = currentThreadGroup.getParent();
- while (parentThreadGroup != null) {
- // Find the root ThreadGroup to construct our main AppContext
- currentThreadGroup = parentThreadGroup;
- parentThreadGroup = currentThreadGroup.getParent();
- }
- mainAppContext = new AppContext(currentThreadGroup);
- return null;
- }
- });
- }
/*
* The context ClassLoader that was used to create this AppContext.
@@ -266,6 +248,27 @@
private static final ThreadLocal<AppContext> threadAppContext =
new ThreadLocal<AppContext>();
+ private final static void initMainAppContext() {
+ // On the main Thread, we get the ThreadGroup, make a corresponding
+ // AppContext, and instantiate the Java EventQueue. This way, legacy
+ // code is unaffected by the move to multiple AppContext ability.
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
+ ThreadGroup currentThreadGroup =
+ Thread.currentThread().getThreadGroup();
+ ThreadGroup parentThreadGroup = currentThreadGroup.getParent();
+ while (parentThreadGroup != null) {
+ // Find the root ThreadGroup to construct our main AppContext
+ currentThreadGroup = parentThreadGroup;
+ parentThreadGroup = currentThreadGroup.getParent();
+ }
+
+ mainAppContext = SunToolkit.createNewAppContext(currentThreadGroup);
+ return null;
+ }
+ });
+ }
+
/**
* Returns the appropriate AppContext for the caller,
* as determined by its ThreadGroup. If the main "system" AppContext
@@ -278,8 +281,10 @@
* @since 1.2
*/
public final static AppContext getAppContext() {
- if (numAppContexts.get() == 1) // If there's only one system-wide,
- return mainAppContext; // return the main system AppContext.
+ // we are standalone app, return the main app context
+ if (numAppContexts.get() == 1 && mainAppContext != null) {
+ return mainAppContext;
+ }
AppContext appContext = threadAppContext.get();
@@ -293,29 +298,37 @@
// when new AppContext objects are created.
ThreadGroup currentThreadGroup = Thread.currentThread().getThreadGroup();
ThreadGroup threadGroup = currentThreadGroup;
+
+ // Special case: we implicitly create the main app context
+ // if no contexts have been created yet. This covers standalone apps
+ // and excludes applets because by the time applet starts
+ // a number of contexts have already been created by the plugin.
+ if (numAppContexts.get() == 0) {
+ // This check is not necessary, its purpose is to help
+ // Plugin devs to catch all the cases of main AC creation.
+ if (System.getProperty("javaplugin.version") == null &&
+ System.getProperty("javawebstart.version") == null) {
+ initMainAppContext();
+ }
+ }
+
AppContext context = threadGroup2appContext.get(threadGroup);
while (context == null) {
threadGroup = threadGroup.getParent();
if (threadGroup == null) {
- // If we get here, we're running under a ThreadGroup that
- // has no AppContext associated with it. This should never
- // happen, because createNewContext() should be used by the
- // toolkit to create the ThreadGroup that everything runs
- // under.
- throw new RuntimeException("Invalid ThreadGroup");
+ return null;
}
context = threadGroup2appContext.get(threadGroup);
}
+
// In case we did anything in the above while loop, we add
// all the intermediate ThreadGroups to threadGroup2appContext
// so we won't spin again.
for (ThreadGroup tg = currentThreadGroup; tg != threadGroup; tg = tg.getParent()) {
threadGroup2appContext.put(tg, context);
}
+
// Now we're done, so we cache the latest key/value pair.
- // (we do this before checking with any AWTSecurityManager, so if
- // this Thread equates with the main AppContext in the cache, it
- // still will)
threadAppContext.set(context);
return context;
@@ -323,17 +336,18 @@
});
}
- if (appContext == mainAppContext) {
- // Before we return the main "system" AppContext, check to
- // see if there's an AWTSecurityManager installed. If so,
- // allow it to choose the AppContext to return.
- AppContext secAppContext = getExecutionAppContext();
- if (secAppContext != null) {
- appContext = secAppContext; // Return what we're told
- }
- }
+ return appContext;
+ }
- return appContext;
+ /**
+ * Returns true if the specified AppContext is the main AppContext.
+ *
+ * @param ctx the context to compare with the main context
+ * @return true if the specified AppContext is the main AppContext.
+ * @since 1.8
+ */
+ public final static boolean isMainContext(AppContext ctx) {
+ return (ctx != null && ctx == mainAppContext);
}
private final static AppContext getExecutionAppContext() {
@@ -348,16 +362,6 @@
return null;
}
- /**
- * Returns the main ("system") AppContext.
- *
- * @return the main AppContext
- * @since 1.8
- */
- final static AppContext getMainAppContext() {
- return mainAppContext;
- }
-
private long DISPOSAL_TIMEOUT = 5000; // Default to 5-second timeout
// for disposal of all Frames
// (we wait for this time twice,
@@ -810,7 +814,7 @@
return getAppContext().isDisposed();
}
public boolean isMainAppContext() {
- return (numAppContexts.get() == 1);
+ return (numAppContexts.get() == 1 && mainAppContext != null);
}
public Object getContext() {
return getAppContext();