1 /* 2 * Copyright (c) 2013, 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 /* 25 * @test 26 * @bug 8002070 27 * @summary Remove the stack search for a resource bundle Logger to use 28 * @author Jim Gish 29 * @build ResourceBundleSearchTest IndirectlyLoadABundle LoadItUp 30 * @run main ResourceBundleSearchTest 31 */ 32 import java.net.URL; 33 import java.net.URLClassLoader; 34 import java.nio.file.Paths; 35 import java.util.ArrayList; 36 import java.util.List; 37 import java.util.Locale; 38 import java.util.MissingResourceException; 39 import java.util.ResourceBundle; 40 import java.util.logging.Logger; 41 42 public class ResourceBundleSearchTest { 43 44 private final static boolean DEBUG = false; 45 private final static String LOGGER_PREFIX = "myLogger."; 46 private static int loggerNum = 0; 47 private final static String PROP_RB_NAME = "ClassPathTestBundle"; 48 private final static String TCCL_TEST_BUNDLE = "ContextClassLoaderTestBundle"; 49 50 private static int numPass = 0; 51 private static int numFail = 0; 52 private static List<String> msgs = new ArrayList<>(); 53 54 public static void main(String[] args) throws Throwable { 55 ResourceBundleSearchTest test = new ResourceBundleSearchTest(); 56 test.runTests(); 57 } 58 59 private void runTests() throws Throwable { 60 // ensure we are using en as the default Locale so we can find the resource 61 Locale.setDefault(Locale.ENGLISH); 62 63 String testClasses = System.getProperty("test.classes"); 64 System.out.println( "test.classes = " + testClasses ); 65 66 ClassLoader myClassLoader = ClassLoader.getSystemClassLoader(); 67 68 // Find out where we are running from so we can setup the URLClassLoader URL 69 String userDir = System.getProperty("user.dir"); 70 String testDir = System.getProperty("test.src", userDir); 71 String sep = System.getProperty("file.separator"); 72 73 URL[] urls = new URL[1]; 74 75 urls[0] = Paths.get(testDir, "resources").toUri().toURL(); 76 URLClassLoader rbClassLoader = new URLClassLoader(urls); 77 78 // Test 1 - can we find a Logger bundle from doing a stack search? 79 // We shouldn't be able to 80 assertFalse(testGetBundleFromStackSearch(), "testGetBundleFromStackSearch"); 81 82 // Test 2 - can we find a Logger bundle off of the Thread context class 83 // loader? We should be able to. 84 assertTrue( 85 testGetBundleFromTCCL(TCCL_TEST_BUNDLE, rbClassLoader), 86 "testGetBundleFromTCCL"); 87 88 // Test 3 - Can we find a Logger bundle from the classpath? We should be 89 // able to, but .... 90 // We check to see if the bundle is on the classpath or not so that this 91 // will work standalone. In the case of jtreg/samevm, 92 // the resource bundles are not on the classpath. Running standalone 93 // (or othervm), they are 94 if (isOnClassPath(PROP_RB_NAME, myClassLoader)) { 95 debug("We should be able to see " + PROP_RB_NAME + " on the classpath"); 96 assertTrue(testGetBundleFromSystemClassLoader(PROP_RB_NAME), 97 "testGetBundleFromSystemClassLoader"); 98 } else { 99 debug("We should not be able to see " + PROP_RB_NAME + " on the classpath"); 100 assertFalse(testGetBundleFromSystemClassLoader(PROP_RB_NAME), 101 "testGetBundleFromSystemClassLoader"); 102 } 103 104 report(); 105 } 106 107 private void report() throws Exception { 108 System.out.println("Num passed = " + numPass + " Num failed = " + numFail); 109 if (numFail > 0) { 110 // We only care about the messages if they were errors 111 for (String msg : msgs) { 112 System.out.println(msg); 113 } 114 throw new Exception(numFail + " out of " + (numPass + numFail) 115 + " tests failed."); 116 } 117 } 118 119 public void assertTrue(boolean testResult, String testName) { 120 if (testResult) { 121 numPass++; 122 } else { 123 numFail++; 124 System.out.println("FAILED: " + testName 125 + " was supposed to return true but did NOT!"); 126 } 127 } 128 129 public void assertFalse(boolean testResult, String testName) { 130 if (!testResult) { 131 numPass++; 132 } else { 133 numFail++; 134 System.out.println("FAILED: " + testName 135 + " was supposed to return false but did NOT!"); 136 } 137 } 138 139 public boolean testGetBundleFromStackSearch() throws Throwable { 140 // This should fail. This was the old functionality to search up the 141 // caller's call stack 142 IndirectlyLoadABundle indirectLoader = new IndirectlyLoadABundle(); 143 return indirectLoader.loadAndTest(); 144 } 145 146 public boolean testGetBundleFromTCCL(String bundleName, 147 ClassLoader setOnTCCL) throws InterruptedException { 148 // This should succeed. We should be able to get the bundle from the 149 // thread context class loader 150 debug("Looking for " + bundleName + " using TCCL"); 151 LoggingThread lr = new LoggingThread(bundleName, setOnTCCL); 152 lr.start(); 153 synchronized (lr) { 154 try { 155 lr.wait(); 156 } catch (InterruptedException ex) { 157 throw ex; 158 } 159 } 160 msgs.add(lr.msg); 161 return lr.foundBundle; 162 } 163 164 /* 165 * @param String bundleClass 166 * @param ClassLoader to use for search 167 * @return true iff bundleClass is on system classpath 168 */ 169 public static boolean isOnClassPath(String baseName, ClassLoader cl) { 170 ResourceBundle rb = null; 171 try { 172 rb = ResourceBundle.getBundle(baseName, Locale.getDefault(), cl); 173 System.out.println("INFO: Found bundle " + baseName + " on " + cl); 174 } catch (MissingResourceException e) { 175 System.out.println("INFO: Could not find bundle " + baseName + " on " + cl); 176 return false; 177 } 178 return (rb != null); 179 } 180 181 private static String newLoggerName() { 182 // we need a new logger name every time we attempt to find a bundle via 183 // the Logger.getLogger call, so we'll simply tack on an integer which 184 // we increment each time this is called 185 loggerNum++; 186 return LOGGER_PREFIX + loggerNum; 187 } 188 189 public boolean testGetBundleFromSystemClassLoader(String bundleName) { 190 // this should succeed if the bundle is on the system classpath. 191 try { 192 Logger aLogger = Logger.getLogger(ResourceBundleSearchTest.newLoggerName(), 193 bundleName); 194 } catch (MissingResourceException re) { 195 msgs.add("INFO: testGetBundleFromSystemClassLoader() did not find bundle " 196 + bundleName); 197 return false; 198 } 199 msgs.add("INFO: testGetBundleFromSystemClassLoader() found the bundle " 200 + bundleName); 201 return true; 202 } 203 204 public static class LoggingThread extends Thread { 205 206 boolean foundBundle = false; 207 String msg = null; 208 ClassLoader clToSetOnTCCL = null; 209 String bundleName = null; 210 211 public LoggingThread(String bundleName) { 212 this.bundleName = bundleName; 213 } 214 215 public LoggingThread(String bundleName, ClassLoader setOnTCCL) { 216 this.clToSetOnTCCL = setOnTCCL; 217 this.bundleName = bundleName; 218 } 219 220 public void run() { 221 boolean setTCCL = false; 222 try { 223 if (clToSetOnTCCL != null) { 224 Thread.currentThread().setContextClassLoader(clToSetOnTCCL); 225 setTCCL = true; 226 } 227 // this should succeed if the bundle is on the system classpath. 228 try { 229 Logger aLogger = Logger.getLogger(ResourceBundleSearchTest.newLoggerName(), 230 bundleName); 231 msg = "INFO: LoggingRunnable() found the bundle " + bundleName 232 + (setTCCL ? " with " : " without ") + "setting the TCCL"; 233 foundBundle = true; 234 } catch (MissingResourceException re) { 235 msg = "INFO: LoggingRunnable() did not find the bundle " + bundleName 236 + (setTCCL ? " with " : " without ") + "setting the TCCL"; 237 foundBundle = false; 238 } 239 } catch (Throwable e) { 240 e.printStackTrace(); 241 System.exit(1); 242 } 243 } 244 } 245 246 private void debug(String msg) { 247 if (DEBUG) { 248 System.out.println(msg); 249 } 250 } 251 }