1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package org.apache.harmony.luni.tests.java.lang; 19 20import java.io.InputStream; 21import java.security.CodeSource; 22import java.security.Permission; 23import java.security.PermissionCollection; 24import java.security.Policy; 25import java.security.ProtectionDomain; 26import java.security.SecurityPermission; 27 28import junit.framework.TestCase; 29 30public class ClassLoaderTest extends TestCase { 31 32 public static volatile int flag; 33 34 /** 35 * Tests that Classloader.defineClass() assigns appropriate 36 * default domains to the defined classes. 37 */ 38 public void test_defineClass_defaultDomain() throws Exception { 39 // Regression for HARMONY-765 40 DynamicPolicy plc = new DynamicPolicy(); 41 Policy back = Policy.getPolicy(); 42 try { 43 Policy.setPolicy(plc); 44 45 Class<?> a = new Ldr().define(); 46 47 Permission p = new SecurityPermission("abc"); 48 assertFalse("impossible! misconfiguration?", a.getProtectionDomain().implies(p)); 49 50 plc.pc = p.newPermissionCollection(); 51 plc.pc.add(p); 52 assertTrue("default domain is not dynamic", a.getProtectionDomain().implies(p)); 53 } finally { 54 Policy.setPolicy(back); 55 } 56 } 57 58 static class SyncTestClassLoader extends ClassLoader { 59 Object lock; 60 volatile int numFindClassCalled; 61 62 SyncTestClassLoader(Object o) { 63 this.lock = o; 64 numFindClassCalled = 0; 65 } 66 67 /* 68 * Byte array of bytecode equivalent to the following source code: 69 * public class TestClass { 70 * } 71 */ 72 private byte[] classData = new byte[] { 73 -54, -2, -70, -66, 0, 0, 0, 49, 0, 13, 74 10, 0, 3, 0, 10, 7, 0, 11, 7, 0, 75 12, 1, 0, 6, 60, 105, 110, 105, 116, 62, 76 1, 0, 3, 40, 41, 86, 1, 0, 4, 67, 77 111, 100, 101, 1, 0, 15, 76, 105, 110, 101, 78 78, 117, 109, 98, 101, 114, 84, 97, 98, 108, 79 101, 1, 0, 10, 83, 111, 117, 114, 99, 101, 80 70, 105, 108, 101, 1, 0, 14, 84, 101, 115, 81 116, 67, 108, 97, 115, 115, 46, 106, 97, 118, 82 97, 12, 0, 4, 0, 5, 1, 0, 9, 84, 83 101, 115, 116, 67, 108, 97, 115, 115, 1, 0, 84 16, 106, 97, 118, 97, 47, 108, 97, 110, 103, 85 47, 79, 98, 106, 101, 99, 116, 0, 33, 0, 86 2, 0, 3, 0, 0, 0, 0, 0, 1, 0, 87 1, 0, 4, 0, 5, 0, 1, 0, 6, 0, 88 0, 0, 29, 0, 1, 0, 1, 0, 0, 0, 89 5, 42, -73, 0, 1, -79, 0, 0, 0, 1, 90 0, 7, 0, 0, 0, 6, 0, 1, 0, 0, 91 0, 1, 0, 1, 0, 8, 0, 0, 0, 2, 92 0, 9 }; 93 94 @Override 95 protected Class<?> findClass(String name) throws ClassNotFoundException { 96 try { 97 while (flag != 2) { 98 synchronized (lock) { 99 lock.wait(); 100 } 101 } 102 } catch (InterruptedException ie) {} 103 104 if (name.equals("TestClass")) { 105 numFindClassCalled++; 106 return defineClass(null, classData, 0, classData.length); 107 } 108 throw new ClassNotFoundException("Class " + name + " not found."); 109 } 110 } 111 112 static class SyncLoadTestThread extends Thread { 113 volatile boolean started; 114 ClassLoader cl; 115 Class<?> cls; 116 117 SyncLoadTestThread(ClassLoader cl) { 118 this.cl = cl; 119 } 120 121 @Override 122 public void run() { 123 try { 124 started = true; 125 cls = Class.forName("TestClass", false, cl); 126 } catch (Exception ex) { 127 ex.printStackTrace(); 128 } 129 } 130 } 131 132 /** 133 * Regression test for HARMONY-1939: 134 * 2 threads simultaneously run Class.forName() method for the same classname 135 * and the same classloader. It is expected that both threads succeed but 136 * class must be defined just once. 137 */ 138 public void test_loadClass_concurrentLoad() throws Exception 139 { 140 Object lock = new Object(); 141 SyncTestClassLoader cl = new SyncTestClassLoader(lock); 142 SyncLoadTestThread tt1 = new SyncLoadTestThread(cl); 143 SyncLoadTestThread tt2 = new SyncLoadTestThread(cl); 144 flag = 1; 145 tt1.start(); 146 tt2.start(); 147 148 while (!tt1.started && !tt2.started) { 149 Thread.sleep(100); 150 } 151 152 flag = 2; 153 synchronized (lock) { 154 lock.notifyAll(); 155 } 156 tt1.join(); 157 tt2.join(); 158 159 assertSame("Bad or redefined class", tt1.cls, tt2.cls); 160 assertEquals("Both threads tried to define class", 1, cl.numFindClassCalled); 161 } 162 163 /** 164 * @tests java.lang.ClassLoader#getResource(java.lang.String) 165 */ 166 public void test_getResourceLjava_lang_String() { 167 // Test for method java.net.URL 168 // java.lang.ClassLoader.getResource(java.lang.String) 169 java.net.URL u = ClassLoader.getSystemClassLoader().getResource("hyts_Foo.c"); 170 assertNotNull("Unable to find resource", u); 171 java.io.InputStream is = null; 172 try { 173 is = u.openStream(); 174 assertNotNull("Resource returned is invalid", is); 175 is.close(); 176 } catch (java.io.IOException e) { 177 fail("IOException getting stream for resource : " + e.getMessage()); 178 } 179 } 180 181 /** 182 * @tests java.lang.ClassLoader#getResourceAsStream(java.lang.String) 183 */ 184 public void test_getResourceAsStreamLjava_lang_String() { 185 // Test for method java.io.InputStream 186 // java.lang.ClassLoader.getResourceAsStream(java.lang.String) 187 // Need better test... 188 189 java.io.InputStream is = null; 190 assertNotNull("Failed to find resource: hyts_Foo.c", (is = ClassLoader 191 .getSystemClassLoader().getResourceAsStream("hyts_Foo.c"))); 192 try { 193 is.close(); 194 } catch (java.io.IOException e) { 195 fail("Exception during getResourceAsStream: " + e.toString()); 196 } 197 } 198 199 /** 200 * @tests java.lang.ClassLoader#getSystemClassLoader() 201 */ 202 public void test_getSystemClassLoader() { 203 // Test for method java.lang.ClassLoader 204 // java.lang.ClassLoader.getSystemClassLoader() 205 ClassLoader cl = ClassLoader.getSystemClassLoader(); 206 java.io.InputStream is = cl.getResourceAsStream("hyts_Foo.c"); 207 assertNotNull("Failed to find resource from system classpath", is); 208 try { 209 is.close(); 210 } catch (java.io.IOException e) { 211 } 212 213 } 214 215 /** 216 * @tests java.lang.ClassLoader#getSystemResource(java.lang.String) 217 */ 218 public void test_getSystemResourceLjava_lang_String() { 219 // Test for method java.net.URL 220 // java.lang.ClassLoader.getSystemResource(java.lang.String) 221 // Need better test... 222 assertNotNull("Failed to find resource: hyts_Foo.c", ClassLoader 223 .getSystemResource("hyts_Foo.c")); 224 } 225 226 227 //Regression Test for JIRA-2047 228 public void test_getResourceAsStream_withSharpChar() throws Exception { 229 InputStream in = this.getClass().getClassLoader().getResourceAsStream( 230 ClassTest.FILENAME); 231 assertNotNull(in); 232 in.close(); 233 } 234} 235 236class DynamicPolicy extends Policy { 237 238 public PermissionCollection pc; 239 240 @Override 241 public PermissionCollection getPermissions(ProtectionDomain pd) { 242 return pc; 243 } 244 245 @Override 246 public PermissionCollection getPermissions(CodeSource codesource) { 247 return pc; 248 } 249 250 @Override 251 public void refresh() { 252 } 253} 254 255class A { 256} 257 258class Ldr extends ClassLoader { 259 @SuppressWarnings("deprecation") 260 public Class<?> define() throws Exception { 261 Package p = getClass().getPackage(); 262 // Class loader paths use '/' character as separator 263 String path = p == null ? "" : p.getName().replace('.', '/') + '/'; 264 InputStream is = getResourceAsStream(path + "A.class"); 265 byte[] buf = new byte[512]; 266 int len = is.read(buf); 267 return defineClass(buf, 0, len); 268 } 269} 270