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 import java.lang.reflect.InvocationTargetException;
25 import java.lang.reflect.Method;
26 import java.net.MalformedURLException;
27 import java.net.URL;
28 import java.net.URLClassLoader;
29 import java.nio.file.Paths;
30 import java.util.logging.Logger;
31 
32 /**
33  * This class is used to ensure that a resource bundle loadable by a classloader
34  * is on the caller's stack, but not on the classpath or TCCL.  It tests that
35  * Logger.getLogger() can load the bundle via the immediate caller's classloader
36  *
37  * @author Jim Gish
38  */
39 public class IndirectlyLoadABundle {
40 
41     private static final String rbName = "CallerSearchableResource";
42 
loadAndTest()43     public boolean loadAndTest() throws Throwable {
44         // Make sure we can find it via the URLClassLoader
45         URLClassLoader yetAnotherResourceCL = new URLClassLoader(getURLs(), null);
46         if (!testForValidResourceSetup(yetAnotherResourceCL)) {
47             throw new Exception("Couldn't directly load bundle " + rbName
48                     + " as expected. Test config problem");
49         }
50         // But it shouldn't be available via the system classloader
51         ClassLoader myCL = this.getClass().getClassLoader();
52         if (testForValidResourceSetup(myCL)) {
53             throw new Exception("Was able to directly load bundle " + rbName
54                     + " from " + myCL + " but shouldn't have been"
55                     + " able to. Test config problem");
56         }
57 
58         Class<?> loadItUpClazz = Class.forName("LoadItUp1", true,
59                                                yetAnotherResourceCL);
60         ClassLoader actual = loadItUpClazz.getClassLoader();
61         if (actual != yetAnotherResourceCL) {
62             throw new Exception("LoadItUp1 was loaded by an unexpected CL: " + actual);
63         }
64         Object loadItUp = loadItUpClazz.newInstance();
65         Method testMethod = loadItUpClazz.getMethod("getLogger", String.class, String.class);
66         try {
67             return (Logger)testMethod.invoke(loadItUp, "NestedLogger1", rbName) != null;
68         } catch (InvocationTargetException ex) {
69             throw ex.getTargetException();
70         }
71     }
72 
testGetAnonymousLogger()73     public boolean testGetAnonymousLogger() throws Throwable {
74         // Test getAnonymousLogger()
75         URLClassLoader loadItUpCL = new URLClassLoader(getURLs(), null);
76         Class<?> loadItUpClazz = Class.forName("LoadItUp1", true, loadItUpCL);
77         ClassLoader actual = loadItUpClazz.getClassLoader();
78         if (actual != loadItUpCL) {
79             throw new Exception("LoadItUp1 was loaded by an unexpected CL: "
80                                  + actual);
81         }
82         Object loadItUpAnon = loadItUpClazz.newInstance();
83         Method testAnonMethod = loadItUpClazz.getMethod("getAnonymousLogger",
84                                                         String.class);
85         try {
86             return (Logger)testAnonMethod.invoke(loadItUpAnon, rbName) != null;
87         } catch (InvocationTargetException ex) {
88             throw ex.getTargetException();
89         }
90     }
91 
92 
testGetLoggerGetLoggerWithBundle()93     public boolean testGetLoggerGetLoggerWithBundle() throws Throwable {
94         // test getLogger("NestedLogger2"); followed by
95         // getLogger("NestedLogger2", rbName) to see if the bundle is found
96         //
97         URL[] urls = getURLs();
98         if (getLoggerWithNewCL(urls, "NestedLogger2", null)) {
99             return getLoggerWithNewCL(urls, "NestedLogger2", rbName);
100 
101         } else {
102             throw new Exception("TEST FAILED: first call to getLogger() failed "
103                                  + " in IndirectlyLoadABundle."
104                                  + "testGetLoggerGetLoggerWithBundle");
105         }
106     }
107 
getURLs()108     private URL[] getURLs() throws MalformedURLException {
109         // Find out where we are running from so we can setup the URLClassLoader URLs
110         // test.src and test.classes will be set if running in jtreg, but probably
111         // not otherwise
112         String testDir = System.getProperty("test.src", System.getProperty("user.dir"));
113         String testClassesDir = System.getProperty("test.classes",
114                                                    System.getProperty("user.dir"));
115         URL[] urls = new URL[2];
116         // Allow for both jtreg and standalone cases here
117         urls[0] = Paths.get(testDir, "resources").toUri().toURL();
118         urls[1] = Paths.get(testClassesDir).toUri().toURL();
119 
120         return urls;
121     }
122 
getLoggerWithNewCL(URL[] urls, String loggerName, String bundleName)123     private boolean getLoggerWithNewCL(URL[] urls, String loggerName,
124                                          String bundleName) throws Throwable {
125         Logger result = null;;
126         // Test getLogger("foo"); getLogger("foo", "rbName");
127         // First do the getLogger() call with no bundle name
128         URLClassLoader getLoggerCL = new URLClassLoader(urls, null);
129         Class<?> loadItUpClazz1 = Class.forName("LoadItUp1", true, getLoggerCL);
130         ClassLoader actual = loadItUpClazz1.getClassLoader();
131         if (actual != getLoggerCL) {
132             throw new Exception("LoadItUp1 was loaded by an unexpected CL: "
133                                  + actual);
134         }
135         Object loadItUp1 = loadItUpClazz1.newInstance();
136         if (bundleName != null) {
137             Method getLoggerMethod = loadItUpClazz1.getMethod("getLogger",
138                                                               String.class,
139                                                               String.class);
140             try {
141                 result = (Logger) getLoggerMethod.invoke(loadItUp1, loggerName,
142                                                          bundleName);
143             } catch (InvocationTargetException ex) {
144                 throw ex.getTargetException();
145             }
146         } else {
147             Method getLoggerMethod = loadItUpClazz1.getMethod("getLogger",
148                                                               String.class);
149             try {
150                 result = (Logger) getLoggerMethod.invoke(loadItUp1, loggerName);
151             } catch (InvocationTargetException ex) {
152                 throw ex.getTargetException();
153             }
154         }
155         return result != null;
156     }
157 
testForValidResourceSetup(ClassLoader cl)158     private boolean testForValidResourceSetup(ClassLoader cl) {
159         // First make sure the test environment is setup properly and the bundle
160         // actually exists
161         return ResourceBundleSearchTest.isOnClassPath(rbName, cl);
162     }
163 }
164