mirror of
https://github.com/openjdk/jdk.git
synced 2026-06-06 10:42:45 +00:00
8385347: Remove AppContext from SunToolkit and also remove AppContext
Reviewed-by: azvegint, serb, kizune
This commit is contained in:
parent
08ecb87b3d
commit
05244e8d37
@ -853,8 +853,10 @@ public class EventQueue {
|
||||
newEventQueue.previousQueue = topQueue;
|
||||
topQueue.nextQueue = newEventQueue;
|
||||
|
||||
if (SunToolkit.currentEventQueue == topQueue) {
|
||||
SunToolkit.currentEventQueue = newEventQueue;
|
||||
synchronized (SunToolkit.class) {
|
||||
if (SunToolkit.getSystemEventQueueImplPP() == topQueue) {
|
||||
SunToolkit.currentEventQueue = newEventQueue;
|
||||
}
|
||||
}
|
||||
|
||||
pushPopCond.signalAll();
|
||||
@ -913,8 +915,10 @@ public class EventQueue {
|
||||
topQueue.dispatchThread.setEventQueue(prevQueue);
|
||||
}
|
||||
|
||||
if (SunToolkit.currentEventQueue == this) {
|
||||
SunToolkit.currentEventQueue = prevQueue;
|
||||
synchronized (SunToolkit.class) {
|
||||
if (SunToolkit.getSystemEventQueueImplPP() == this) {
|
||||
SunToolkit.currentEventQueue = prevQueue;
|
||||
}
|
||||
}
|
||||
|
||||
// Wake up EDT waiting in getNextEvent(), so it can
|
||||
|
||||
@ -125,7 +125,6 @@ public class TrayIcon {
|
||||
if (!SystemTray.isSupported()) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
SunToolkit.insertTargetMapping(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,692 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2026, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.awt;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.Window;
|
||||
import java.awt.SystemTray;
|
||||
import java.awt.TrayIcon;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.event.InvocationEvent;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.lang.ref.SoftReference;
|
||||
|
||||
import sun.util.logging.PlatformLogger;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* The AppContext is a table referenced by ThreadGroup which stores
|
||||
* application service instances. (If you are not writing an application
|
||||
* service, or don't know what one is, please do not use this class.)
|
||||
* The AppContext allows a context access to what would otherwise be
|
||||
* potentially dangerous services, such as the ability to peek at
|
||||
* EventQueues or change the look-and-feel of a Swing application.<p>
|
||||
*
|
||||
* Most application services use a singleton object to provide their
|
||||
* services, either as a default (such as getSystemEventQueue or
|
||||
* getDefaultToolkit) or as static methods with class data (System).
|
||||
* The AppContext works with the former method by extending the concept
|
||||
* of "default" to be ThreadGroup-specific. Application services
|
||||
* lookup their singleton in the AppContext.<p>
|
||||
*
|
||||
* For example, here we have a Foo service, with its pre-AppContext
|
||||
* code:<p>
|
||||
* <pre>{@code
|
||||
* public class Foo {
|
||||
* private static Foo defaultFoo = new Foo();
|
||||
*
|
||||
* public static Foo getDefaultFoo() {
|
||||
* return defaultFoo;
|
||||
* }
|
||||
*
|
||||
* ... Foo service methods
|
||||
* }
|
||||
* }</pre><p>
|
||||
*
|
||||
* The problem with the above is that the Foo service is global in scope,
|
||||
* so that untrusted code can execute methods on the
|
||||
* single, shared Foo instance. The Foo service therefore either needs
|
||||
* to block its use by untrusted code using a SecurityManager test, or
|
||||
* restrict its capabilities so that it doesn't matter if untrusted code
|
||||
* executes it.<p>
|
||||
*
|
||||
* Here's the Foo class written to use the AppContext:<p>
|
||||
* <pre>{@code
|
||||
* public class Foo {
|
||||
* public static Foo getDefaultFoo() {
|
||||
* Foo foo = (Foo)AppContext.getAppContext().get(Foo.class);
|
||||
* if (foo == null) {
|
||||
* foo = new Foo();
|
||||
* getAppContext().put(Foo.class, foo);
|
||||
* }
|
||||
* return foo;
|
||||
* }
|
||||
*
|
||||
* ... Foo service methods
|
||||
* }
|
||||
* }</pre><p>
|
||||
*
|
||||
* Since a separate AppContext can exist for each ThreadGroup, trusted
|
||||
* and untrusted code have access to different Foo instances. This allows
|
||||
* untrusted code access to "system-wide" services -- the service remains
|
||||
* within the AppContext "sandbox". For example, say malicious code
|
||||
* wants to peek all of the key events on the EventQueue to listen for
|
||||
* passwords; if separate EventQueues are used for each ThreadGroup
|
||||
* using AppContexts, the only key events that code will be able to
|
||||
* listen to are its own. A more reasonable request would be to
|
||||
* change the Swing default look-and-feel; with that default stored in
|
||||
* an AppContext, the look-and-feel will change without
|
||||
* disrupting other contexts.
|
||||
*
|
||||
* @author Thomas Ball
|
||||
* @author Fred Ecks
|
||||
*/
|
||||
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
|
||||
* session, this class should never be serialized. */
|
||||
|
||||
/* A map of AppContexts, referenced by ThreadGroup.
|
||||
*/
|
||||
private static final Map<ThreadGroup, AppContext> threadGroup2appContext =
|
||||
Collections.synchronizedMap(new IdentityHashMap<ThreadGroup, AppContext>());
|
||||
|
||||
/**
|
||||
* Returns a set containing all {@code AppContext}s.
|
||||
*/
|
||||
public static Set<AppContext> getAppContexts() {
|
||||
synchronized (threadGroup2appContext) {
|
||||
return new HashSet<AppContext>(threadGroup2appContext.values());
|
||||
}
|
||||
}
|
||||
|
||||
/* The main "system" AppContext, used by everything not otherwise
|
||||
contained in another AppContext. It is implicitly created for
|
||||
standalone apps only.
|
||||
*/
|
||||
private static volatile AppContext mainAppContext;
|
||||
|
||||
private static class GetAppContextLock {}
|
||||
private static final Object getAppContextLock = new GetAppContextLock();
|
||||
|
||||
/*
|
||||
* The hash map associated with this AppContext. A private delegate
|
||||
* is used instead of subclassing HashMap so as to avoid all of
|
||||
* HashMap's potentially risky methods, such as clear(), elements(),
|
||||
* putAll(), etc.
|
||||
*/
|
||||
private final Map<Object, Object> table = new HashMap<>();
|
||||
|
||||
private final ThreadGroup threadGroup;
|
||||
|
||||
/**
|
||||
* If any {@code PropertyChangeListeners} have been registered,
|
||||
* the {@code changeSupport} field describes them.
|
||||
*
|
||||
* @see #addPropertyChangeListener
|
||||
* @see #removePropertyChangeListener
|
||||
* @see PropertyChangeSupport#firePropertyChange
|
||||
*/
|
||||
private PropertyChangeSupport changeSupport = null;
|
||||
|
||||
public static final String DISPOSED_PROPERTY_NAME = "disposed";
|
||||
public static final String GUI_DISPOSED = "guidisposed";
|
||||
|
||||
private enum State {
|
||||
VALID,
|
||||
BEING_DISPOSED,
|
||||
DISPOSED
|
||||
}
|
||||
|
||||
private volatile State state = State.VALID;
|
||||
|
||||
public boolean isDisposed() {
|
||||
return state == State.DISPOSED;
|
||||
}
|
||||
|
||||
/*
|
||||
* The total number of AppContexts, system-wide. This number is
|
||||
* incremented at the beginning of the constructor, and decremented
|
||||
* at the end of dispose(). getAppContext() checks to see if this
|
||||
* number is 1. If so, it returns the sole AppContext without
|
||||
* checking Thread.currentThread().
|
||||
*/
|
||||
private static final AtomicInteger numAppContexts = new AtomicInteger();
|
||||
|
||||
|
||||
/*
|
||||
* The context ClassLoader that was used to create this AppContext.
|
||||
*/
|
||||
private final ClassLoader contextClassLoader;
|
||||
|
||||
/**
|
||||
* Constructor for AppContext. This method is <i>not</i> public,
|
||||
* nor should it ever be used as such. The proper way to construct
|
||||
* an AppContext is through the use of SunToolkit.createNewAppContext.
|
||||
* A ThreadGroup is created for the new AppContext, a Thread is
|
||||
* created within that ThreadGroup, and that Thread calls
|
||||
* SunToolkit.createNewAppContext before calling anything else.
|
||||
* That creates both the new AppContext and its EventQueue.
|
||||
*
|
||||
* @param threadGroup The ThreadGroup for the new AppContext
|
||||
* @see sun.awt.SunToolkit
|
||||
* @since 1.2
|
||||
*/
|
||||
AppContext(ThreadGroup threadGroup) {
|
||||
numAppContexts.incrementAndGet();
|
||||
|
||||
this.threadGroup = threadGroup;
|
||||
threadGroup2appContext.put(threadGroup, this);
|
||||
|
||||
this.contextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
}
|
||||
|
||||
private static final ThreadLocal<AppContext> threadAppContext =
|
||||
new ThreadLocal<AppContext>();
|
||||
|
||||
private 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.
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the appropriate AppContext for the caller,
|
||||
* as determined by its ThreadGroup.
|
||||
*
|
||||
* @return the AppContext for the caller.
|
||||
* @see java.lang.ThreadGroup
|
||||
* @since 1.2
|
||||
*/
|
||||
public static AppContext getAppContext() {
|
||||
// we are standalone app, return the main app context
|
||||
if (numAppContexts.get() == 1 && mainAppContext != null) {
|
||||
return mainAppContext;
|
||||
}
|
||||
|
||||
AppContext appContext = threadAppContext.get();
|
||||
|
||||
if (null == appContext) {
|
||||
// Get the current ThreadGroup, and look for it and its
|
||||
// parents in the hash from ThreadGroup to AppContext --
|
||||
// it should be found, because we use createNewContext()
|
||||
// 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.
|
||||
synchronized (getAppContextLock) {
|
||||
if (numAppContexts.get() == 0) {
|
||||
if (System.getProperty("javaplugin.version") == null &&
|
||||
System.getProperty("javawebstart.version") == null) {
|
||||
initMainAppContext();
|
||||
} else if (System.getProperty("javafx.version") != null &&
|
||||
threadGroup.getParent() != null) {
|
||||
// Swing inside JavaFX case
|
||||
SunToolkit.createNewAppContext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AppContext context = threadGroup2appContext.get(threadGroup);
|
||||
while (context == null) {
|
||||
threadGroup = threadGroup.getParent();
|
||||
if (threadGroup == null) {
|
||||
// We've got up to the root thread group and did not find an AppContext
|
||||
// We have nowhere else to look, and this is not supposed to happen.
|
||||
// return null from this whole method.
|
||||
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.
|
||||
threadAppContext.set(context);
|
||||
|
||||
appContext = context;
|
||||
}
|
||||
|
||||
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 static boolean isMainContext(AppContext ctx) {
|
||||
return (ctx != null && ctx == mainAppContext);
|
||||
}
|
||||
|
||||
private long DISPOSAL_TIMEOUT = 5000; // Default to 5-second timeout
|
||||
// for disposal of all Frames
|
||||
// (we wait for this time twice,
|
||||
// once for dispose(), and once
|
||||
// to clear the EventQueue).
|
||||
|
||||
private long THREAD_INTERRUPT_TIMEOUT = 1000;
|
||||
// Default to 1-second timeout for all
|
||||
// interrupted Threads to exit, and another
|
||||
// 1 second for all stopped Threads to die.
|
||||
|
||||
/**
|
||||
* Disposes of this AppContext, all of its top-level Frames, and
|
||||
* all Threads and ThreadGroups contained within it.
|
||||
*
|
||||
* This method must be called from a Thread which is not contained
|
||||
* within this AppContext.
|
||||
*
|
||||
* @throws IllegalThreadStateException if the current thread is
|
||||
* contained within this AppContext
|
||||
* @since 1.2
|
||||
*/
|
||||
public void dispose() throws IllegalThreadStateException {
|
||||
System.err.println(
|
||||
"""
|
||||
WARNING: sun.awt.AppContext.dispose() no longer stops threads.
|
||||
Additionally AppContext will be removed in a future release.
|
||||
Remove all uses of this internal class as soon as possible.
|
||||
There is no replacement.
|
||||
""");
|
||||
// Check to be sure that the current Thread isn't in this AppContext
|
||||
if (this.threadGroup.parentOf(Thread.currentThread().getThreadGroup())) {
|
||||
throw new IllegalThreadStateException(
|
||||
"Current Thread is contained within AppContext to be disposed."
|
||||
);
|
||||
}
|
||||
|
||||
synchronized(this) {
|
||||
if (this.state != State.VALID) {
|
||||
return; // If already disposed or being disposed, bail.
|
||||
}
|
||||
|
||||
this.state = State.BEING_DISPOSED;
|
||||
}
|
||||
|
||||
final PropertyChangeSupport changeSupport = this.changeSupport;
|
||||
if (changeSupport != null) {
|
||||
changeSupport.firePropertyChange(DISPOSED_PROPERTY_NAME, false, true);
|
||||
}
|
||||
|
||||
// First, we post an InvocationEvent to be run on the
|
||||
// EventDispatchThread which disposes of all top-level Frames and TrayIcons
|
||||
|
||||
final Object notificationLock = new Object();
|
||||
|
||||
Runnable runnable = new Runnable() {
|
||||
public void run() {
|
||||
Window[] windowsToDispose = Window.getOwnerlessWindows();
|
||||
for (Window w : windowsToDispose) {
|
||||
try {
|
||||
w.dispose();
|
||||
} catch (Throwable t) {
|
||||
log.finer("exception occurred while disposing app context", t);
|
||||
}
|
||||
}
|
||||
if (!GraphicsEnvironment.isHeadless() && SystemTray.isSupported()) {
|
||||
SystemTray systemTray = SystemTray.getSystemTray();
|
||||
TrayIcon[] trayIconsToDispose = systemTray.getTrayIcons();
|
||||
for (TrayIcon ti : trayIconsToDispose) {
|
||||
systemTray.remove(ti);
|
||||
}
|
||||
}
|
||||
// Alert PropertyChangeListeners that the GUI has been disposed.
|
||||
if (changeSupport != null) {
|
||||
changeSupport.firePropertyChange(GUI_DISPOSED, false, true);
|
||||
}
|
||||
synchronized(notificationLock) {
|
||||
notificationLock.notifyAll(); // Notify caller that we're done
|
||||
}
|
||||
}
|
||||
};
|
||||
synchronized(notificationLock) {
|
||||
SunToolkit.postEvent(this,
|
||||
new InvocationEvent(Toolkit.getDefaultToolkit(), runnable));
|
||||
try {
|
||||
notificationLock.wait(DISPOSAL_TIMEOUT);
|
||||
} catch (InterruptedException e) { }
|
||||
}
|
||||
|
||||
// Next, we post another InvocationEvent to the end of the
|
||||
// EventQueue. When it's executed, we know we've executed all
|
||||
// events in the queue.
|
||||
|
||||
runnable = new Runnable() { public void run() {
|
||||
synchronized(notificationLock) {
|
||||
notificationLock.notifyAll(); // Notify caller that we're done
|
||||
}
|
||||
} };
|
||||
synchronized(notificationLock) {
|
||||
SunToolkit.postEvent(this,
|
||||
new InvocationEvent(Toolkit.getDefaultToolkit(), runnable));
|
||||
try {
|
||||
notificationLock.wait(DISPOSAL_TIMEOUT);
|
||||
} 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
|
||||
// InterruptedException to the console here. This needs to be
|
||||
// fixed in the EventDispatchThread, not here.
|
||||
|
||||
// Next, we sleep 10ms at a time, waiting for all of the active
|
||||
// Threads in the ThreadGroup to exit.
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
long endTime = startTime + THREAD_INTERRUPT_TIMEOUT;
|
||||
while ((this.threadGroup.activeCount() > 0) &&
|
||||
(System.currentTimeMillis() < endTime)) {
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
} catch (InterruptedException e) { }
|
||||
}
|
||||
|
||||
// Next, we remove this and all subThreadGroups from threadGroup2appContext
|
||||
int numSubGroups = this.threadGroup.activeGroupCount();
|
||||
if (numSubGroups > 0) {
|
||||
ThreadGroup [] subGroups = new ThreadGroup[numSubGroups];
|
||||
numSubGroups = this.threadGroup.enumerate(subGroups);
|
||||
for (int subGroup = 0; subGroup < numSubGroups; subGroup++) {
|
||||
threadGroup2appContext.remove(subGroups[subGroup]);
|
||||
}
|
||||
}
|
||||
threadGroup2appContext.remove(this.threadGroup);
|
||||
|
||||
threadAppContext.set(null);
|
||||
|
||||
synchronized (table) {
|
||||
this.table.clear(); // Clear out the Hashtable to ease garbage collection
|
||||
}
|
||||
|
||||
numAppContexts.decrementAndGet();
|
||||
|
||||
mostRecentKeyValue = null;
|
||||
}
|
||||
|
||||
private MostRecentKeyValue mostRecentKeyValue = null;
|
||||
private MostRecentKeyValue shadowMostRecentKeyValue = null;
|
||||
|
||||
/**
|
||||
* Returns the value to which the specified key is mapped in this context.
|
||||
*
|
||||
* @param key a key in the AppContext.
|
||||
* @return the value to which the key is mapped in this AppContext;
|
||||
* {@code null} if the key is not mapped to any value.
|
||||
* @see #put(Object, Object)
|
||||
* @since 1.2
|
||||
*/
|
||||
public Object get(Object key) {
|
||||
/*
|
||||
* The most recent reference should be updated inside a synchronized
|
||||
* block to avoid a race when put() and get() are executed in
|
||||
* parallel on different threads.
|
||||
*/
|
||||
synchronized (table) {
|
||||
// Note: this most recent key/value caching is thread-hot.
|
||||
// A simple test using SwingSet found that 72% of lookups
|
||||
// were matched using the most recent key/value. By instantiating
|
||||
// a simple MostRecentKeyValue object on cache misses, the
|
||||
// cache hits can be processed without synchronization.
|
||||
|
||||
MostRecentKeyValue recent = mostRecentKeyValue;
|
||||
if ((recent != null) && (recent.key == key)) {
|
||||
return recent.value;
|
||||
}
|
||||
|
||||
Object value = table.get(key);
|
||||
if(mostRecentKeyValue == null) {
|
||||
mostRecentKeyValue = new MostRecentKeyValue(key, value);
|
||||
shadowMostRecentKeyValue = new MostRecentKeyValue(key, value);
|
||||
} else {
|
||||
MostRecentKeyValue auxKeyValue = mostRecentKeyValue;
|
||||
shadowMostRecentKeyValue.setPair(key, value);
|
||||
mostRecentKeyValue = shadowMostRecentKeyValue;
|
||||
shadowMostRecentKeyValue = auxKeyValue;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the specified {@code key} to the specified
|
||||
* {@code value} in this AppContext. Neither the key nor the
|
||||
* value can be {@code null}.
|
||||
* <p>
|
||||
* The value can be retrieved by calling the {@code get} method
|
||||
* with a key that is equal to the original key.
|
||||
*
|
||||
* @param key the AppContext key.
|
||||
* @param value the value.
|
||||
* @return the previous value of the specified key in this
|
||||
* AppContext, or {@code null} if it did not have one.
|
||||
* @throws NullPointerException if the key or value is
|
||||
* {@code null}.
|
||||
* @see #get(Object)
|
||||
* @since 1.2
|
||||
*/
|
||||
public Object put(Object key, Object value) {
|
||||
synchronized (table) {
|
||||
MostRecentKeyValue recent = mostRecentKeyValue;
|
||||
if ((recent != null) && (recent.key == key))
|
||||
recent.value = value;
|
||||
return table.put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the key (and its corresponding value) from this
|
||||
* AppContext. This method does nothing if the key is not in the
|
||||
* AppContext.
|
||||
*
|
||||
* @param key the key that needs to be removed.
|
||||
* @return the value to which the key had been mapped in this AppContext,
|
||||
* or {@code null} if the key did not have a mapping.
|
||||
* @since 1.2
|
||||
*/
|
||||
public Object remove(Object key) {
|
||||
synchronized (table) {
|
||||
MostRecentKeyValue recent = mostRecentKeyValue;
|
||||
if ((recent != null) && (recent.key == key))
|
||||
recent.value = null;
|
||||
return table.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the root ThreadGroup for all Threads contained within
|
||||
* this AppContext.
|
||||
* @since 1.2
|
||||
*/
|
||||
public ThreadGroup getThreadGroup() {
|
||||
return threadGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the context ClassLoader that was used to create this
|
||||
* AppContext.
|
||||
*
|
||||
* @see java.lang.Thread#getContextClassLoader
|
||||
*/
|
||||
public ClassLoader getContextClassLoader() {
|
||||
return contextClassLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this AppContext.
|
||||
* @since 1.2
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getName() + "[threadGroup=" + threadGroup.getName() + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all the property change listeners
|
||||
* registered on this component.
|
||||
*
|
||||
* @return all of this component's {@code PropertyChangeListener}s
|
||||
* or an empty array if no property change
|
||||
* listeners are currently registered
|
||||
*
|
||||
* @see #addPropertyChangeListener
|
||||
* @see #removePropertyChangeListener
|
||||
* @see #getPropertyChangeListeners(java.lang.String)
|
||||
* @see java.beans.PropertyChangeSupport#getPropertyChangeListeners
|
||||
* @since 1.4
|
||||
*/
|
||||
public synchronized PropertyChangeListener[] getPropertyChangeListeners() {
|
||||
if (changeSupport == null) {
|
||||
return new PropertyChangeListener[0];
|
||||
}
|
||||
return changeSupport.getPropertyChangeListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a PropertyChangeListener to the listener list for a specific
|
||||
* property. The specified property may be one of the following:
|
||||
* <ul>
|
||||
* <li>if this AppContext is disposed ("disposed")</li>
|
||||
* </ul>
|
||||
* <ul>
|
||||
* <li>if this AppContext's unowned Windows have been disposed
|
||||
* ("guidisposed"). Code to cleanup after the GUI is disposed
|
||||
* (such as LookAndFeel.uninitialize()) should execute in response to
|
||||
* this property being fired. Notifications for the "guidisposed"
|
||||
* property are sent on the event dispatch thread.</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* If listener is null, no exception is thrown and no action is performed.
|
||||
*
|
||||
* @param propertyName one of the property names listed above
|
||||
* @param listener the PropertyChangeListener to be added
|
||||
*
|
||||
* @see #removePropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener)
|
||||
* @see #getPropertyChangeListeners(java.lang.String)
|
||||
* @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener)
|
||||
*/
|
||||
public synchronized void addPropertyChangeListener(
|
||||
String propertyName,
|
||||
PropertyChangeListener listener) {
|
||||
if (listener == null) {
|
||||
return;
|
||||
}
|
||||
if (changeSupport == null) {
|
||||
changeSupport = new PropertyChangeSupport(this);
|
||||
}
|
||||
changeSupport.addPropertyChangeListener(propertyName, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a PropertyChangeListener from the listener list for a specific
|
||||
* property. This method should be used to remove PropertyChangeListeners
|
||||
* that were registered for a specific bound property.
|
||||
* <p>
|
||||
* If listener is null, no exception is thrown and no action is performed.
|
||||
*
|
||||
* @param propertyName a valid property name
|
||||
* @param listener the PropertyChangeListener to be removed
|
||||
*
|
||||
* @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener)
|
||||
* @see #getPropertyChangeListeners(java.lang.String)
|
||||
* @see PropertyChangeSupport#removePropertyChangeListener(java.beans.PropertyChangeListener)
|
||||
*/
|
||||
public synchronized void removePropertyChangeListener(
|
||||
String propertyName,
|
||||
PropertyChangeListener listener) {
|
||||
if (listener == null || changeSupport == null) {
|
||||
return;
|
||||
}
|
||||
changeSupport.removePropertyChangeListener(propertyName, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all the listeners which have been associated
|
||||
* with the named property.
|
||||
*
|
||||
* @return all of the {@code PropertyChangeListeners} associated with
|
||||
* the named property or an empty array if no listeners have
|
||||
* been added
|
||||
*
|
||||
* @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener)
|
||||
* @see #removePropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener)
|
||||
* @see #getPropertyChangeListeners
|
||||
* @since 1.4
|
||||
*/
|
||||
public synchronized PropertyChangeListener[] getPropertyChangeListeners(
|
||||
String propertyName) {
|
||||
if (changeSupport == null) {
|
||||
return new PropertyChangeListener[0];
|
||||
}
|
||||
return changeSupport.getPropertyChangeListeners(propertyName);
|
||||
}
|
||||
}
|
||||
|
||||
final class MostRecentKeyValue {
|
||||
Object key;
|
||||
Object value;
|
||||
MostRecentKeyValue(Object k, Object v) {
|
||||
key = k;
|
||||
value = v;
|
||||
}
|
||||
void setPair(Object k, Object v) {
|
||||
key = k;
|
||||
value = v;
|
||||
}
|
||||
}
|
||||
@ -166,6 +166,7 @@ public abstract class SunToolkit extends Toolkit
|
||||
}
|
||||
|
||||
public SunToolkit() {
|
||||
initEQ();
|
||||
}
|
||||
|
||||
public boolean useBufferPerWindow() {
|
||||
@ -258,24 +259,6 @@ public abstract class SunToolkit extends Toolkit
|
||||
return AWT_LOCK.isHeldByCurrentThread();
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new AppContext, along with its EventQueue, for a
|
||||
* new ThreadGroup.
|
||||
*/
|
||||
public static AppContext createNewAppContext() {
|
||||
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
|
||||
return createNewAppContext(threadGroup);
|
||||
}
|
||||
|
||||
static final AppContext createNewAppContext(ThreadGroup threadGroup) {
|
||||
// Create appContext before initialization of EventQueue, so all
|
||||
// the calls to AppContext.getAppContext() from EventQueue ctor
|
||||
// return correct values
|
||||
AppContext appContext = new AppContext(threadGroup);
|
||||
initEQ();
|
||||
return appContext;
|
||||
}
|
||||
|
||||
static void wakeupEventQueue(EventQueue q, boolean isShutdown){
|
||||
AWTAccessor.getEventQueueAccessor().wakeup(q, isShutdown);
|
||||
}
|
||||
@ -311,52 +294,6 @@ public abstract class SunToolkit extends Toolkit
|
||||
}
|
||||
}
|
||||
|
||||
// Maps from non-Component/MenuComponent to AppContext.
|
||||
// WeakHashMap<Component,AppContext>
|
||||
private static final Map<Object, AppContext> appContextMap =
|
||||
Collections.synchronizedMap(new WeakIdentityHashMap<Object, AppContext>());
|
||||
|
||||
/**
|
||||
* Sets the appContext field of target. If target is not a Component or
|
||||
* MenuComponent, this returns false.
|
||||
*/
|
||||
private static boolean setAppContext(Object target,
|
||||
AppContext context) {
|
||||
return (target instanceof Component);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the appContext field for target. If target is not a
|
||||
* Component or MenuComponent this returns null.
|
||||
*/
|
||||
private static AppContext getAppContext(Object target) {
|
||||
if ((target instanceof Component) ||
|
||||
(target instanceof MenuComponent)) {
|
||||
return AppContext.getAppContext();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetch the AppContext associated with the given target.
|
||||
* This can be used to determine things like which EventQueue
|
||||
* to use for posting events to a Component. If the target is
|
||||
* null or the target can't be found, a null with be returned.
|
||||
*/
|
||||
public static AppContext targetToAppContext(Object target) {
|
||||
if (target == null) {
|
||||
return null;
|
||||
}
|
||||
AppContext context = getAppContext(target);
|
||||
if (context == null) {
|
||||
// target is not a Component/MenuComponent, try the
|
||||
// appContextMap.
|
||||
context = appContextMap.get(target);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the synchronous status of focus requests on lightweight
|
||||
* components in the specified window to the specified value.
|
||||
@ -394,34 +331,6 @@ public abstract class SunToolkit extends Toolkit
|
||||
cont.setFocusTraversalPolicy(defaultPolicy);
|
||||
}
|
||||
|
||||
/* This method should be removed at the same time as targetToAppContext() */
|
||||
public static void insertTargetMapping(Object target) {
|
||||
insertTargetMapping(target, AppContext.getAppContext());
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert a mapping from target to AppContext, for later retrieval
|
||||
* via targetToAppContext() above.
|
||||
*/
|
||||
public static void insertTargetMapping(Object target, AppContext appContext) {
|
||||
if (!setAppContext(target, appContext)) {
|
||||
// Target is not a Component/MenuComponent, use the private Map
|
||||
// instead.
|
||||
appContextMap.put(target, appContext);
|
||||
}
|
||||
}
|
||||
|
||||
public static void postEvent(AWTEvent event) {
|
||||
/* Adding AppContext is temporary to help migrate away from using app contexts
|
||||
* It is used by code which has already been subject to that migration.
|
||||
* However until that is complete, there is a single main app context we
|
||||
* can retrieve to use which would be the same as if the code had
|
||||
* not been migrated.
|
||||
* The overload which accepts the AppContext will eventually be replaced by this.
|
||||
*/
|
||||
postEvent(AppContext.getAppContext(), event);
|
||||
}
|
||||
|
||||
/*
|
||||
* Post an AWTEvent to the Java EventQueue, using the PostEventQueue
|
||||
* to avoid possibly calling client code (EventQueueSubclass.postEvent())
|
||||
@ -429,7 +338,7 @@ public abstract class SunToolkit extends Toolkit
|
||||
* not be called under another lock since it locks the EventQueue.
|
||||
* See bugids 4632918, 4526597.
|
||||
*/
|
||||
public static void postEvent(AppContext appContext, AWTEvent event) {
|
||||
public static void postEvent(AWTEvent event) {
|
||||
if (event == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
@ -468,7 +377,7 @@ public abstract class SunToolkit extends Toolkit
|
||||
((Component)e.getSource()).dispatchEvent(e);
|
||||
}
|
||||
}, PeerEvent.ULTIMATE_PRIORITY_EVENT);
|
||||
postEvent(targetToAppContext(e.getSource()), pe);
|
||||
postEvent(pe);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -513,25 +422,18 @@ public abstract class SunToolkit extends Toolkit
|
||||
* returning to the caller.
|
||||
*/
|
||||
public static void executeOnEventHandlerThread(PeerEvent peerEvent) {
|
||||
postEvent(targetToAppContext(peerEvent.getSource()), peerEvent);
|
||||
postEvent(peerEvent);
|
||||
}
|
||||
|
||||
public static void invokeLater(Runnable dispatcher) {
|
||||
invokeLaterOnAppContext(AppContext.getAppContext(), dispatcher);
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute a chunk of code on the Java event handler thread. The
|
||||
* method takes into account provided AppContext and sets
|
||||
* {@code SunToolkit.getDefaultToolkit()} as a target of the
|
||||
* method sets {@code SunToolkit.getDefaultToolkit()} as a target of the
|
||||
* event. See 6451487 for details.
|
||||
* Does not wait for the execution to occur before returning to
|
||||
* the caller.
|
||||
*/
|
||||
public static void invokeLaterOnAppContext(
|
||||
AppContext appContext, Runnable dispatcher)
|
||||
{
|
||||
postEvent(appContext,
|
||||
public static void invokeLater(Runnable dispatcher) {
|
||||
postEvent(
|
||||
new PeerEvent(Toolkit.getDefaultToolkit(), dispatcher,
|
||||
PeerEvent.PRIORITY_EVENT));
|
||||
}
|
||||
@ -1479,8 +1381,7 @@ public abstract class SunToolkit extends Toolkit
|
||||
final AtomicBoolean eventDispatched = new AtomicBoolean();
|
||||
synchronized (waitLock) {
|
||||
queueWasEmpty = isEQEmpty();
|
||||
postEvent(AppContext.getAppContext(),
|
||||
new PeerEvent(getSystemEventQueueImpl(), null, PeerEvent.LOW_PRIORITY_EVENT) {
|
||||
postEvent(new PeerEvent(getSystemEventQueueImpl(), null, PeerEvent.LOW_PRIORITY_EVENT) {
|
||||
@Override
|
||||
public void dispatch() {
|
||||
// Here we block EDT. It could have some
|
||||
|
||||
@ -478,8 +478,6 @@ final class XSelection {
|
||||
int count = 0;
|
||||
|
||||
try {
|
||||
SunToolkit.insertTargetMapping(this);
|
||||
|
||||
byteData = DataTransferer.getInstance().convertData(this,
|
||||
contents,
|
||||
format,
|
||||
|
||||
@ -33,8 +33,7 @@ import sun.awt.UngrabEvent;
|
||||
|
||||
/**
|
||||
* This class provides static utility methods to be used by FX swing interop
|
||||
* to access and use jdk internal classes like SunToolkit, AppContext
|
||||
* and UngrabEvent.
|
||||
* to access and use jdk internal classes like SunToolkit and UngrabEvent.
|
||||
*
|
||||
* @since 11
|
||||
*/
|
||||
|
||||
@ -142,7 +142,6 @@ java/awt/Focus/ToFrontFocusTest/ToFrontFocus.java 7156130 linux-all
|
||||
java/awt/Focus/WrongKeyTypedConsumedTest/WrongKeyTypedConsumedTest.java 8169096 macosx-all
|
||||
java/awt/Focus/TestDisabledAutoTransfer.java 8159871 macosx-all,windows-all
|
||||
java/awt/Focus/TestDisabledAutoTransferSwing.java 6962362 windows-all
|
||||
java/awt/Focus/ActivateOnProperAppContextTest.java 8136516 macosx-all
|
||||
java/awt/Focus/FocusPolicyTest.java 7160904 linux-all
|
||||
java/awt/Graphics/SmallPrimitives.java 8047070 macosx-all,linux-all
|
||||
java/awt/EventQueue/6980209/bug6980209.java 8198615 macosx-all
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2026, 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
|
||||
@ -44,7 +44,6 @@ import java.awt.event.WindowEvent;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import sun.awt.SunToolkit;
|
||||
import sun.awt.AppContext;
|
||||
|
||||
public class JaWSTest implements ActionListener, Runnable {
|
||||
|
||||
@ -52,7 +51,6 @@ public class JaWSTest implements ActionListener, Runnable {
|
||||
static volatile JaWSTest worker;
|
||||
static volatile Dialog dummyDialog;
|
||||
static final Object signalObject = new Object();
|
||||
static volatile AppContext appContextObject = null;
|
||||
static volatile Button button = null;
|
||||
static final CountDownLatch dialogFinished = new CountDownLatch(1);
|
||||
|
||||
@ -115,9 +113,6 @@ public class JaWSTest implements ActionListener, Runnable {
|
||||
e.printStackTrace();
|
||||
dummyDialog.setVisible(false);
|
||||
}
|
||||
if (appContextObject != null) {
|
||||
appContextObject = null;
|
||||
}
|
||||
dummyDialog.dispose();
|
||||
}
|
||||
System.err.println("Show Something");
|
||||
@ -127,21 +122,17 @@ public class JaWSTest implements ActionListener, Runnable {
|
||||
public void run() {
|
||||
System.err.println("Running");
|
||||
try {
|
||||
appContextObject = SunToolkit.createNewAppContext();
|
||||
} finally {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ie) {
|
||||
ie.printStackTrace();
|
||||
}
|
||||
System.err.println("Before Hiding 1");
|
||||
dummyDialog.setVisible(false);
|
||||
System.err.println("Before Synchronized");
|
||||
synchronized (signalObject) {
|
||||
System.err.println("In Synchronized");
|
||||
signalObject.notify();
|
||||
System.err.println("After Notify");
|
||||
}
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ie) {
|
||||
ie.printStackTrace();
|
||||
}
|
||||
System.err.println("Before Hiding 1");
|
||||
dummyDialog.setVisible(false);
|
||||
System.err.println("Before Synchronized");
|
||||
synchronized (signalObject) {
|
||||
System.err.println("In Synchronized");
|
||||
signalObject.notify();
|
||||
System.err.println("After Notify");
|
||||
}
|
||||
System.err.println("Stop Running");
|
||||
}
|
||||
|
||||
@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2015, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8004584
|
||||
* @summary Tests 8004584
|
||||
* @author anthony.petrov@oracle.com, petr.pchelko@oracle.com
|
||||
* @modules java.desktop/sun.awt
|
||||
*/
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import sun.awt.*;
|
||||
|
||||
public class MainAppContext {
|
||||
|
||||
public static void main(String[] args) {
|
||||
ThreadGroup secondGroup = new ThreadGroup("test");
|
||||
new Thread(secondGroup, () -> {
|
||||
SunToolkit.createNewAppContext();
|
||||
test(true);
|
||||
}).start();
|
||||
|
||||
// Sleep on the main thread so that the AWT Toolkit is initialized
|
||||
// in a user AppContext first
|
||||
try { Thread.sleep(2000); } catch (Exception e) {}
|
||||
|
||||
test(false);
|
||||
}
|
||||
|
||||
private static void test(boolean expectAppContext) {
|
||||
boolean appContextIsCreated = AppContext.getAppContext() != null;
|
||||
if (expectAppContext != appContextIsCreated) {
|
||||
throw new RuntimeException("AppContext is created: " + appContextIsCreated
|
||||
+ " expected: " + expectAppContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2026, 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
|
||||
@ -33,7 +33,6 @@
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import sun.awt.AppContext;
|
||||
import sun.awt.SunToolkit;
|
||||
|
||||
public class PostEventOrderingTest {
|
||||
@ -45,11 +44,11 @@ public class PostEventOrderingTest {
|
||||
for (int j = 0; j < 100; j++) {
|
||||
q.postEvent(new PostActionEvent());
|
||||
for (int k = 0; k < 10; k++) {
|
||||
SunToolkit.postEvent(AppContext.getAppContext(), new PostActionEvent());
|
||||
SunToolkit.postEvent(new PostActionEvent());
|
||||
}
|
||||
}
|
||||
for (int k = 0; k < 100; k++) {
|
||||
SunToolkit.postEvent(AppContext.getAppContext(), new PostActionEvent());
|
||||
SunToolkit.postEvent(new PostActionEvent());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2026, 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
|
||||
@ -66,7 +66,7 @@ public class PushPopTest {
|
||||
};
|
||||
InvocationEvent ie = new InvocationEvent(eq2, runnable, null, false);
|
||||
// System.err.println(ie);
|
||||
SunToolkit.postEvent(SunToolkit.targetToAppContext(frame), ie);
|
||||
SunToolkit.postEvent(ie);
|
||||
eq1.pop();
|
||||
frame.dispose();
|
||||
}
|
||||
@ -94,7 +94,7 @@ class MyEventQueue2 extends EventQueue {
|
||||
}
|
||||
};
|
||||
InvocationEvent ie = new InvocationEvent(MyEventQueue2.this, runnable, null, false);
|
||||
SunToolkit.postEvent(SunToolkit.targetToAppContext(PushPopTest.frame), ie);
|
||||
SunToolkit.postEvent(ie);
|
||||
postEvent(ie);
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,245 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006, 2024, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
/*
|
||||
* @test
|
||||
* @bug 6385277
|
||||
* @key headful
|
||||
* @summary Tests that activation happens on correct AppContext.
|
||||
* @modules java.desktop/sun.awt
|
||||
* @run main ActivateOnProperAppContextTest
|
||||
*/
|
||||
|
||||
import sun.awt.AppContext;
|
||||
import sun.awt.SunToolkit;
|
||||
|
||||
import java.awt.Button;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Label;
|
||||
import java.awt.Point;
|
||||
import java.awt.Robot;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class ActivateOnProperAppContextTest {
|
||||
static Robot robot;
|
||||
SunToolkit toolkit;
|
||||
|
||||
ThreadGroup threadGroup = new ThreadGroup("Test_Thread_Group");
|
||||
AppContext appContext;
|
||||
Frame frame;
|
||||
volatile boolean passed = true;
|
||||
AtomicBoolean cond = new AtomicBoolean(false);
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ActivateOnProperAppContextTest app = new ActivateOnProperAppContextTest();
|
||||
robot = new Robot();
|
||||
app.start();
|
||||
}
|
||||
|
||||
public void start() {
|
||||
toolkit = (SunToolkit)Toolkit.getDefaultToolkit();
|
||||
|
||||
Runnable runnable = new Runnable() {
|
||||
public void run() {
|
||||
test();
|
||||
|
||||
synchronized (cond) {
|
||||
cond.set(true);
|
||||
cond.notifyAll();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Thread thread = new Thread(threadGroup, runnable, "Test Thread");
|
||||
|
||||
synchronized (cond) {
|
||||
|
||||
thread.start();
|
||||
|
||||
while (!cond.get()) {
|
||||
try {
|
||||
cond.wait();
|
||||
} catch (InterruptedException ie) {
|
||||
ie.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (passed) {
|
||||
System.out.println("Test passed.");
|
||||
} else {
|
||||
throw new TestFailedException("Test failed!");
|
||||
}
|
||||
}
|
||||
|
||||
void test() {
|
||||
appContext = SunToolkit.createNewAppContext();
|
||||
System.out.println("Created new AppContext: " + appContext);
|
||||
|
||||
frame = new Frame("ActivateOnProperAppContextTest Frame") {
|
||||
public boolean isActive() {
|
||||
verifyAppContext("Frame.isActive()");
|
||||
return super.isActive();
|
||||
}
|
||||
public boolean isFocused() {
|
||||
verifyAppContext("Frame.isFocused()");
|
||||
return super.isFocused();
|
||||
}
|
||||
public boolean isFocusable() {
|
||||
verifyAppContext("Frame.isFocusable()");
|
||||
return super.isFocusable();
|
||||
}
|
||||
public Window getOwner() {
|
||||
verifyAppContext("Frame.getOwner()");
|
||||
return super.getOwner();
|
||||
}
|
||||
public boolean isEnabled() {
|
||||
verifyAppContext("Frame.isEnabled()");
|
||||
return super.isEnabled();
|
||||
}
|
||||
public boolean isVisible() {
|
||||
verifyAppContext("Frame.isVisible()");
|
||||
return super.isVisible();
|
||||
}
|
||||
public Container getParent() {
|
||||
verifyAppContext("Frame.getParent()");
|
||||
return super.getParent();
|
||||
}
|
||||
public Cursor getCursor() {
|
||||
verifyAppContext("Frame.getCursor()");
|
||||
return super.getCursor();
|
||||
}
|
||||
public Point getLocation() {
|
||||
verifyAppContext("Frame.getLocation()");
|
||||
return super.getLocation();
|
||||
}
|
||||
public Point getLocationOnScreen() {
|
||||
verifyAppContext("Frame.getLocationOnScreen()");
|
||||
return super.getLocationOnScreen();
|
||||
}
|
||||
};
|
||||
Window window = new Window(frame) {
|
||||
public boolean isFocused() {
|
||||
verifyAppContext("Window.isFocused()");
|
||||
return super.isFocused();
|
||||
}
|
||||
public boolean isFocusable() {
|
||||
verifyAppContext("Window.isFocusable()");
|
||||
return super.isFocusable();
|
||||
}
|
||||
public Window getOwner() {
|
||||
verifyAppContext("Window.getOwner()");
|
||||
return super.getOwner();
|
||||
}
|
||||
public boolean isEnabled() {
|
||||
verifyAppContext("Window.isEnabled()");
|
||||
return super.isEnabled();
|
||||
}
|
||||
public boolean isVisible() {
|
||||
verifyAppContext("Window.isVisible()");
|
||||
return super.isVisible();
|
||||
}
|
||||
public Container getParent() {
|
||||
verifyAppContext("Window.getParent()");
|
||||
return super.getParent();
|
||||
}
|
||||
public Cursor getCursor() {
|
||||
verifyAppContext("Window.getCursor()");
|
||||
return super.getCursor();
|
||||
}
|
||||
public Point getLocation() {
|
||||
verifyAppContext("Window.getLocation()");
|
||||
return super.getLocation();
|
||||
}
|
||||
public Point getLocationOnScreen() {
|
||||
verifyAppContext("Window.getLocationOnScreen()");
|
||||
return super.getLocationOnScreen();
|
||||
}
|
||||
};
|
||||
Button button = new Button("button");
|
||||
Label label = new Label("label");
|
||||
|
||||
window.setLayout(new FlowLayout());
|
||||
window.add(button);
|
||||
window.add(label);
|
||||
window.setLocation(800, 0);
|
||||
window.pack();
|
||||
window.setVisible(true);
|
||||
|
||||
frame.setBounds(800, 100, 100, 50);
|
||||
frame.setVisible(true);
|
||||
|
||||
toolkit.realSync();
|
||||
|
||||
/*
|
||||
* When the label is clicked in the window some of
|
||||
* the owner's public method get called.
|
||||
*/
|
||||
clickOn(label);
|
||||
}
|
||||
|
||||
void verifyAppContext(String methodName) {
|
||||
AppContext ac = AppContext.getAppContext();
|
||||
println(methodName + " called on AppContext: " + ac);
|
||||
|
||||
if (ac != appContext) {
|
||||
passed = false;
|
||||
System.err.println("Test failed: " + methodName + " is called on wrong AppContext!");
|
||||
Thread.dumpStack();
|
||||
}
|
||||
}
|
||||
|
||||
void clickOn(Component c) {
|
||||
Point p = c.getLocationOnScreen();
|
||||
Dimension d = c.getSize();
|
||||
|
||||
robot.mouseMove(p.x + (int)(d.getWidth()/2), p.y + (int)(d.getHeight()/2));
|
||||
|
||||
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
|
||||
robot.delay(20);
|
||||
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
|
||||
|
||||
toolkit.realSync();
|
||||
}
|
||||
|
||||
void println(final String msg) {
|
||||
SunToolkit.executeOnEventHandlerThread(frame, new Runnable() {
|
||||
public void run() {
|
||||
System.out.println(msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class TestFailedException extends RuntimeException {
|
||||
TestFailedException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2026, 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
|
||||
@ -27,8 +27,7 @@
|
||||
* @bug 8013563 8028486
|
||||
* @summary Tests that windows are removed from windows list
|
||||
* @library /javax/swing/regtesthelpers
|
||||
* @modules java.desktop/sun.awt
|
||||
* java.desktop/sun.java2d
|
||||
* @modules java.desktop/sun.java2d
|
||||
* @build Util
|
||||
* @run main/othervm -Xms32M -Xmx32M WindowsLeak
|
||||
*/
|
||||
@ -39,7 +38,6 @@ import java.awt.Window;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Vector;
|
||||
|
||||
import sun.awt.AppContext;
|
||||
import sun.java2d.Disposer;
|
||||
|
||||
public class WindowsLeak {
|
||||
@ -61,11 +59,10 @@ public class WindowsLeak {
|
||||
Util.generateOOME();
|
||||
}
|
||||
|
||||
Vector<WeakReference<Window>> windowList =
|
||||
(Vector<WeakReference<Window>>) AppContext.getAppContext().get(Window.class);
|
||||
Window[] windowList = Window.getWindows();
|
||||
|
||||
if (windowList != null && !windowList.isEmpty()) {
|
||||
throw new RuntimeException("Test FAILED: Window list is not empty: " + windowList.size());
|
||||
if (windowList != null && (windowList.length != 0)) {
|
||||
throw new RuntimeException("Test FAILED: Window list is not empty: " + windowList.length);
|
||||
}
|
||||
|
||||
System.out.println("Test PASSED");
|
||||
|
||||
@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2024, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
import java.util.logging.Logger;
|
||||
import sun.awt.AppContext;
|
||||
import sun.awt.SunToolkit;
|
||||
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8026404
|
||||
* @summary checks that calling getLogger() from a Thread whose ThreadGroup is
|
||||
* a child of the main root group doesn't throw an exception.
|
||||
* @modules java.desktop/sun.awt
|
||||
* java.logging
|
||||
* @build TestMainAppContext
|
||||
* @run main/othervm TestMainAppContext
|
||||
* @author danielfuchs
|
||||
*/
|
||||
public class TestMainAppContext {
|
||||
|
||||
static volatile Throwable thrown = null;
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
ThreadGroup rootTG = Thread.currentThread().getThreadGroup();
|
||||
while (rootTG.getParent() != null) {
|
||||
rootTG = rootTG.getParent();
|
||||
}
|
||||
|
||||
ThreadGroup tg = new ThreadGroup(rootTG, "main");
|
||||
final Thread t1 = new Thread(tg, "child") {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
AppContext context = SunToolkit.createNewAppContext();
|
||||
} catch(Throwable t) {
|
||||
thrown = t;
|
||||
}
|
||||
}
|
||||
};
|
||||
t1.start();
|
||||
t1.join();
|
||||
if (thrown != null) {
|
||||
throw new RuntimeException("Unexpected exception: " + thrown, thrown);
|
||||
}
|
||||
Thread t2 = new Thread(tg, "BugDetector") {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Logger.getLogger("foo").info("Done");
|
||||
} catch (Throwable x) {
|
||||
thrown = x;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
t2.start();
|
||||
t2.join();
|
||||
if (thrown != null) {
|
||||
throw new RuntimeException("Test failed: " + thrown, thrown);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,224 +0,0 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# Copyright (c) 2009, 2020, 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
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
|
||||
#
|
||||
# @test
|
||||
# @bug 6788096
|
||||
# @key intermittent
|
||||
# @summary Test simulates the case of multiple applets executed in
|
||||
# the same VM and verifies that ImageIO shutdown hook
|
||||
# StreamCloser does not cause a leak of classloaders.
|
||||
#
|
||||
# @modules java.desktop/sun.awt
|
||||
# @build test.Main
|
||||
# @build testapp.Main
|
||||
# @run shell run_test.sh
|
||||
|
||||
# There are several resources which need to be present before many
|
||||
# shell scripts can run. Following are examples of how to check for
|
||||
# many common ones.
|
||||
#
|
||||
# Note that the shell used is the Korn Shell, KSH
|
||||
#
|
||||
# Also note, it is recommended that make files NOT be used. Rather,
|
||||
# put the individual commands directly into this file. That way,
|
||||
# it is possible to use command line arguments and other shell tech-
|
||||
# niques to find the compiler, etc on different systems. For example,
|
||||
# a different path could be used depending on whether this were a
|
||||
# Solaris or Win32 machine, which is more difficult (if even possible)
|
||||
# in a make file.
|
||||
|
||||
|
||||
# Beginning of subroutines:
|
||||
status=1
|
||||
|
||||
#Call this from anywhere to fail the test with an error message
|
||||
# usage: fail "reason why the test failed"
|
||||
fail()
|
||||
{ echo "The test failed :-("
|
||||
echo "$*" 1>&2
|
||||
echo "exit status was $status"
|
||||
exit $status
|
||||
} #end of fail()
|
||||
|
||||
#Call this from anywhere to pass the test with a message
|
||||
# usage: pass "reason why the test passed if applicable"
|
||||
pass()
|
||||
{ echo "The test passed!!!"
|
||||
echo "$*" 1>&2
|
||||
exit 0
|
||||
} #end of pass()
|
||||
|
||||
# end of subroutines
|
||||
|
||||
|
||||
# The beginning of the script proper
|
||||
|
||||
# Checking for proper OS
|
||||
OS=`uname -s`
|
||||
case "$OS" in
|
||||
Linux )
|
||||
VAR="A different value for Linux"
|
||||
DEFAULT_JDK=/
|
||||
FILESEP="/"
|
||||
PATHSEP=":"
|
||||
TMP="/tmp"
|
||||
;;
|
||||
|
||||
AIX )
|
||||
VAR="A different value for AIX"
|
||||
DEFAULT_JDK=/
|
||||
FILESEP="/"
|
||||
PATHSEP=":"
|
||||
TMP="/tmp"
|
||||
;;
|
||||
|
||||
Darwin )
|
||||
VAR="A different value for MacOSX"
|
||||
DEFAULT_JDK=/usr
|
||||
FILESEP="/"
|
||||
PATHSEP=":"
|
||||
TMP="/tmp"
|
||||
;;
|
||||
|
||||
Windows* )
|
||||
VAR="A different value for Win32"
|
||||
DEFAULT_JDK="C:/Program Files/Java/jdk1.8.0"
|
||||
FILESEP="\\"
|
||||
PATHSEP=";"
|
||||
TMP=`cd "${SystemRoot}/Temp"; echo ${PWD}`
|
||||
;;
|
||||
|
||||
CYGWIN* )
|
||||
VAR="A different value for Cygwin"
|
||||
DEFAULT_JDK="/cygdrive/c/Program\ Files/Java/jdk1.8.0"
|
||||
FILESEP="/"
|
||||
PATHSEP=";"
|
||||
TMP=`cd "${SystemRoot}/Temp"; echo ${PWD}`
|
||||
;;
|
||||
|
||||
# catch all other OSs
|
||||
* )
|
||||
echo "Unrecognized system! $OS"
|
||||
fail "Unrecognized system! $OS"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Want this test to run standalone as well as in the harness, so do the
|
||||
# following to copy the test's directory into the harness's scratch directory
|
||||
# and set all appropriate variables:
|
||||
|
||||
if [ -z "${TESTJAVA}" ] ; then
|
||||
# TESTJAVA is not set, so the test is running stand-alone.
|
||||
# TESTJAVA holds the path to the root directory of the build of the JDK
|
||||
# to be tested. That is, any java files run explicitly in this shell
|
||||
# should use TESTJAVA in the path to the java interpreter.
|
||||
# So, we'll set this to the JDK spec'd on the command line. If none
|
||||
# is given on the command line, tell the user that and use a cheesy
|
||||
# default.
|
||||
# THIS IS THE JDK BEING TESTED.
|
||||
if [ -n "$1" ] ;
|
||||
then TESTJAVA=$1
|
||||
else echo "no JDK specified on command line so using default!"
|
||||
TESTJAVA=$DEFAULT_JDK
|
||||
fi
|
||||
TESTSRC=.
|
||||
TESTCLASSES=.
|
||||
STANDALONE=1;
|
||||
fi
|
||||
echo "JDK under test is: $TESTJAVA"
|
||||
|
||||
|
||||
############### YOUR TEST CODE HERE!!!!!!! #############
|
||||
|
||||
#All files required for the test should be in the same directory with
|
||||
# this file. If converting a standalone test to run with the harness,
|
||||
# as long as all files are in the same directory and it returns 0 for
|
||||
# pass, you should be able to cut and paste it into here and it will
|
||||
# run with the test harness.
|
||||
|
||||
# This is an example of running something -- test
|
||||
# The stuff below catches the exit status of test then passes or fails
|
||||
# this shell test as appropriate ( 0 status is considered a pass here )
|
||||
|
||||
echo "Create TestApp.jar..."
|
||||
|
||||
if [ -f TestApp.jar ] ; then
|
||||
rm -f TestApp.jar
|
||||
fi
|
||||
|
||||
${TESTJAVA}/bin/jar -cvf TestApp.jar -C ${TESTCLASSES} testapp
|
||||
|
||||
if [ $? -ne "0" ] ; then
|
||||
fail "Failed to create TestApp.jar"
|
||||
fi
|
||||
|
||||
echo "Create Test.jar..."
|
||||
if [ -f Test.jar ] ; then
|
||||
rm -f Test.jar
|
||||
fi
|
||||
|
||||
${TESTJAVA}/bin/jar -cvf Test.jar -C ${TESTCLASSES} test
|
||||
|
||||
if [ $? -ne 0 ] ; then
|
||||
fail "Failed to create Test.jar"
|
||||
fi
|
||||
|
||||
# Prepare temp dir for cahce files
|
||||
mkdir ./tmp
|
||||
if [ $? -ne 0 ] ; then
|
||||
fail "Unable to create temp directory."
|
||||
fi
|
||||
|
||||
# Verify that all classloaders are destroyed
|
||||
${TESTJAVA}/bin/java --add-exports java.desktop/sun.awt=ALL-UNNAMED ${TESTVMOPTS} -cp Test.jar test.Main
|
||||
if [ $? -ne 0 ] ; then
|
||||
fail "Test FAILED: some classloaders weren't destroyed."
|
||||
fi
|
||||
|
||||
|
||||
# Verify that ImageIO shutdown hook works correcly
|
||||
${TESTJAVA}/bin/java --add-exports java.desktop/sun.awt=ALL-UNNAMED ${TESTVMOPTS} \
|
||||
-cp Test.jar -DforgetSomeStreams=true test.Main
|
||||
if [ $? -ne 0 ] ; then
|
||||
fail "Test FAILED: some classloaders weren't destroyed of shutdown hook failed."
|
||||
fi
|
||||
|
||||
# sanity check: verify that all cache files were deleted
|
||||
cache_files=`ls tmp`
|
||||
|
||||
if [ "x${cache_files}" != "x" ] ; then
|
||||
echo "WARNING: some cache files was not deleted: ${cache_files}"
|
||||
fi
|
||||
|
||||
echo "Test done."
|
||||
|
||||
status=$?
|
||||
|
||||
if [ $status -eq "0" ] ; then
|
||||
pass ""
|
||||
else
|
||||
fail "Test failed due to test plugin was not found."
|
||||
fi
|
||||
|
||||
@ -1,284 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import sun.awt.AppContext;
|
||||
import sun.awt.SunToolkit;
|
||||
|
||||
public class Main {
|
||||
|
||||
private static ThreadGroup appsThreadGroup;
|
||||
|
||||
private static WeakHashMap<MyClassLoader, String> refs =
|
||||
new WeakHashMap<MyClassLoader, String>();
|
||||
|
||||
/** Collection to simulate forgrotten streams **/
|
||||
private static HashMap<String, ImageInputStream> strongRefs =
|
||||
new HashMap<String, ImageInputStream>();
|
||||
|
||||
private static ConcurrentLinkedQueue<Throwable> problems =
|
||||
new ConcurrentLinkedQueue<Throwable>();
|
||||
|
||||
private static AppContext mainAppContext = null;
|
||||
|
||||
private static CountDownLatch doneSignal;
|
||||
|
||||
private static final int gcTimeout =
|
||||
Integer.getInteger("gcTimeout", 10).intValue();
|
||||
|
||||
private static boolean forgetSomeStreams =
|
||||
Boolean.getBoolean("forgetSomeStreams");
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
mainAppContext = SunToolkit.createNewAppContext();
|
||||
System.out.println("Current context class loader: " +
|
||||
Thread.currentThread().getContextClassLoader());
|
||||
|
||||
appsThreadGroup = new ThreadGroup("MyAppsThreadGroup");
|
||||
|
||||
File jar = new File("TestApp.jar");
|
||||
if (!jar.exists()) {
|
||||
System.out.println(jar.getAbsolutePath() + " was not found!\n" +
|
||||
"Please install the jar with test application correctly!");
|
||||
throw new RuntimeException("Test failed: no TestApp.jar");
|
||||
}
|
||||
|
||||
URL[] urls = new URL[]{jar.toURL()};
|
||||
|
||||
int numApps = Integer.getInteger("numApps", 20).intValue();
|
||||
|
||||
doneSignal = new CountDownLatch(numApps);
|
||||
int cnt = 0;
|
||||
while (cnt++ < numApps) {
|
||||
launch(urls, "testapp.Main", "launch");
|
||||
|
||||
checkErrors();
|
||||
}
|
||||
|
||||
System.out.println("Wait for apps completion....");
|
||||
|
||||
try {
|
||||
doneSignal.await();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
|
||||
System.out.println("All apps finished.");
|
||||
|
||||
System.gc();
|
||||
|
||||
System.out.flush();
|
||||
|
||||
System.out.println("Enumerate strong refs:");
|
||||
for (String is : strongRefs.keySet()) {
|
||||
System.out.println("-> " + is);
|
||||
}
|
||||
|
||||
System.out.println("=======================");
|
||||
|
||||
// wait few seconds
|
||||
waitAndGC(gcTimeout);
|
||||
|
||||
doneSignal = new CountDownLatch(1);
|
||||
|
||||
Runnable workaround = new Runnable() {
|
||||
|
||||
public void run() {
|
||||
AppContext ctx = null;
|
||||
try {
|
||||
ctx = SunToolkit.createNewAppContext();
|
||||
} catch (Throwable e) {
|
||||
// ignore...
|
||||
} finally {
|
||||
doneSignal.countDown();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Thread wt = new Thread(appsThreadGroup, workaround, "Workaround");
|
||||
wt.setContextClassLoader(new MyClassLoader(urls, "workaround"));
|
||||
wt.start();
|
||||
wt = null;
|
||||
workaround = null;
|
||||
|
||||
System.out.println("Wait for workaround completion...");
|
||||
|
||||
try {
|
||||
doneSignal.await();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
|
||||
// give a chance to GC
|
||||
waitAndGC(gcTimeout);
|
||||
|
||||
if (!refs.isEmpty()) {
|
||||
System.out.println("Classloaders still alive:");
|
||||
|
||||
for (MyClassLoader l : refs.keySet()) {
|
||||
String val = refs.get(l);
|
||||
|
||||
if (val == null) {
|
||||
throw new RuntimeException("Test FAILED: Invalid classloader name");
|
||||
}
|
||||
System.out.println("->" + val + (strongRefs.get(val) != null ?
|
||||
" (has strong ref)" : ""));
|
||||
if (strongRefs.get(val) == null) {
|
||||
throw new RuntimeException("Test FAILED: exta class loader is detected! ");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
System.out.println("No alive class loaders!!");
|
||||
}
|
||||
System.out.println("Test PASSED.");
|
||||
}
|
||||
|
||||
private static void waitAndGC(int sec) {
|
||||
int cnt = sec;
|
||||
System.out.print("Wait ");
|
||||
while (cnt-- > 0) {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
// do GC every 3 seconds
|
||||
if (cnt % 3 == 2) {
|
||||
System.gc();
|
||||
System.out.print("+");
|
||||
} else {
|
||||
System.out.print(".");
|
||||
}
|
||||
checkErrors();
|
||||
}
|
||||
System.out.println("");
|
||||
}
|
||||
|
||||
private static void checkErrors() {
|
||||
while (!problems.isEmpty()) {
|
||||
Throwable theProblem = problems.poll();
|
||||
System.out.println("Test FAILED!");
|
||||
do {
|
||||
theProblem.printStackTrace(System.out);
|
||||
theProblem = theProblem.getCause();
|
||||
} while (theProblem != null);
|
||||
throw new RuntimeException("Test FAILED");
|
||||
}
|
||||
}
|
||||
static int counter = 0;
|
||||
|
||||
private static void launch(URL[] urls, final String className,
|
||||
final String methodName)
|
||||
{
|
||||
final String uniqClassName = "testapp/Uniq" + counter;
|
||||
final boolean saveStrongRef = forgetSomeStreams ? (counter % 5 == 4) : false;
|
||||
|
||||
System.out.printf("%s: launch the app\n", uniqClassName);
|
||||
Runnable launchIt = new Runnable() {
|
||||
public void run() {
|
||||
AppContext ctx = SunToolkit.createNewAppContext();
|
||||
|
||||
try {
|
||||
Class appMain =
|
||||
ctx.getContextClassLoader().loadClass(className);
|
||||
Method launch = appMain.getDeclaredMethod(methodName,
|
||||
strongRefs.getClass());
|
||||
|
||||
Constructor c = appMain.getConstructor(String.class,
|
||||
problems.getClass());
|
||||
|
||||
Object o = c.newInstance(uniqClassName, problems);
|
||||
|
||||
if (saveStrongRef) {
|
||||
System.out.printf("%s: force strong ref\n",
|
||||
uniqClassName);
|
||||
launch.invoke(o, strongRefs);
|
||||
} else {
|
||||
HashMap<String, ImageInputStream> empty = null;
|
||||
launch.invoke(o, empty);
|
||||
}
|
||||
|
||||
ctx = null;
|
||||
} catch (Throwable e) {
|
||||
problems.add(e);
|
||||
} finally {
|
||||
doneSignal.countDown();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MyClassLoader appClassLoader = new MyClassLoader(urls, uniqClassName);
|
||||
|
||||
refs.put(appClassLoader, uniqClassName);
|
||||
|
||||
Thread appThread = new Thread(appsThreadGroup, launchIt,
|
||||
"AppThread" + counter++);
|
||||
appThread.setContextClassLoader(appClassLoader);
|
||||
|
||||
appThread.start();
|
||||
launchIt = null;
|
||||
appThread = null;
|
||||
appClassLoader = null;
|
||||
}
|
||||
|
||||
private static class MyClassLoader extends URLClassLoader {
|
||||
|
||||
private static boolean verbose =
|
||||
Boolean.getBoolean("verboseClassLoading");
|
||||
private String uniqClassName;
|
||||
|
||||
public MyClassLoader(URL[] urls, String uniq) {
|
||||
super(urls);
|
||||
|
||||
uniqClassName = uniq;
|
||||
}
|
||||
|
||||
public Class loadClass(String name) throws ClassNotFoundException {
|
||||
if (verbose) {
|
||||
System.out.printf("%s: load class %s\n", uniqClassName, name);
|
||||
}
|
||||
if (uniqClassName.equals(name)) {
|
||||
return Object.class;
|
||||
}
|
||||
return super.loadClass(name);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "MyClassLoader(" + uniqClassName + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package testapp;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import javax.imageio.stream.FileCacheImageInputStream;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
|
||||
public class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Main o = new Main("testapp.some.class", null);
|
||||
o.launch(null);
|
||||
}
|
||||
|
||||
private final String uniqClassName;
|
||||
private final ConcurrentLinkedQueue<Throwable> problems;
|
||||
|
||||
public Main(String uniq, ConcurrentLinkedQueue<Throwable> p) {
|
||||
uniqClassName = uniq;
|
||||
problems = p;
|
||||
}
|
||||
|
||||
public void launch(HashMap<String, ImageInputStream> refs) {
|
||||
System.out.printf("%s: current context class loader: %s\n",
|
||||
uniqClassName,
|
||||
Thread.currentThread().getContextClassLoader());
|
||||
try {
|
||||
byte[] data = new byte[1024];
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(data);
|
||||
MyImageInputStream iis = new MyImageInputStream(bais,
|
||||
uniqClassName,
|
||||
problems);
|
||||
if (refs != null) {
|
||||
System.out.printf("%s: added to strong store\n",
|
||||
uniqClassName);
|
||||
refs.put(uniqClassName, iis);
|
||||
}
|
||||
iis.read();
|
||||
//leave stream open : let's shutdown hook work!
|
||||
} catch (IOException e) {
|
||||
problems.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyImageInputStream extends FileCacheImageInputStream {
|
||||
private final String uniqClassName;
|
||||
private ConcurrentLinkedQueue<Throwable> problems;
|
||||
public MyImageInputStream(InputStream is, String uniq,
|
||||
ConcurrentLinkedQueue<Throwable> p) throws IOException
|
||||
{
|
||||
super(is, new File("tmp"));
|
||||
uniqClassName = uniq;
|
||||
problems = p;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
Test t = new Test();
|
||||
try {
|
||||
t.doTest(uniqClassName);
|
||||
} catch (Throwable e) {
|
||||
problems.add(e);
|
||||
}
|
||||
|
||||
super.close();
|
||||
|
||||
problems = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Test {
|
||||
public void doTest(String uniqClassName) throws ClassNotFoundException {
|
||||
System.out.printf("%s: Current thread: %s\n", uniqClassName,
|
||||
Thread.currentThread());
|
||||
|
||||
ClassLoader thisCL = this.getClass().getClassLoader();
|
||||
Class uniq = thisCL.loadClass(uniqClassName);
|
||||
|
||||
System.out.printf("%s: test is done!\n",uniqClassName);
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2010, 2026, 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
|
||||
@ -27,12 +27,9 @@
|
||||
* @bug 7004134
|
||||
* @summary JLabel containing a ToolTipText does no longer show ToolTip after browser refresh
|
||||
* @author Pavel Porvatov
|
||||
* @modules java.desktop/sun.awt
|
||||
* @modules java.desktop/javax.swing:open
|
||||
*/
|
||||
|
||||
import sun.awt.SunToolkit;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
@ -45,7 +42,12 @@ public class bug7004134 {
|
||||
|
||||
private static volatile int toolTipWidth;
|
||||
|
||||
private static Robot robot;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
robot = new Robot();
|
||||
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
public void run() {
|
||||
label = new JLabel("A JLabel used as object for an HTML-formatted tooltip");
|
||||
@ -59,7 +61,7 @@ public class bug7004134 {
|
||||
}
|
||||
});
|
||||
|
||||
((SunToolkit) SunToolkit.getDefaultToolkit()).realSync();
|
||||
robot.waitForIdle();
|
||||
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
public void run() {
|
||||
@ -82,7 +84,6 @@ public class bug7004134 {
|
||||
|
||||
Thread thread = new Thread(new ThreadGroup("Some ThreadGroup"), new Runnable() {
|
||||
public void run() {
|
||||
SunToolkit.createNewAppContext();
|
||||
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
@ -96,7 +97,7 @@ public class bug7004134 {
|
||||
}
|
||||
});
|
||||
|
||||
((SunToolkit) SunToolkit.getDefaultToolkit()).realSync();
|
||||
robot.waitForIdle();
|
||||
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
public void run() {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2026, 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
|
||||
@ -29,8 +29,6 @@
|
||||
* @modules java.desktop/sun.awt
|
||||
*/
|
||||
|
||||
import sun.awt.SunToolkit;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.Set;
|
||||
import javax.swing.JSplitPane;
|
||||
@ -60,7 +58,6 @@ public class Test6657026 extends BasicSplitPaneUI implements Runnable {
|
||||
}
|
||||
|
||||
public void run() {
|
||||
SunToolkit.createNewAppContext();
|
||||
if (new JSplitPane().getFocusTraversalKeys(0).isEmpty()) {
|
||||
throw new Error("shared traversal keys");
|
||||
}
|
||||
|
||||
@ -1,229 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2025, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4969419
|
||||
* @summary Tests that generated disabled icons have same look with Ocean
|
||||
* and are updated when theme is switched
|
||||
* @modules java.desktop/sun.awt
|
||||
* @library /java/awt/regtesthelpers
|
||||
* @build PassFailJFrame
|
||||
* @key headful
|
||||
* @run main/manual bug4969419
|
||||
*/
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.FlowLayout;
|
||||
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTabbedPane;
|
||||
import javax.swing.JToggleButton;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
import javax.swing.plaf.metal.DefaultMetalTheme;
|
||||
import javax.swing.plaf.metal.MetalLookAndFeel;
|
||||
import javax.swing.plaf.metal.MetalTheme;
|
||||
|
||||
import sun.awt.AppContext;
|
||||
|
||||
public class bug4969419 {
|
||||
static final String INSTRUCTIONS = """
|
||||
When the test starts you'll see several components with icons.
|
||||
Use the bottom combo box and the "Set" button to switch between
|
||||
the Ocean theme and DefaultMetalTheme.
|
||||
|
||||
1. Set the Ocean theme. Ensure all the icons are the same
|
||||
Note that they all are of the same brightness: none of them
|
||||
can be brighter or darker than the others.
|
||||
|
||||
2. Switch to DefaultMetalTheme. Ensure all the icons changed
|
||||
(became slightly darker).
|
||||
|
||||
3. Switch back to Ocean. Ensure all the icons changed
|
||||
(became brighter).
|
||||
""";
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
|
||||
PassFailJFrame.builder()
|
||||
.title("bug4969419 Test Instructions")
|
||||
.instructions(INSTRUCTIONS)
|
||||
.columns(40)
|
||||
.testUI(bug4969419::createUI)
|
||||
.build()
|
||||
.awaitAndCheck();
|
||||
}
|
||||
|
||||
static JFrame createUI() {
|
||||
JFrame frame = new JFrame("Metal Themes Icon Test");
|
||||
Container pane = frame.getContentPane();
|
||||
|
||||
LFSwitch lfswitch = new LFSwitch(pane);
|
||||
if (!lfswitch.obtainOceanTheme()) {
|
||||
throw new RuntimeException("No Ocean theme available");
|
||||
}
|
||||
|
||||
pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));
|
||||
|
||||
String prefix = System.getProperty("test.src",
|
||||
System.getProperty("user.dir")) + System.getProperty("file.separator");
|
||||
ImageIcon icon = new ImageIcon(prefix + "duke.gif");
|
||||
|
||||
JPanel panel = new JPanel();
|
||||
JButton b = new JButton(icon);
|
||||
b.setEnabled(false);
|
||||
|
||||
JLabel label = new JLabel(icon, SwingConstants.LEFT);
|
||||
label.setEnabled(false);
|
||||
|
||||
JTabbedPane tp = new JTabbedPane();
|
||||
tp.addTab("", icon, new JPanel());
|
||||
tp.addTab("", icon, new JPanel());
|
||||
tp.setEnabledAt(0, false);
|
||||
tp.setEnabledAt(1, false);
|
||||
|
||||
JButton sb = new JButton(icon);
|
||||
sb.setSelectedIcon(icon);
|
||||
sb.setSelected(true);
|
||||
sb.setEnabled(false);
|
||||
|
||||
JToggleButton tb = new JToggleButton(icon);
|
||||
tb.setEnabled(false);
|
||||
|
||||
JToggleButton stb = new JToggleButton(icon);
|
||||
stb.setSelectedIcon(icon);
|
||||
stb.setSelected(true);
|
||||
stb.setEnabled(false);
|
||||
|
||||
pane.setBackground(Color.white);
|
||||
panel.setBackground(Color.white);
|
||||
b.setBackground(Color.white);
|
||||
label.setBackground(Color.white);
|
||||
tp.setBackground(Color.white);
|
||||
sb.setBackground(Color.white);
|
||||
tb.setBackground(Color.white);
|
||||
stb.setBackground(Color.white);
|
||||
|
||||
panel.add(b);
|
||||
panel.add(label);
|
||||
panel.add(tp);
|
||||
panel.add(sb);
|
||||
panel.add(tb);
|
||||
panel.add(stb);
|
||||
|
||||
pane.add(panel);
|
||||
pane.add(lfswitch);
|
||||
frame.setSize(400, 400);
|
||||
return frame;
|
||||
}
|
||||
|
||||
static class LFSwitch extends JPanel {
|
||||
private Component target;
|
||||
static MetalTheme oceanTheme;
|
||||
JComboBox lfcombo;
|
||||
|
||||
public LFSwitch(Component target) {
|
||||
this.target = target;
|
||||
setLayout(new FlowLayout());
|
||||
lfcombo = new JComboBox(lookAndFeels);
|
||||
add(lfcombo);
|
||||
JButton setLfBut = new JButton("Set");
|
||||
add(setLfBut);
|
||||
setLfBut.addActionListener(e -> setLf(lfcombo.getSelectedIndex(),
|
||||
LFSwitch.this.target));
|
||||
}
|
||||
|
||||
boolean obtainOceanTheme() {
|
||||
if (oceanTheme != null) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
|
||||
SwingUtilities.updateComponentTreeUI(this);
|
||||
} catch (Exception e) {
|
||||
JOptionPane.showMessageDialog(this,
|
||||
"Unexpected error: couldn't set Metal", "Error",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
return false;
|
||||
}
|
||||
MetalTheme theme = (MetalTheme) AppContext.getAppContext().
|
||||
get("currentMetalTheme");
|
||||
if (theme == null || theme.getName() != "Ocean") {
|
||||
JOptionPane.showMessageDialog(this,
|
||||
"The Ocean theme is not the default Metal theme,\n" +
|
||||
"but this test requires it to be default.\n" +
|
||||
"Therefore simply click PASS");
|
||||
return false;
|
||||
}
|
||||
oceanTheme = theme;
|
||||
return true;
|
||||
}
|
||||
|
||||
void setLf(int idx, final Component root) {
|
||||
try {
|
||||
UIManager.setLookAndFeel((LookAndFeel) lfs[idx]);
|
||||
if (root != null) {
|
||||
SwingUtilities.updateComponentTreeUI(root);
|
||||
}
|
||||
} catch (UnsupportedLookAndFeelException e) {
|
||||
JOptionPane.showMessageDialog(root,
|
||||
"The selected look and feel is unsupported on this platform",
|
||||
"Error", JOptionPane.ERROR_MESSAGE);
|
||||
} catch (Exception exc) {
|
||||
JOptionPane.showMessageDialog(root,
|
||||
"Error setting the selected look and feel", "Error",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
static Object[] lookAndFeels = {
|
||||
"Metal (Ocean)", "Metal (DefaultMetalTheme)",
|
||||
};
|
||||
static Object[] lfs = {
|
||||
new MetalLookAndFeel() {
|
||||
protected void createDefaultTheme() {
|
||||
setCurrentTheme(oceanTheme);
|
||||
}
|
||||
},
|
||||
new MetalLookAndFeel() {
|
||||
protected void createDefaultTheme() {
|
||||
MetalTheme dt = new DefaultMetalTheme();
|
||||
setCurrentTheme(dt);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2010, 2026, 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
|
||||
@ -25,9 +25,7 @@
|
||||
@bug 6990651
|
||||
@summary Regression: NPE when refreshing embedded window since 6u22-b01
|
||||
@author Pavel Porvatov
|
||||
@modules java.desktop/sun.awt
|
||||
*/
|
||||
import sun.awt.SunToolkit;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
@ -43,7 +41,6 @@ public class bug6990651 {
|
||||
|
||||
Thread thread = new Thread(new ThreadGroup("Some ThreadGroup"), new Runnable() {
|
||||
public void run() {
|
||||
SunToolkit.createNewAppContext();
|
||||
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
|
||||
@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2015, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8019623
|
||||
* @summary Tests that AppContext.getAppContext() works correctly in multi-threads scenario.
|
||||
* @author Leonid Romanov
|
||||
* @modules java.desktop/sun.awt
|
||||
*/
|
||||
|
||||
import sun.awt.AppContext;
|
||||
|
||||
public class MultiThreadTest {
|
||||
private static final int NUM_THREADS = 2;
|
||||
|
||||
private static AppContextGetter[] getters = new AppContextGetter[NUM_THREADS];
|
||||
|
||||
public static void main(String[] args) {
|
||||
createAndStartThreads();
|
||||
compareAppContexts();
|
||||
}
|
||||
|
||||
private static void createAndStartThreads() {
|
||||
ThreadGroup systemGroup = getSystemThreadGroup();
|
||||
for (int i = 0; i < NUM_THREADS; ++i) {
|
||||
ThreadGroup tg = new ThreadGroup(systemGroup, "AppContextGetter" + i);
|
||||
getters[i] = new AppContextGetter(tg);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_THREADS; ++i) {
|
||||
getters[i].start();
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_THREADS; ++i) {
|
||||
try {
|
||||
getters[i].join();
|
||||
} catch (InterruptedException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static ThreadGroup getSystemThreadGroup() {
|
||||
ThreadGroup currentThreadGroup =
|
||||
Thread.currentThread().getThreadGroup();
|
||||
ThreadGroup parentThreadGroup = currentThreadGroup.getParent();
|
||||
while (parentThreadGroup != null) {
|
||||
currentThreadGroup = parentThreadGroup;
|
||||
parentThreadGroup = currentThreadGroup.getParent();
|
||||
}
|
||||
|
||||
return currentThreadGroup;
|
||||
}
|
||||
|
||||
private static void compareAppContexts() {
|
||||
AppContext ctx = getters[0].getAppContext();
|
||||
for (int i = 1; i < NUM_THREADS; ++i) {
|
||||
if (!ctx.equals(getters[i].getAppContext())) {
|
||||
throw new RuntimeException("Unexpected AppContexts difference, could be a race condition");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class AppContextGetter extends Thread {
|
||||
private AppContext appContext;
|
||||
|
||||
public AppContextGetter(ThreadGroup tg) {
|
||||
super(tg, tg.getName());
|
||||
}
|
||||
|
||||
AppContext getAppContext() {
|
||||
return appContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
appContext = AppContext.getAppContext();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2010, 2026, 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
|
||||
@ -30,6 +30,7 @@
|
||||
* @run main/othervm ClassLoaderLeakTest FontManagerTest
|
||||
*/
|
||||
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics;
|
||||
import java.io.File;
|
||||
@ -48,6 +49,7 @@ public class ClassLoaderLeakTest {
|
||||
private static Throwable launchFailure = null;
|
||||
|
||||
public static void main(String[] args) {
|
||||
Toolkit.getDefaultToolkit().getSystemEventQueue(); // load EQ in initial TG
|
||||
doneSignal = new CountDownLatch(1);
|
||||
launchSignal = new CountDownLatch(1);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user