/*
 * Copyright (c) 2007, 2011, 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(new Locale("en", "US"));
        try {
            final Locale loc = new Locale("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", new Locale("fr", "FR"));
     *      -->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", new Locale("fr", "FR"));
     *      -->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", new Locale("fr", "FR"));
     *      -->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", new Locale("fr", "FR"));
     *      -->find cached Bug4168625Resource_fr_FR
     *      -->return Bug4168625Resource_en_US (which is realy Bug4168625Resource)
     *  </pre>
     *  <P>
     *
     */
    public void testCacheFailures() throws Exception {
        checkResourceLoading("Bug4168625Resource", new Locale("fr", "FR"));
    }

    /**
     *  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", new Locale("en", "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", new Locale("en", "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, new Locale("en", "CA"));
        ConcurrentLoadingThread thread2 = new ConcurrentLoadingThread(loader, test, new Locale("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, new Locale("en", "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) {
                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);
                    }
                }
            }
            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", new Locale("sp"));
     *      A-->load Bug4168625Resource_sp
     *      A-->find cached Bug4168625Resource
     *      A-->cache Bug4168625Resource_sp as Bug4168625Resource_sp
     *  ThreadB.getBundle("Bug4168625Resource", new Locale("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.
     */
}
