blob: 9c7b1ed19e71ae588b6d6aeaeed167d5b9dba79d [file] [log] [blame]
duke6e45e102007-12-01 00:00:00 +00001/*
2 * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 */
23/*
24 @test 1.3 99/02/15
25 @summary test Resource Bundle for bug 4179766
26 @build Bug4179766Class Bug4179766Resource Bug4179766Getter
27 @run main TestBug4179766
28 @bug 4179766
29*/
30/*
31 *
32 *
33 * (C) Copyright IBM Corp. 1996 - 1999 - All Rights Reserved
34 *
35 * Portions copyright (c) 2007 Sun Microsystems, Inc.
36 * All Rights Reserved.
37 *
38 * The original version of this source code and documentation
39 * is copyrighted and owned by Taligent, Inc., a wholly-owned
40 * subsidiary of IBM. These materials are provided under terms
41 * of a License Agreement between Taligent and Sun. This technology
42 * is protected by multiple US and International patents.
43 *
44 * This notice and attribution to Taligent may not be removed.
45 * Taligent is a registered trademark of Taligent, Inc.
46 *
47 * Permission to use, copy, modify, and distribute this software
48 * and its documentation for NON-COMMERCIAL purposes and without
49 * fee is hereby granted provided that this copyright notice
50 * appears in all copies. Please refer to the file "copyright.html"
51 * for further important copyright and licensing information.
52 *
53 * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
54 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
55 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
56 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
57 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
58 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
59 *
60 */
61
62import java.util.Hashtable;
63import java.util.ResourceBundle;
64import java.util.MissingResourceException;
65import java.util.Hashtable;
66import java.io.File;
67import java.io.FileInputStream;
68
69/**
70 * This class tests the behavior of the ResourceBundle cache with
71 * respect to ClassLoaders. The same resource loaded by different
72 * loaders should be cached as separate objects, one for each loader.
73 * In order to test this behavior, this test constructs a custom
74 * class loader to load its resources. It does not delegate resource
75 * loading to the system loader to load the class files, but loads
76 * them from the current directory instead. This is so that the
77 * defining class loader for the resources is different. If it
78 * delegated to the system loader to load the resources, the
79 * defining ClassLoader would be the same even though the initiating
80 * loader differered, and the resource would only be cached once.
81 */
82public class TestBug4179766 extends RBTestFmwk {
83 //hash code used by class loaders when sameHash is true
84 private static final int SAME_HASH_CODE = 0;
85 //the next unique hash code
86 private static int nextHashCode = SAME_HASH_CODE + 1;
87 //suffix on class files
88 private static final String CLASS_SUFFIX = ".class";
89
90 //generate a unique hashcode for a class loader
91 private static synchronized int getNextHashCode() {
92 return nextHashCode++;
93 }
94
95 public static void main(String[] args) throws Exception {
96 //static links so all needed classes get compiled
97 Object o1 = new Bug4179766Class();
98 Object o2 = new Bug4179766Resource();
99 new TestBug4179766().run(args);
100 }
101
102 /**
103 * Ensure the resource cache is working correctly for a single
104 * resource from a single loader. If we get the same resource
105 * from the same loader twice, we should get the same resource.
106 */
107 public void testCache() throws Exception {
108 Loader loader = new Loader(false);
109 ResourceBundle b1 = getResourceBundle(loader, "Bug4179766Resource");
110 if (b1 == null) {
111 errln("Resource not found: Bug4179766Resource");
112 }
113 ResourceBundle b2 = getResourceBundle(loader, "Bug4179766Resource");
114 if (b2 == null) {
115 errln("Resource not found: Bug4179766Resource");
116 }
117 printIDInfo("[bundle1]",b1);
118 printIDInfo("[bundle2]",b2);
119 if (b1 != b2) {
120 errln("Different objects returned by same ClassLoader");
121 }
122 }
123
124 /**
125 * Test that loaders with the same hash key still
126 * cache resources seperately
127 */
128 public void testSameHash() throws Exception {
129 doTest(true);
130 }
131
132 /**
133 * Test that loaders with different hash keys
134 * cache resources seperately
135 */
136 public void testDifferentHash() throws Exception {
137 doTest(false);
138 }
139
140 /**
141 * Ensure that cached resources for different ClassLoaders
142 * are cached seperately
143 */
144 private void doTest(boolean sameHash) throws Exception {
145 ResourceBundle b1 = getResourceBundle(new Loader(sameHash), "Bug4179766Resource");
146 if (b1 == null) {
147 errln("Resource not found: Bug4179766Resource");
148 }
149 ResourceBundle b2 = getResourceBundle(new Loader(sameHash), "Bug4179766Resource");
150 if (b2 == null) {
151 errln("Resource not found: Bug4179766Resource");
152 }
153 printIDInfo("[bundle1]",b1);
154 printIDInfo("[bundle2]",b2);
155 if (b1 == b2) {
156 errln("Same object returned by different ClassLoaders");
157 }
158 }
159
160 /**
161 * Get a resource using a specified class loader to load the resource
162 */
163 private ResourceBundle getResourceBundle(Loader loader, String name) throws Exception {
164 try {
165 Class c = loader.loadClass("Bug4179766Class");
166 Bug4179766Getter test = (Bug4179766Getter)c.newInstance();
167 return test.getResourceBundle(name);
168 } catch (ClassNotFoundException e) {
169 errln("Class not found by custom class loader: "+name);
170 throw e;
171 } catch (InstantiationException e) {
172 errln("Error instantiating: "+name);
173 throw e;
174 } catch (IllegalAccessException e) {
175 errln("IllegalAccessException instantiating: "+name);
176 throw e;
177 }
178 }
179
180 /**
181 * Print information about an object
182 * [message][object's identity][object's class][object's loader][loaders hash][loaders identity]
183 */
184 private void printIDInfo(String message, Object o) {
185 if (o == null) {
186 return;
187 }
188 Class c = o.getClass();
189 ClassLoader l = c.getClassLoader();
190 int hash = -1;
191 if (l != null) {
192 hash = l.hashCode();
193 }
194 logln(message + System.identityHashCode(o) + " Class: " + c
195 + " ClassLoader: " + l + " loaderHash: " + hash
196 + " loaderPrimHash: " + System.identityHashCode(l));
197 }
198
199 /**
200 * A simple class loader that loads classes from the current
201 * working directory. The hash code of the loader can be
202 * set to be either the loaders identity or 0, allowing several
203 * loaders to have the same hashCode value.
204 */
205 public class Loader extends ClassLoader {
206 private int thisHashCode;
207
208 /**
209 * Create a new loader
210 */
211 public Loader(boolean sameHash) {
212 if (sameHash) {
213 thisHashCode = SAME_HASH_CODE;
214 } else {
215 thisHashCode = getNextHashCode();
216 }
217 }
218
219 /**
220 * Return the hash code for this loader.
221 */
222 public int hashCode() {
223 return thisHashCode;
224 }
225
226 /**
227 * Get the data from the class file for the specified class. If
228 * the file can't be found, or the class is not one of the
229 * special ones listed below, return null.
230 * Bug4179766Class
231 * Bug4179766Resource
232 */
233 private byte[] getClassData(String className) {
234 boolean shouldLoad = className.equals("Bug4179766Class");
235 shouldLoad = shouldLoad || className.equals("Bug4179766Resource");
236
237 if (shouldLoad) {
238 try {
239 File file = new File(System.getProperty("test.classes", "."), className+CLASS_SUFFIX);
240 FileInputStream fi = new FileInputStream(file);
241 byte[] result = new byte[fi.available()];
242 fi.read(result);
243 return result;
244 } catch (Exception e) {
245 return null;
246 }
247 } else {
248 return null;
249 }
250 }
251
252 /**
253 * Load a class. Files we can load take preference over ones the system
254 * can load.
255 */
256 public synchronized Class loadClass(String className, boolean resolveIt)
257 throws ClassNotFoundException {
258
259 Class result = findLoadedClass(className);
260 if (result != null) {
261 printInfo(" ***Returning cached class: "+className, result);
262 return result;
263 }
264
265 byte[] classData = getClassData(className);
266 if (classData == null) {
267 //we don't have a local copy of this one
268 return loadFromSystem(className);
269 }
270
271 result = defineClass(classData, 0, classData.length);
272 if (result == null) {
273 //there was an error defining the class
274 return loadFromSystem(className);
275 }
276
277 if (resolveIt) {
278 resolveClass(result);
279 }
280
281 printInfo(" ***Loaded local class: "+className, result);
282 return result;
283 }
284
285 /**
286 * Delegate loading to the system loader
287 */
288 private Class loadFromSystem(String className) throws ClassNotFoundException {
289 try {
290 Class result = super.findSystemClass(className);
291 printInfo(" ***Returning system class: "+className, result);
292 return result;
293 } catch (ClassNotFoundException e) {
294 printInfo(" ***Class not found: "+className, null);
295 throw e;
296 }
297 }
298
299 /**
300 * Print information about a class that was loaded
301 * [loader identity][message][class identity]
302 */
303 private void printInfo(String message, Class c) {
304 if (c != null) {
305 logln(""+System.identityHashCode(this)+" "+message+" "+System.identityHashCode(c));
306 } else {
307 logln(""+System.identityHashCode(this)+" "+message);
308 }
309 }
310 }
311}