Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/ikvm-fork.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjfrijters <jfrijters>2013-08-15 14:09:08 +0400
committerjfrijters <jfrijters>2013-08-15 14:09:08 +0400
commitcc55a61dba5b181032466ab4f845b5a6da6d3996 (patch)
tree8f120137fc423f61460370c24b738e487746dabc /openjdk/sun/awt/AppContext.java
parent76e31c345f8e31f92d579ef5454a9eccb48218ff (diff)
Merged 7u40 AppContext and TimeZone decoupling mechanism.
Diffstat (limited to 'openjdk/sun/awt/AppContext.java')
-rw-r--r--openjdk/sun/awt/AppContext.java214
1 files changed, 150 insertions, 64 deletions
diff --git a/openjdk/sun/awt/AppContext.java b/openjdk/sun/awt/AppContext.java
index be6734e4..23c86c90 100644
--- a/openjdk/sun/awt/AppContext.java
+++ b/openjdk/sun/awt/AppContext.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -46,6 +46,7 @@ import sun.util.logging.PlatformLogger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* The AppContext is a table referenced by ThreadGroup which stores
@@ -129,7 +130,7 @@ import java.util.concurrent.locks.ReentrantLock;
* @author Thomas Ball
* @author Fred Ecks
*/
-public final class AppContext extends AppContextDC {
+public final class AppContext {
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.AppContext");
/* Since the contents of an AppContext are unique to each Java
@@ -161,8 +162,9 @@ public final class AppContext extends AppContextDC {
}
/* 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;
/*
@@ -188,31 +190,16 @@ public final class AppContext extends AppContextDC {
public static final String DISPOSED_PROPERTY_NAME = "disposed";
public static final String GUI_DISPOSED = "guidisposed";
- private volatile boolean isDisposed = false; // true if AppContext is disposed
+ private enum State {
+ VALID,
+ BEING_DISPOSED,
+ DISPOSED
+ };
- public boolean isDisposed() {
- return isDisposed;
- }
+ private volatile State state = State.VALID;
- 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() {
- public Object 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);
- numAppContexts = 1;
- return mainAppContext;
- }
- });
+ public boolean isDisposed() {
+ return state == State.DISPOSED;
}
/*
@@ -222,7 +209,7 @@ public final class AppContext extends AppContextDC {
* number is 1. If so, it returns the sole AppContext without
* checking Thread.currentThread().
*/
- private static volatile int numAppContexts;
+ private static final AtomicInteger numAppContexts = new AtomicInteger(0);
/*
* The context ClassLoader that was used to create this AppContext.
@@ -243,7 +230,7 @@ public final class AppContext extends AppContextDC {
* @since 1.2
*/
AppContext(ThreadGroup threadGroup) {
- numAppContexts++;
+ numAppContexts.incrementAndGet();
this.threadGroup = threadGroup;
threadGroup2appContext.put(threadGroup, this);
@@ -266,6 +253,27 @@ public final class AppContext extends AppContextDC {
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 +286,10 @@ public final class AppContext extends AppContextDC {
* @since 1.2
*/
public final static AppContext getAppContext() {
- if (numAppContexts == 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 +303,37 @@ public final class AppContext extends AppContextDC {
// 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,33 +341,30 @@ public final class AppContext extends AppContextDC {
});
}
- 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.
- SecurityManager securityManager = System.getSecurityManager();
- if ((securityManager != null) &&
- (securityManager instanceof AWTSecurityManager))
- {
- AWTSecurityManager awtSecMgr = (AWTSecurityManager)securityManager;
- AppContext secAppContext = awtSecMgr.getAppContext();
- if (secAppContext != null) {
- appContext = secAppContext; // Return what we're told
- }
- }
- }
-
return appContext;
}
/**
- * Returns the main ("system") AppContext.
+ * Returns true if the specified AppContext is the main AppContext.
*
- * @return 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
*/
- final static AppContext getMainAppContext() {
- return mainAppContext;
+ public final static boolean isMainContext(AppContext ctx) {
+ return (ctx != null && ctx == mainAppContext);
+ }
+
+ private final static AppContext getExecutionAppContext() {
+ SecurityManager securityManager = System.getSecurityManager();
+ if ((securityManager != null) &&
+ (securityManager instanceof AWTSecurityManager))
+ {
+ AWTSecurityManager awtSecMgr = (AWTSecurityManager) securityManager;
+ AppContext secAppContext = awtSecMgr.getAppContext();
+ return secAppContext; // Return what we're told
+ }
+ return null;
}
private long DISPOSAL_TIMEOUT = 5000; // Default to 5-second timeout
@@ -383,10 +398,11 @@ public final class AppContext extends AppContextDC {
}
synchronized(this) {
- if (this.isDisposed) {
- return; // If already disposed, bail.
+ if (this.state != State.VALID) {
+ return; // If already disposed or being disposed, bail.
}
- this.isDisposed = true;
+
+ this.state = State.BEING_DISPOSED;
}
final PropertyChangeSupport changeSupport = this.changeSupport;
@@ -401,6 +417,27 @@ public final class AppContext extends AppContextDC {
Runnable runnable = new Runnable() {
public void run() {
+ Window[] windowsToDispose = Window.getOwnerlessWindows();
+ for (Window w : windowsToDispose) {
+ try {
+ w.dispose();
+ } catch (Throwable t) {
+ log.finer("exception occured while disposing app context", t);
+ }
+ }
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ if (!GraphicsEnvironment.isHeadless() && SystemTray.isSupported())
+ {
+ SystemTray systemTray = SystemTray.getSystemTray();
+ TrayIcon[] trayIconsToDispose = systemTray.getTrayIcons();
+ for (TrayIcon ti : trayIconsToDispose) {
+ systemTray.remove(ti);
+ }
+ }
+ return null;
+ }
+ });
// Alert PropertyChangeListeners that the GUI has been disposed.
if (changeSupport != null) {
changeSupport.firePropertyChange(GUI_DISPOSED, false, true);
@@ -435,6 +472,11 @@ public final class AppContext extends AppContextDC {
} catch (InterruptedException e) { }
}
+ // We are done with posting events, so change the state to disposed
+ synchronized(this) {
+ this.state = State.DISPOSED;
+ }
+
// Next, we interrupt all Threads in the ThreadGroup
this.threadGroup.interrupt();
// Note, the EventDispatchThread we've interrupted may dump an
@@ -492,7 +534,7 @@ public final class AppContext extends AppContextDC {
this.table.clear(); // Clear out the Hashtable to ease garbage collection
}
- numAppContexts--;
+ numAppContexts.decrementAndGet();
mostRecentKeyValue = null;
}
@@ -766,6 +808,50 @@ public final class AppContext extends AppContextDC {
}
return changeSupport.getPropertyChangeListeners(propertyName);
}
+
+ // Set up JavaAWTAccess in SharedSecrets
+ static {
+ sun.misc.SharedSecrets.setJavaAWTAccess(new sun.misc.JavaAWTAccess() {
+ public Object get(Object key) {
+ AppContext ac = getAppContext();
+ return (ac == null) ? null : ac.get(key);
+ }
+ public void put(Object key, Object value) {
+ AppContext ac = getAppContext();
+ if (ac != null) {
+ ac.put(key, value);
+ }
+ }
+ public void remove(Object key) {
+ AppContext ac = getAppContext();
+ if (ac != null) {
+ ac.remove(key);
+ }
+ }
+ public boolean isDisposed() {
+ AppContext ac = getAppContext();
+ return (ac == null) ? true : ac.isDisposed();
+ }
+ public boolean isMainAppContext() {
+ return (numAppContexts.get() == 1 && mainAppContext != null);
+ }
+ public Object getContext() {
+ return getAppContext();
+ }
+ public Object getExecutionContext() {
+ return getExecutionAppContext();
+ }
+ public Object get(Object context, Object key) {
+ return ((AppContext)context).get(key);
+ }
+ public void put(Object context, Object key, Object value) {
+ ((AppContext)context).put(key, value);
+ }
+ public void remove(Object context, Object key) {
+ ((AppContext)context).remove(key);
+ }
+ });
+ }
}
final class MostRecentKeyValue {