1/*
2 * Copyright (c) 2007, 2017, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23/*
24    @test
25    @bug 4049325 4073127 4083270 4106034 4108126 8027930 8171139
26    @summary test Resource Bundle
27    @build TestResource TestResource_de TestResource_fr TestResource_fr_CH
28    @build TestResource_it FakeTestResource
29    @run main ResourceBundleTest
30*/
31/*
32 *
33 *
34 * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
35 * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
36 *
37 * Portions copyright (c) 2007 Sun Microsystems, Inc.
38 * All Rights Reserved.
39 *
40 * The original version of this source code and documentation
41 * is copyrighted and owned by Taligent, Inc., a wholly-owned
42 * subsidiary of IBM. These materials are provided under terms
43 * of a License Agreement between Taligent and Sun. This technology
44 * is protected by multiple US and International patents.
45 *
46 * This notice and attribution to Taligent may not be removed.
47 * Taligent is a registered trademark of Taligent, Inc.
48 *
49 * Permission to use, copy, modify, and distribute this software
50 * and its documentation for NON-COMMERCIAL purposes and without
51 * fee is hereby granted provided that this copyright notice
52 * appears in all copies. Please refer to the file "copyright.html"
53 * for further important copyright and licensing information.
54 *
55 * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
56 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
57 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
58 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
59 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
60 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
61 *
62 */
63
64import java.text.*;
65import java.util.*;
66import java.util.ResourceBundle.Control;
67import java.io.*;
68import java.net.URL;
69
70public class ResourceBundleTest extends RBTestFmwk {
71    public static void main(String[] args) throws Exception {
72        new ResourceBundleTest().run(args);
73    }
74
75    public ResourceBundleTest() {
76        makePropertiesFile();
77    }
78
79    public void TestResourceBundle() {
80        Locale  saveDefault = Locale.getDefault();
81        Locale.setDefault(new Locale("fr", "FR"));
82
83        // load up the resource bundle, and make sure we got the right one
84        ResourceBundle  bundle = ResourceBundle.getBundle("TestResource");
85        if (!bundle.getClass().getName().equals("TestResource_fr"))
86            errln("Expected TestResource_fr, got " + bundle.getClass().getName());
87
88        // these resources are defines in ResourceBundle_fr
89        String  test1 = bundle.getString("Time");
90        if (!test1.equals("Time keeps on slipping..."))
91            errln("TestResource_fr returned wrong value for \"Time\":  got " + test1);
92
93        test1 = bundle.getString("For");
94        if (!test1.equals("Four score and seven years ago..."))
95            errln("TestResource_fr returned wrong value for \"For\":  got " + test1);
96
97        String[] test2 = bundle.getStringArray("All");
98        if (test2.length != 4)
99            errln("TestResource_fr returned wrong number of elements for \"All\": got " + test2.length);
100        else if (!test2[0].equals("'Twas brillig, and the slithy toves") ||
101                 !test2[1].equals("Did gyre and gimble in the wabe.") ||
102                 !test2[2].equals("All mimsy were the borogoves,") ||
103                 !test2[3].equals("And the mome raths outgrabe."))
104            errln("TestResource_fr returned the wrong value for one of the elements in \"All\"");
105
106        Object  test3 = bundle.getObject("Good");
107        if (test3 == null || test3.getClass() != Integer.class)
108            errln("TestResource_fr returned an object of the wrong class for \"Good\"");
109        else if (((Integer)test3).intValue() != 3)
110            errln("TestResource_fr returned the wrong value for \"Good\": got " + test3);
111
112        // This resource is defined in TestResource and inherited by TestResource_fr
113        test2 = bundle.getStringArray("Men");
114        if (test2.length != 3)
115            errln("TestResource_fr returned wrong number of elements for \"Men\": got " + test2.length);
116        else if (!test2[0].equals("1") ||
117                 !test2[1].equals("2") ||
118                 !test2[2].equals("C"))
119            errln("TestResource_fr returned the wrong value for one of the elements in \"All\"");
120
121        // This resource is defined in neither TestResource not TestResource_fr
122        try {
123            test3 = bundle.getObject("Is");
124            errln("TestResource_fr returned a value for \"Is\" when it shouldn't: got " + test3);
125        }
126        catch (MissingResourceException e) {
127        }
128
129        String[] keys = { "Now", "Time", "For", "All", "Good", "Men", "Come" };
130        checkKeys(bundle.getKeys(),  keys);
131
132        Locale.setDefault(saveDefault);
133    }
134
135    public void TestListResourceBundle() {
136        // load up the resource and check to make sure we got the right class
137        // (we don't define be_BY or be, so we fall back on the root default)
138        ResourceBundle  bundle = ResourceBundle.getBundle("TestResource",
139                            new Locale("be", "BY"),
140                            Control.getNoFallbackControl(Control.FORMAT_DEFAULT));
141        if (!bundle.getClass().getName().equals("TestResource"))
142            errln("Expected TestResource, got " + bundle.getClass().getName());
143
144        doListResourceBundleTest(bundle);
145    }
146
147    /**
148     * @bug 4073127
149     * Repeat TestListResourceBundle on TestResource_it, which is a ListResourceBundle
150     * with NO contents.  It should gracefully inherit everything from the root
151     * TestResource.
152     */
153    public void TestEmptyListResourceBundle() {
154        ResourceBundle bundle = ResourceBundle.getBundle("TestResource",
155                            new Locale("it", "IT"));
156        doListResourceBundleTest(bundle);
157    }
158
159    private void doListResourceBundleTest(ResourceBundle bundle) {
160        // load up the resource and check to make sure we got the right class
161        // all of these resources are defined in TestResource; it doesn' inherit from anybody
162        String  test1 = bundle.getString("Now");
163        if (!test1.equals("Now is the time for all..."))
164            errln("TestResource returned wrong value for \"Now\":  got " + test1);
165
166        test1 = bundle.getString("Time");
167        if (!test1.equals("Howdy Doody Time!"))
168            errln("TestResource returned wrong value for \"Time\":  got " + test1);
169
170        test1 = bundle.getString("Come");
171        if (!test1.equals("Come into my parlor..."))
172            errln("TestResource returned wrong value for \"Come\":  got " + test1);
173
174        Object  test3 = bundle.getObject("Good");
175        if (test3 == null || test3.getClass() != Integer.class)
176            errln("TestResource returned an object of the wrong class for \"Good\"");
177        else if (((Integer)test3).intValue() != 27)
178            errln("TestResource returned the wrong value for \"Good\": got " + test3);
179
180        String[] test2 = bundle.getStringArray("Men");
181        if (test2.length != 3)
182            errln("TestResource returned wrong number of elements for \"Men\": got " + test2.length);
183        else if (!test2[0].equals("1") ||
184                 !test2[1].equals("2") ||
185                 !test2[2].equals("C"))
186            errln("TestResource returned the wrong value for one of the elements in \"All\"");
187
188        // this item isn't defined in TestResource
189        try {
190            test3 = bundle.getObject("All");
191            errln("TestResource_en returned a value for \"All\" when it shouldn't: got " + test3);
192        }
193        catch (MissingResourceException e) {
194        }
195
196        String[] keys = { "Now", "Time", "Good", "Men", "Come" };
197        checkKeys(bundle.getKeys(), keys);
198    }
199
200    /**
201     * @bug 4049325
202     * @ summary Bug 4049325 says ResourceBundle.findBundle() uses a hard-coded '/' as
203     * the directory separator when searching for properties files.  Interestingly, it
204     * still works on my NT installation.  I can't tell whether this is a required
205     * property of all Java implementations (the magic appears to happen ClassLoader.
206     * getResourceAsStream(), which is a native function) or a lucky property of my
207     * particular implementation.  If this bug regresses, this test may still pass
208     * because a lower-level facility translates the / to the platform-specific separator
209     * for us.
210     */
211    public void TestPropertyResourceBundle() {
212        ResourceBundle  bundle = ResourceBundle.getBundle("TestResource",
213                            new Locale("es", "ES"));
214
215        // these resources are defined in TestResource_es.properties
216        String  test = bundle.getString("Now");
217        if (!test.equals("How now brown cow"))
218            errln("TestResource_es returned wrong value for \"Now\":  got " + test);
219
220        test = bundle.getString("Is");
221        if (!test.equals("Is there a dog?"))
222            errln("TestResource_es returned wrong value for \"Is\":  got " + test);
223
224        test = bundle.getString("The");
225        if (!test.equals("The rain in Spain"))
226            errln("TestResource_es returned wrong value for \"The\":  got " + test);
227
228        test = bundle.getString("Time");
229        if (!test.equals("Time marches on..."))
230            errln("TestResource_es returned wrong value for \"Time\":  got " + test);
231
232        // this resource is defined in TestResource and inherited by TestResource_es
233        String[] test2 = bundle.getStringArray("Men");
234        if (test2.length != 3)
235            errln("TestResource returned wrong number of elements for \"Men\": got " + test2.length);
236        else if (!test2[0].equals("1") ||
237                 !test2[1].equals("2") ||
238                 !test2[2].equals("C"))
239            errln("TestResource returned the wrong value for one of the elements in \"All\"");
240
241        // this resource is defined in neither TestResource nor TestResource_es
242        try {
243            test = bundle.getString("All");
244            errln("TestResource_es returned a value for \"All\" when it shouldn't: got " + test);
245        }
246        catch (MissingResourceException e) {
247        }
248
249        String[] keys = { "Now", "Is", "The", "Time", "Good", "Men", "Come" };
250        checkKeys(bundle.getKeys(), keys);
251    }
252
253    /**
254     * @bug 4108126
255     */
256    public void TestGetLocale() {
257        // try to find TestResource_fr_CH.  Should get fr_CH as its locale
258        ResourceBundle test = ResourceBundle.getBundle("TestResource",
259                        new Locale("fr", "CH", ""));
260        Locale locale = test.getLocale();
261        if (!(locale.getLanguage().equals("fr")) || !(locale.getCountry().equals("CH")))
262            errln("Actual locale for TestResource_fr_CH should have been fr_CH, got " + locale);
263
264        // try to find TestResource_fr_BE, which doesn't exist.  Should get fr as its locale
265        test = ResourceBundle.getBundle("TestResource",
266                        new Locale("fr", "BE", ""));
267        locale = test.getLocale();
268        if (!(locale.getLanguage().equals("fr")) || !(locale.getCountry().equals("")))
269            errln("Actual locale for TestResource_fr_BE should have been fr, got " + locale);
270
271        // try to find TestResource_iw_IL, which doesn't exist.  Should get root locale
272        // as its locale
273        test = ResourceBundle.getBundle("TestResource",
274                        new Locale("iw", "IL", ""),
275                        Control.getNoFallbackControl(Control.FORMAT_DEFAULT));
276        locale = test.getLocale();
277        if (!(locale.getLanguage().equals("")) || !(locale.getCountry().equals("")))
278            errln("Actual locale for TestResource_iw_IL should have been the root locale, got "
279                            + locale);
280    }
281
282    /*
283     * @bug 4083270
284     */
285    public void TestNonSubclass() {
286        // ResourceBundle.getBundle should never return an object that isn't an instance
287        // of ResourceBundle or one of its subclasses.  We have a class called FakeTestResource
288        // in this package that isn't a ResourceBundle.  If we get that back, we barf.
289        // (Actually, at the time I fixed this bug, getResource() would throw a
290        // ClassCastException in that case.)
291        // There's also a properties file called FakeTestResource; we should get back a
292        // PropertyResourceBundle pointing to that file.
293        Object test1 = ResourceBundle.getBundle("FakeTestResource",
294                Locale.US);
295
296        if (!(test1 instanceof ResourceBundle))
297            errln("Got back a " + test1.getClass().getName() + " instead of a PropertyResourceBundle when looking for FakeTestResource.");
298
299        ResourceBundle test = (ResourceBundle)test1;
300
301        // there's also a properties file called FakeTestResource.  getBundle() should
302        // find it, and it should have the following contents
303        String message = test.getString("message");
304        if (!message.equals("Hello!"))
305            errln("Supposedly found FakeTestResource.properties, but it had the wrong contents.");
306    }
307
308    /*
309     * @bug 4106034
310     */
311    public void TestErrorMessage() {
312        // Ensure that the message produced by the exception thrown
313        // by ResourceBundle.getObject contains both the class name and
314        // the key name.
315        final String className = "TestResource";
316        final String keyName = "DontGetThis";
317        ResourceBundle bundle = ResourceBundle.getBundle(className,
318                            new Locale("it", "IT"));
319        try {
320            Object o = bundle.getObject(keyName);
321            errln(bundle.getClass().getName()+" returned a value for tag \""+keyName+"\" when it should have thrown an exception.  It returned "+o);
322        } catch (MissingResourceException e) {
323            String message = e.getMessage();
324            boolean found = false;
325            if (message.indexOf(className) < 0) {
326                    errln("MissingResourceException error message did not contain class name.");
327            }
328            if (message.indexOf(keyName) < 0) {
329                    errln("MissingResourceException error message did not contain resource key name.");
330            }
331        }
332    }
333
334    /*
335     * @bug 8171139
336     * @summary Make sure clearCache() clears cached ResourceBundle instances
337     */
338    public void TestClearCache() {
339        final String className = "TestResource";
340        Locale loc = Locale.getDefault();
341
342        // testing no-arg clearCache()
343        ResourceBundle rb1 = ResourceBundle.getBundle(className, loc);
344        ResourceBundle.clearCache();
345        ResourceBundle rb2 = ResourceBundle.getBundle(className, loc);
346        if (rb1 == rb2) {
347            errln("clearCache(no-arg) did not clear cache");
348        }
349
350        // clearCache() with a custom classloader
351        ClassLoader cl1 = new DummyClassLoader();
352        rb1 = ResourceBundle.getBundle(className, loc, cl1);
353        if (rb1 == rb2) {
354            errln("Same bundle was returned for different class loaders");
355        }
356        ResourceBundle.clearCache(cl1);
357        rb2= ResourceBundle.getBundle(className, loc, cl1);
358        if (rb1 == rb2) {
359            errln("clearCache(classLoader) did not clear cache");
360        }
361        ClassLoader cl2 = new DummyClassLoader();
362        rb1 = ResourceBundle.getBundle(className, loc, cl2);
363        if (rb1 == rb2) {
364            errln("Same bundle was returned for different class loaders");
365        }
366        ResourceBundle.clearCache(cl1);
367        rb2 = ResourceBundle.getBundle(className, loc, cl2);
368        if (rb1 != rb2) {
369            errln("clearCache(classLoader) incorrectly cleared cache");
370        }
371    }
372
373    private void makePropertiesFile() {
374        try {
375            //
376            // The getProperty call is to ensure that this test will work with
377            // the JTREG test harness.  When running in the harness, the current
378            // directory is often set to someplace that isn't on the CLASSPATH,
379            // so we can't just create the properties files in the current
380            // directory.  But the harness uses the "test.classes" property to
381            // tell us where the classes directory is.
382            //
383            String classesDir = System.getProperty("test.classes", ".");
384            File    file = new File(classesDir, "TestResource_es.properties");
385            if (!file.exists()) {
386                FileOutputStream stream = new FileOutputStream(file);
387                Properties  props = new Properties();
388
389                props.put("Now", "How now brown cow");
390                props.put("Is", "Is there a dog?");
391                props.put("The", "The rain in Spain");
392                props.put("Time", "Time marches on...");
393
394                props.save(stream, "Test property list");
395
396                stream.close();
397            }
398
399            file = new File(classesDir, "FakeTestResource.properties");
400            if (!file.exists()) {
401                FileOutputStream stream = new FileOutputStream(file);
402                Properties props = new Properties();
403
404                props.put("message", "Hello!");
405
406                props.save(stream, "Test property list");
407
408                stream.close();
409            }
410        }
411        catch (java.io.IOException e) {
412            errln("Got exception: " + e);
413        }
414    }
415
416    private void checkKeys(Enumeration testKeys, String[] expectedKeys) {
417        Hashtable   hash = new Hashtable();
418        String      element;
419        int         elementCount = 0;
420
421        for (int i=0; i < expectedKeys.length; i++)
422            hash.put(expectedKeys[i], expectedKeys[i]);
423
424        while (testKeys.hasMoreElements()) {
425            element = (String)testKeys.nextElement();
426            elementCount++;
427            if (!hash.containsKey(element))
428                errln(element + " missing from key list.");
429        }
430
431        if (elementCount != expectedKeys.length)
432            errln("Wrong number of elements in key list: expected " + expectedKeys.length +
433                " got " + elementCount);
434    }
435
436    private static class DummyClassLoader extends ClassLoader {
437        public DummyClassLoader() {
438            super(DummyClassLoader.class.getClassLoader());
439        }
440
441        public Class<?> loadClass(String name) throws ClassNotFoundException {
442            return DummyClassLoader.class.getClassLoader().loadClass(name);
443        }
444
445        public URL getResource(String name) {
446            return DummyClassLoader.class.getClassLoader().getResource(name);
447        }
448
449        public InputStream getResourceAsStream(String name) {
450            return DummyClassLoader.class.getClassLoader().getResourceAsStream(name);
451        }
452    }
453}
454