/*
 * Copyright (c) 1998, 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.  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 jdk.internal.access.JavaAWTAccess;
import jdk.internal.access.SharedSecrets;
import sun.util.logging.PlatformLogger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;

/**
 * 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 applet 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 applets and other 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 a malicious applet
 * 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 applet will be able to
 * listen to are its own.  A more reasonable applet request would be to
 * change the Swing default look-and-feel; with that default stored in
 * an AppContext, the applet's look-and-feel will change without
 * disrupting other applets or potentially the browser itself.<p>
 *
 * Because the AppContext is a facility for safely extending application
 * service support to applets, none of its methods may be blocked by a
 * a SecurityManager check in a valid Java implementation.  Applets may
 * therefore safely invoke any of its methods without worry of being
 * blocked.
 *
 * @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. */

    /*
     * The key to put()/get() the Java EventQueue into/from the AppContext.
     */
    public static final Object EVENT_QUEUE_KEY = new StringBuffer("EventQueue");

    /*
     * The keys to store EventQueue push/pop lock and condition.
     */
    public static final Object EVENT_QUEUE_LOCK_KEY = new StringBuilder("EventQueue.Lock");
    public static final Object EVENT_QUEUE_COND_KEY = new StringBuilder("EventQueue.Condition");

    /* 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 (i.e. not applets)
     */
    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();
        // Initialize push/pop lock and its condition to be used by all the
        // EventQueues within this AppContext
        Lock eventQueuePushPopLock = new ReentrantLock();
        put(EVENT_QUEUE_LOCK_KEY, eventQueuePushPopLock);
        Condition eventQueuePushPopCond = eventQueuePushPopLock.newCondition();
        put(EVENT_QUEUE_COND_KEY, eventQueuePushPopCond);
    }

    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. This covers standalone apps
            // and excludes applets because by the time applet starts
            // a number of contexts have already been created by the plugin.
            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;
    }

    static final class PostShutdownEventRunnable implements Runnable {
        private final AppContext appContext;

        PostShutdownEventRunnable(AppContext ac) {
            appContext = ac;
        }

        public void run() {
            final EventQueue eq = (EventQueue)appContext.get(EVENT_QUEUE_KEY);
            if (eq != null) {
                eq.postEvent(AWTAutoShutdown.getShutdownEvent());
            }
        }
    }

    static void stopEventDispatchThreads() {
        for (AppContext appContext: getAppContexts()) {
            if (appContext.isDisposed()) {
                continue;
            }
            Runnable r = new PostShutdownEventRunnable(appContext);
            // For security reasons EventQueue.postEvent should only be called
            // on a thread that belongs to the corresponding thread group.
            if (appContext != AppContext.getAppContext()) {
                // Create a thread that belongs to the thread group associated
                // with the AppContext and invokes EventQueue.postEvent.
                Thread thread = new Thread(appContext.getThreadGroup(),
                                           r, "AppContext Disposer", 0, false);
                thread.setContextClassLoader(appContext.getContextClassLoader());
                thread.setPriority(Thread.NORM_PRIORITY + 1);
                thread.setDaemon(true);
                thread.start();
            } else {
                r.run();
            }
        }
    }

    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);
    }

    // Set up JavaAWTAccess in SharedSecrets
    static {
        SharedSecrets.setJavaAWTAccess(new JavaAWTAccess() {
            private boolean hasRootThreadGroup(final AppContext ecx) {
                return ecx.threadGroup.getParent() == null;
            }

            /**
             * Returns the AppContext used for applet logging isolation, or null if
             * the default global context can be used.
             * If there's no applet, or if the caller is a stand alone application,
             * or running in the main app context, returns null.
             * Otherwise, returns the AppContext of the calling applet.
             * @return null if the global default context can be used,
             *         an AppContext otherwise.
             **/
            public Object getAppletContext() {
                // There's no AppContext: return null.
                // No need to call getAppContext() if numAppContext == 0:
                // it means that no AppContext has been created yet, and
                // we don't want to trigger the creation of a main app
                // context since we don't need it.
                if (numAppContexts.get() == 0) return null;

                AppContext ecx = null;

                // Not sure we really need to re-check numAppContexts here.
                // If all applets have gone away then we could have a
                // numAppContexts coming back to 0. So we recheck
                // it here because we don't want to trigger the
                // creation of a main AppContext in that case.
                // This is probably not 100% MT-safe but should reduce
                // the window of opportunity in which that issue could
                // happen.
                if (numAppContexts.get() > 0) {
                    // Defaults to thread group caching.
                    // This is probably not required as we only really need
                    // isolation in a deployed applet environment, in which
                    // case ecx will not be null when we reach here
                    // However it helps emulate the deployed environment,
                    // in tests for instance.
                    ecx = ecx != null ? ecx : getAppContext();
                }

                // getAppletContext() may be called when initializing the main
                // app context - in which case mainAppContext will still be
                // null. To work around this issue we simply use
                // AppContext.threadGroup.getParent() == null instead, since
                // mainAppContext is the only AppContext which should have
                // the root TG as its thread group.
                // See: JDK-8023258
                final boolean isMainAppContext = ecx == null
                        || mainAppContext == ecx
                        || mainAppContext == null && hasRootThreadGroup(ecx);

                return isMainAppContext ? null : ecx;
            }

        });
    }

    public static <T> T getSoftReferenceValue(Object key,
            Supplier<T> supplier) {

        final AppContext appContext = AppContext.getAppContext();
        @SuppressWarnings("unchecked")
        SoftReference<T> ref = (SoftReference<T>) appContext.get(key);
        if (ref != null) {
            final T object = ref.get();
            if (object != null) {
                return object;
            }
        }
        final T object = supplier.get();
        ref = new SoftReference<>(object);
        appContext.put(key, ref);
        return object;
    }
}

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;
    }
}
