/*
 * Copyright (c) 2007, 2022, 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
    @summary test Resource Bundle for bug 4168625
    @build Bug4168625Class Bug4168625Getter Bug4168625Resource Bug4168625Resource3 Bug4168625Resource3_en Bug4168625Resource3_en_CA Bug4168625Resource3_en_IE Bug4168625Resource3_en_US Bug4168625Resource2_en_US Bug4168625Resource2
    @run main/timeout=600 Bug4168625Test
    @bug 4168625 6993339
*/
/*
 *
 *
 * (C) Copyright IBM Corp. 1999 - All Rights Reserved
 *
 * The original version of this source code and documentation is
 * copyrighted and owned by IBM. These materials are provided
 * under terms of a License Agreement between IBM and Sun.
 * This technology is protected by multiple US and International
 * patents. This notice and attribution to IBM may not be removed.
 *
 */

import java.util.*;
import java.io.*;

/**
 *  This test tries to correct two efficiency problems with the caching
 *  mechanism of ResourceBundle.  It also allows concurrent loads
 *  of resource bundles to be performed if the bundles are unrelated (ex. a
 *  load of a local system resource by one thread while another thread is
 *  doing a slow load over a network).
 */
public class Bug4168625Test extends RBTestFmwk {
    public static void main(String[] args) throws Exception {
        new Bug4168625Test().run(args);
    }

    /**
     * Verify that getBundle will do something reasonable when part of the
     * resource hierarchy is missing.
     */
    public void testMissingParent() throws Exception {
        final Locale oldDefault = Locale.getDefault();
        Locale.setDefault(Locale.US);
        try {
            final Locale loc = Locale.of("jf", "jf");
            ResourceBundle bundle = ResourceBundle.getBundle("Bug4168625Resource2", loc);
            final String s1 = bundle.getString("name");
            if (!s1.equals("Bug4168625Resource2_en_US")) {
                errln("getBundle did not find leaf bundle: "+bundle.getClass().getName());
            }
            final String s2 = bundle.getString("baseName");
            if (!s2.equals("Bug4168625Resource2")) {
                errln("getBundle did not set up proper inheritance chain");
            }
        } finally {
            Locale.setDefault(oldDefault);
        }
    }

    /**
     *  Previous versions of ResourceBundle have had the following
     *  caching behavior.  Assume the classes
     *  Bug4168625Resource_fr_FR, Bug4168625Resource_fr,
     *  Bug4168625Resource_en_US, and Bug4168625Resource_en don't
     *  exist.  The class Bug4168625Resource does.  Assume the default
     *  locale is en_US.
     *  <P>
     *  <pre>
     *  getBundle("Bug4168625Resource", Locale.FRANCE);
     *      -->try to load Bug4168625Resource_fr_FR
     *      -->try to load Bug4168625Resource_fr
     *      -->try to load Bug4168625Resource_en_US
     *      -->try to load Bug4168625Resource_en
     *      -->load Bug4168625Resource
     *      -->cache Bug4168625Resource as Bug4168625Resource
     *      -->cache Bug4168625Resource as Bug4168625Resource_en
     *      -->cache Bug4168625Resource as Bug4168625Resource_en_US
     *      -->return Bug4168625Resource
     *  getBundle("Bug4168625Resource", Locale.FRANCE);
     *      -->try to load Bug4168625Resource_fr_FR
     *      -->try to load Bug4168625Resource_fr
     *      -->find cached Bug4168625Resource_en_US
     *      -->return Bug4168625Resource_en_US (which is realy Bug4168625Resource)
     *  </pre>
     *  <P>
     *  The second call causes two loads for Bug4168625Resource_fr_FR and
     *  Bug4168625Resource_en which have already been tried and failed.  These
     *  two loads should have been cached as Bug4168625Resource by the first
     *  call.
     *
     *  The following, more efficient behavior is desired:
     *  <P>
     *  <pre>
     *  getBundle("Bug4168625Resource", Locale.FRANCE);
     *      -->try to load Bug4168625Resource_fr_FR
     *      -->try to load Bug4168625Resource_fr
     *      -->try to load Bug4168625Resource_en_US
     *      -->try to load Bug4168625Resource_en
     *      -->load Bug4168625Resource
     *      -->cache Bug4168625Resource as Bug4168625Resource
     *      -->cache Bug4168625Resource as Bug4168625Resource_en
     *      -->cache Bug4168625Resource as Bug4168625Resource_en_US
     *      -->cache Bug4168625Resource as Bug4168625Resource_fr
     *      -->cache Bug4168625Resource as Bug4168625Resource_fr_FR
     *      -->return Bug4168625Resource
     *  getBundle("Bug4168625Resource", Locale.FRANCE);
     *      -->find cached Bug4168625Resource_fr_FR
     *      -->return Bug4168625Resource_en_US (which is realy Bug4168625Resource)
     *  </pre>
     *  <P>
     *
     */
    public void testCacheFailures() throws Exception {
        checkResourceLoading("Bug4168625Resource", Locale.FRANCE);
    }

    /**
     *  Previous versions of ResourceBundle have had the following
     *  caching behavior.  Assume the current locale is locale is en_US.
     *  The classes Bug4168625Resource_en_US, and Bug4168625Resource_en don't
     *  exist.  The class Bug4168625Resource does.
     *  <P>
     *  <pre>
     *  getBundle("Bug4168625Resource", Locale.US);
     *      -->try to load Bug4168625Resource_en_US
     *      -->try to load Bug4168625Resource_en
     *      -->try to load Bug4168625Resource_en_US
     *      -->try to load Bug4168625Resource_en
     *      -->load Bug4168625Resource
     *      -->cache Bug4168625Resource as Bug4168625Resource
     *      -->cache Bug4168625Resource as Bug4168625Resource_en
     *      -->cache Bug4168625Resource as Bug4168625Resource_en_US
     *      -->return Bug4168625Resource
     *  </pre>
     *  <P>
     *  The redundant loads of Bug4168625Resource_en_US and Bug4168625Resource_en
     *  should not occur.  The desired behavior is as follows:
     *  <P>
     *  <pre>
     *  getBundle("Bug4168625Resource", Locale.US);
     *      -->try to load Bug4168625Resource_en_US
     *      -->try to load Bug4168625Resource_en
     *      -->load Bug4168625Resource
     *      -->cache Bug4168625Resource as Bug4168625Resource
     *      -->cache Bug4168625Resource as Bug4168625Resource_en
     *      -->cache Bug4168625Resource as Bug4168625Resource_en_US
     *      -->return Bug4168625Resource
     *  </pre>
     *  <P>
     */
    public void testRedundantLoads() throws Exception {
        checkResourceLoading("Bug4168625Resource", Locale.getDefault());
    }

    /**
     * Ensure that resources are only loaded once and are cached correctly
     */
    private void checkResourceLoading(String resName, Locale l) throws Exception {
        final Loader loader = new Loader( new String[] { "Bug4168625Class" }, new String[] { "Bug4168625Resource3_en_US", "Bug4168625Resource3_en_CA" });
        final Class c = loader.loadClass("Bug4168625Class");
        Bug4168625Getter test = (Bug4168625Getter)c.newInstance();
        final String resClassName;
        if (l.toString().length() > 0) {
            resClassName = resName+"_"+l;
        } else {
            resClassName = resName;
        }

        Object bundle = test.getResourceBundle(resName, l);
        loader.logClasses("Initial lookup of "+resClassName+" generated the following loads:");

        final Vector lastLoad = new Vector(loader.loadedClasses.size());
        boolean dups = false;
        for (int i = loader.loadedClasses.size() - 1; i >= 0 ; i--) {
            final Object item = loader.loadedClasses.elementAt(i);
            loader.loadedClasses.removeElementAt(i);
            if (loader.loadedClasses.contains(item)) {
                logln("Resource loaded more than once: "+item);
                dups = true;
            } else {
                lastLoad.addElement(item);
            }
        }
        if (dups) {
            errln("ResourceBundle loaded some classes multiple times");
        }

        loader.loadedClasses.removeAllElements();
        bundle = test.getResourceBundle(resName, l);
        loader.logClasses("Second lookup of "+resClassName+" generated the following loads:");

        dups = false;
        for (int i = 0; i < loader.loadedClasses.size(); i++) {
            Object item = loader.loadedClasses.elementAt(i);
            if (lastLoad.contains(item)) {
                logln("ResourceBundle did not cache "+item+" correctly");
                dups = true;
            }
        }
        if (dups) {
            errln("Resource bundle not caching some classes properly");
        }
    }

    private class ConcurrentLoadingThread extends Thread {
        private Loader loader;
        public Object bundle;
        private Bug4168625Getter test;
        private Locale locale;
        private String resourceName = "Bug4168625Resource3";
        public ConcurrentLoadingThread(Loader loader, Bug4168625Getter test, Locale l, String resourceName) {
            this.loader = loader;
            this.test = test;
            this.locale = l;
            this.resourceName = resourceName;
        }
        public ConcurrentLoadingThread(Loader loader, Bug4168625Getter test, Locale l) {
            this.loader = loader;
            this.test = test;
            this.locale = l;
        }
        public void run() {
            try {
                logln(">>"+threadName()+">run");
                bundle = test.getResourceBundle(resourceName, locale);
            } catch (Exception e) {
                errln("TEST CAUGHT UNEXPECTED EXCEPTION: "+e);
            } finally {
                logln("<<"+threadName()+"<run");
            }
        }
        public synchronized void waitUntilPinged() {
            logln(">>"+threadName()+">waitUntilPinged");
            loader.notifyEveryone();
            try {
                wait(30000);    //wait 30 seconds max.
            } catch (InterruptedException e) {
                logln("Test deadlocked.");
            }
            logln("<<"+threadName()+"<waitUntilPinged");
        }
        public synchronized void ping() {
            logln(">>"+threadName()+">ping "+threadName(this));
            notifyAll();
            logln("<<"+threadName()+"<ping "+threadName(this));
        }
    };

    /**
     * This test ensures that multiple resources can be loading at the same
     * time as long as they don't depend on each other in some way.
     */
    public void testConcurrentLoading() throws Exception {
        final Loader loader = new Loader( new String[] { "Bug4168625Class" }, new String[] { "Bug4168625Resource3_en_US", "Bug4168625Resource3_en_CA" });
        final Class c = loader.loadClass("Bug4168625Class");
        final Bug4168625Getter test = (Bug4168625Getter)c.newInstance();

        ConcurrentLoadingThread thread1 = new ConcurrentLoadingThread(loader, test, Locale.of("en", "CA"));
        ConcurrentLoadingThread thread2 = new ConcurrentLoadingThread(loader, test, Locale.of("en", "IE"));

        thread1.start();            //start thread 1
        loader.waitForNotify(1);    //wait for thread1 to do getBundle & block in loader
        thread2.start();            //start second thread
        thread2.join();             //wait until thread2 terminates.

            //Thread1 should be blocked inside getBundle at the class loader
            //Thread2 should have completed its getBundle call and terminated
        if (!thread1.isAlive() || thread2.isAlive()) {
            errln("ResourceBundle.getBundle not allowing legal concurrent loads");
        }

        thread1.ping();             //continue thread1
        thread1.join();
    }

    /**
     * This test ensures that a resource loads correctly (with all its parents)
     * when memory is very low (ex. the cache gets purged during a load).
     */
    public void testLowMemoryLoad() throws Exception {
        final String[] classToLoad = { "Bug4168625Class" };
        final String[] classToWait = { "Bug4168625Resource3_en_US","Bug4168625Resource3_en","Bug4168625Resource3" };
        final Loader loader = new Loader(classToLoad, classToWait);
        final Class c = loader.loadClass("Bug4168625Class");
        final Bug4168625Getter test = (Bug4168625Getter)c.newInstance();
        causeResourceBundleCacheFlush();

        ConcurrentLoadingThread thread1 = new ConcurrentLoadingThread(loader, test, Locale.US);
        thread1.start();            //start thread 1
        loader.waitForNotify(1);    //wait for thread1 to do getBundle(en_US) & block in loader
        causeResourceBundleCacheFlush();    //cause a cache flush
        thread1.ping();             //kick thread 1
        loader.waitForNotify(2);    //wait for thread1 to do getBundle(en) & block in loader
        causeResourceBundleCacheFlush();    //cause a cache flush
        thread1.ping();             //kick thread 1
        loader.waitForNotify(3);    //wait for thread1 to do getBundle(en) & block in loader
        causeResourceBundleCacheFlush();    //cause a cache flush
        thread1.ping();             //kick thread 1
        thread1.join();             //wait until thread1 terminates

        ResourceBundle bundle = (ResourceBundle)thread1.bundle;
        String s1 = bundle.getString("Bug4168625Resource3_en_US");
        String s2 = bundle.getString("Bug4168625Resource3_en");
        String s3 = bundle.getString("Bug4168625Resource3");
        if ((s1 == null) || (s2 == null) || (s3 == null)) {
            errln("Bundle not constructed correctly.  The parent chain is incorrect.");
        }
    }

    /**
     * A simple class loader that loads classes from the current
     * working directory.  The loader will block the current thread
     * of execution before it returns when it tries to load
     * the class "Bug4168625Resource3_en_US".
     */
    private static final String CLASS_PREFIX = "";
    private static final String CLASS_SUFFIX = ".class";

    private static final class SimpleLoader extends ClassLoader {
        private boolean network = false;

        public SimpleLoader() {
            super(SimpleLoader.class.getClassLoader());
            this.network = false;
        }
        public SimpleLoader(boolean simulateNetworkLoad) {
            super(SimpleLoader.class.getClassLoader());
            this.network = simulateNetworkLoad;
        }
        public Class loadClass(final String className, final boolean resolveIt)
                throws ClassNotFoundException {
            Class result;
            synchronized (this) {
                result = findLoadedClass(className);
                if (result == null) {
                    if (network) {
                        try {
                             Thread.sleep(100);
                        } catch (java.lang.InterruptedException e) {
                        }
                    }
                    result = getParent().loadClass(className);
                    if ((result != null) && resolveIt) {
                        resolveClass(result);
                    }
                }
            }
            return result;
        }
    }

    private final class Loader extends ClassLoader {
        public final Vector loadedClasses = new Vector();
        private String[] classesToLoad;
        private String[] classesToWaitFor;

        public Loader() {
            super(Loader.class.getClassLoader());
            classesToLoad = new String[0];
            classesToWaitFor = new String[0];
        }

        public Loader(final String[] classesToLoadIn, final String[] classesToWaitForIn) {
            super(Loader.class.getClassLoader());
            classesToLoad = classesToLoadIn;
            classesToWaitFor = classesToWaitForIn;
        }

        /**
         * Load a class.  Files we can load take preference over ones the system
         * can load.
         */
        private byte[] getClassData(final String className) {
            boolean shouldLoad = false;
            for (int i = classesToLoad.length-1; i >= 0; --i) {
                if (className.equals(classesToLoad[i])) {
                    shouldLoad = true;
                    break;
                }
            }

            if (shouldLoad) {
                final String name = CLASS_PREFIX+className+CLASS_SUFFIX;
                try {
                    final InputStream fi = this.getClass().getClassLoader().getResourceAsStream(name);
                    final byte[] result = new byte[fi.available()];
                    fi.read(result);
                    return result;
                } catch (Exception e) {
                    logln("Error loading test class: "+name);
                    logln(e.toString());
                    return null;
                }
            } else {
                return null;
            }
        }

        /**
         * Load a class.  Files we can load take preference over ones the system
         * can load.
         */
        public Class loadClass(final String className, final boolean resolveIt)
                throws ClassNotFoundException {
            Class result;
            synchronized (this) {
                try {
                    logln(">>"+threadName()+">load "+className);
                    loadedClasses.addElement(className);

                    result = findLoadedClass(className);
                    if (result == null) {
                        final byte[] classData = getClassData(className);
                        if (classData == null) {
                            //we don't have a local copy of this one
                            logln("Loading system class: "+className);
                            result = loadFromSystem(className);
                        } else {
                            result = defineClass(classData, 0, classData.length);
                            if (result == null) {
                                //there was an error defining the class
                                result = loadFromSystem(className);
                            }
                        }
                        if ((result != null) && resolveIt) {
                            resolveClass(result);
                        }
                    }
                } catch (ClassNotFoundException e) {
                    // Ignore loading of Bug4168625ResourceProvider
                    if (className.equals("Bug4168625ResourceProvider")) {
                        logln("Ignoring " + className);
                        loadedClasses.remove(className);
                        return null;
                    }
                    throw e;
                }
            }
            for (int i = classesToWaitFor.length-1; i >= 0; --i) {
                if (className.equals(classesToWaitFor[i])) {
                    rendezvous();
                    break;
                }
            }
            logln("<<"+threadName()+"<load "+className);
            return result;
        }

        /**
         * Delegate loading to its parent class loader that loads the test classes.
         * In othervm mode, the parent class loader is the system class loader;
         * in samevm mode, the parent class loader is the jtreg URLClassLoader.
         */
        private Class loadFromSystem(String className) throws ClassNotFoundException {
            return getParent().loadClass(className);
        }

        public void logClasses(String title) {
            logln(title);
            for (int i = 0; i < loadedClasses.size(); i++) {
                logln("    "+loadedClasses.elementAt(i));
            }
            logln("");
        }

        public int notifyCount = 0;
        public int waitForNotify(int count) {
            return waitForNotify(count, 0);
        }
        public synchronized int waitForNotify(int count, long time) {
            logln(">>"+threadName()+">waitForNotify");
            if (count > notifyCount) {
                try {
                    wait(time);
                } catch (InterruptedException e) {
                }
            } else {
                logln("  count("+count+") > notifyCount("+notifyCount+")");
            }
            logln("<<"+threadName()+"<waitForNotify");
            return notifyCount;
        }
        private synchronized void notifyEveryone() {
            logln(">>"+threadName()+">notifyEveryone");
            notifyCount++;
            notifyAll();
            logln("<<"+threadName()+"<notifyEveryone");
        }
        private void rendezvous() {
            final Thread current = Thread.currentThread();
            if (current instanceof ConcurrentLoadingThread) {
                ((ConcurrentLoadingThread)current).waitUntilPinged();
            }
        }
    }

    private static String threadName() {
        return threadName(Thread.currentThread());
    }

    private static String threadName(Thread t) {
        String temp = t.toString();
        int ndx = temp.indexOf("Thread[");
        temp = temp.substring(ndx + "Thread[".length());
        ndx = temp.indexOf(',');
        temp = temp.substring(0, ndx);
        return temp;
    }

    /** Fill memory to force all SoftReferences to be GCed */
    private void causeResourceBundleCacheFlush() {
        logln("Filling memory...");
        int allocationSize = 1024;
        Vector memoryHog = new Vector();
        try {
            while (true) {
                memoryHog.addElement(new byte[allocationSize]);
                allocationSize *= 2;
            }
        } catch (Throwable e) {
            logln("Caught "+e+" filling memory");
        } finally{
            memoryHog = null;
            System.gc();
        }
        logln("last allocation size: " + allocationSize);
    }

    /**
     *  NOTE: this problem is not externally testable and can only be
     *  verified through code inspection unless special code to force
     *  a task switch is inserted into ResourceBundle.
     *  The class Bug4168625Resource_sp exists.  It's parent bundle
     *  (Bug4168625Resource) contains a resource string with the tag
     *  "language" but Bug4168625Resource_sp does not.
     *  Assume two threads are executing, ThreadA and ThreadB and they both
     *  load a resource Bug4168625Resource with from sp locale.
     *  ResourceBundle.getBundle adds a bundle to the bundle cache (in
     *  findBundle) before it sets the bundle's parent (in getBundle after
     *  returning from findBundle).
     *  <P>
     *  <pre>
     *  ThreadA.getBundle("Bug4168625Resource", Locale.of("sp"));
     *      A-->load Bug4168625Resource_sp
     *      A-->find cached Bug4168625Resource
     *      A-->cache Bug4168625Resource_sp as Bug4168625Resource_sp
     *  ThreadB.getBundle("Bug4168625Resource", Locale.of("sp"));
     *      B-->find cached Bug4168625Resource_sp
     *      B-->return Bug4168625Resource_sp
     *  ThreadB.bundle.getString("language");
     *      B-->try to find "language" in Bug4168625Resource_sp
     *      B-->Bug4168625Resource_sp does not have a parent, so return null;
     *  ThreadB.System.out.println("Some unknown country");
     *      A-->set parent of Bug4168625Resource_sp to Bug4168625Resource
     *      A-->return Bug4168625Resource_sp (the same bundle ThreadB got)
     *  ThreadA.bundle.getString("language");
     *      A-->try to find "language" in Bug4168625Resource_sp
     *      A-->try to find "language" in Bug4168625Resource (parent of Bug4168625Resource_sp)
     *      A-->return the string
     *  ThreadA.System.out.println("Langauge = "+country);
     *  ThreadB.bundle.getString("language");
     *      B-->try to find "language" in Bug4168625Resource_sp
     *      B-->try to find "language" in Bug4168625Resource (parent of Bug4168625Resource_sp)
     *      B-->return the string
     *  ThreadB.System.out.println("Langauge = "+country);
     *  </pre>
     *  <P>
     *  Note that the first call to getString() by ThreadB returns null, but the second
     *  returns a value.  Thus to ThreadB, the bundle appears to change.  ThreadA gets
     *  the expected results right away.
     */
}
