/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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
@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.
*
*/
/**
* 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).
*/
}
/**
* Verify that getBundle will do something reasonable when part of the
* resource hierarchy is missing.
*/
try {
}
errln("getBundle did not set up proper inheritance chain");
}
} finally {
}
}
/**
* 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>
*
*/
}
/**
* 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>
*/
}
/**
* Ensure that resources are only loaded once and are cached correctly
*/
final Loader loader = new Loader( new String[] { "Bug4168625Class" }, new String[] { "Bug4168625Resource3_en_US", "Bug4168625Resource3_en_CA" });
final String resClassName;
} else {
}
boolean dups = false;
dups = true;
} else {
}
}
if (dups) {
errln("ResourceBundle loaded some classes multiple times");
}
dups = false;
dups = true;
}
}
if (dups) {
errln("Resource bundle not caching some classes properly");
}
}
public ConcurrentLoadingThread(Loader loader, Bug4168625Getter test, Locale l, String resourceName) {
this.locale = l;
this.resourceName = resourceName;
}
this.locale = l;
}
public void run() {
try {
} catch (Exception e) {
errln("TEST CAUGHT UNEXPECTED EXCEPTION: "+e);
} finally {
}
}
public synchronized void waitUntilPinged() {
try {
} catch (InterruptedException e) {
logln("Test deadlocked.");
}
}
public synchronized void ping() {
notifyAll();
}
};
/**
* 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.
*/
final Loader loader = new Loader( new String[] { "Bug4168625Class" }, new String[] { "Bug4168625Resource3_en_US", "Bug4168625Resource3_en_CA" });
ConcurrentLoadingThread thread1 = new ConcurrentLoadingThread(loader, test, new Locale("en", "CA"));
ConcurrentLoadingThread thread2 = new ConcurrentLoadingThread(loader, test, new Locale("en", "IE"));
//Thread1 should be blocked inside getBundle at the class loader
//Thread2 should have completed its getBundle call and terminated
errln("ResourceBundle.getBundle not allowing legal concurrent loads");
}
}
/**
* 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).
*/
final String[] classToWait = { "Bug4168625Resource3_en_US","Bug4168625Resource3_en","Bug4168625Resource3" };
ConcurrentLoadingThread thread1 = new ConcurrentLoadingThread(loader, test, new Locale("en", "US"));
causeResourceBundleCacheFlush(); //cause a cache flush
causeResourceBundleCacheFlush(); //cause a cache flush
causeResourceBundleCacheFlush(); //cause a cache flush
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 boolean network = false;
public SimpleLoader() {
super(SimpleLoader.class.getClassLoader());
this.network = false;
}
super(SimpleLoader.class.getClassLoader());
this.network = simulateNetworkLoad;
}
throws ClassNotFoundException {
synchronized (this) {
if (network) {
try {
}
}
}
}
}
return result;
}
}
public Loader() {
super(Loader.class.getClassLoader());
}
super(Loader.class.getClassLoader());
}
/**
* Load a class. Files we can load take preference over ones the system
* can load.
*/
boolean shouldLoad = false;
shouldLoad = true;
break;
}
}
if (shouldLoad) {
try {
return result;
} catch (Exception e) {
return null;
}
} else {
return null;
}
}
/**
* Load a class. Files we can load take preference over ones the system
* can load.
*/
throws ClassNotFoundException {
synchronized (this) {
//we don't have a local copy of this one
} else {
//there was an error defining the class
}
}
}
}
}
rendezvous();
break;
}
}
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.
*/
}
}
logln("");
}
}
if (count > notifyCount) {
try {
} catch (InterruptedException e) {
}
} else {
}
return notifyCount;
}
private synchronized void notifyEveryone() {
notifyCount++;
notifyAll();
}
private void rendezvous() {
if (current instanceof ConcurrentLoadingThread) {
}
}
}
}
return temp;
}
/** Fill memory to force all SoftReferences to be GCed */
private void causeResourceBundleCacheFlush() {
logln("Filling memory...");
int allocationSize = 1024;
try {
while (true) {
allocationSize *= 2;
}
} catch (Throwable e) {
} finally{
}
}
/**
* 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.
*/
}