/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.harmony.luni.tests.java.lang; import java.io.InputStream; import java.security.CodeSource; import java.security.Permission; import java.security.PermissionCollection; import java.security.Policy; import java.security.ProtectionDomain; import java.security.SecurityPermission; import junit.framework.TestCase; public class ClassLoaderTest extends TestCase { public static volatile int flag; /** * Tests that Classloader.defineClass() assigns appropriate * default domains to the defined classes. */ public void test_defineClass_defaultDomain() throws Exception { // Regression for HARMONY-765 DynamicPolicy plc = new DynamicPolicy(); Policy back = Policy.getPolicy(); try { Policy.setPolicy(plc); Class a = new Ldr().define(); Permission p = new SecurityPermission("abc"); assertFalse("impossible! misconfiguration?", a.getProtectionDomain().implies(p)); plc.pc = p.newPermissionCollection(); plc.pc.add(p); assertTrue("default domain is not dynamic", a.getProtectionDomain().implies(p)); } finally { Policy.setPolicy(back); } } static class SyncTestClassLoader extends ClassLoader { Object lock; volatile int numFindClassCalled; SyncTestClassLoader(Object o) { this.lock = o; numFindClassCalled = 0; } /* * Byte array of bytecode equivalent to the following source code: * public class TestClass { * } */ private byte[] classData = new byte[] { -54, -2, -70, -66, 0, 0, 0, 49, 0, 13, 10, 0, 3, 0, 10, 7, 0, 11, 7, 0, 12, 1, 0, 6, 60, 105, 110, 105, 116, 62, 1, 0, 3, 40, 41, 86, 1, 0, 4, 67, 111, 100, 101, 1, 0, 15, 76, 105, 110, 101, 78, 117, 109, 98, 101, 114, 84, 97, 98, 108, 101, 1, 0, 10, 83, 111, 117, 114, 99, 101, 70, 105, 108, 101, 1, 0, 14, 84, 101, 115, 116, 67, 108, 97, 115, 115, 46, 106, 97, 118, 97, 12, 0, 4, 0, 5, 1, 0, 9, 84, 101, 115, 116, 67, 108, 97, 115, 115, 1, 0, 16, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 0, 33, 0, 2, 0, 3, 0, 0, 0, 0, 0, 1, 0, 1, 0, 4, 0, 5, 0, 1, 0, 6, 0, 0, 0, 29, 0, 1, 0, 1, 0, 0, 0, 5, 42, -73, 0, 1, -79, 0, 0, 0, 1, 0, 7, 0, 0, 0, 6, 0, 1, 0, 0, 0, 1, 0, 1, 0, 8, 0, 0, 0, 2, 0, 9 }; @Override protected Class findClass(String name) throws ClassNotFoundException { try { while (flag != 2) { synchronized (lock) { lock.wait(); } } } catch (InterruptedException ie) {} if (name.equals("TestClass")) { numFindClassCalled++; return defineClass(null, classData, 0, classData.length); } throw new ClassNotFoundException("Class " + name + " not found."); } } static class SyncLoadTestThread extends Thread { volatile boolean started; ClassLoader cl; Class cls; SyncLoadTestThread(ClassLoader cl) { this.cl = cl; } @Override public void run() { try { started = true; cls = Class.forName("TestClass", false, cl); } catch (Exception ex) { ex.printStackTrace(); } } } /** * Regression test for HARMONY-1939: * 2 threads simultaneously run Class.forName() method for the same classname * and the same classloader. It is expected that both threads succeed but * class must be defined just once. */ public void test_loadClass_concurrentLoad() throws Exception { Object lock = new Object(); SyncTestClassLoader cl = new SyncTestClassLoader(lock); SyncLoadTestThread tt1 = new SyncLoadTestThread(cl); SyncLoadTestThread tt2 = new SyncLoadTestThread(cl); flag = 1; tt1.start(); tt2.start(); while (!tt1.started && !tt2.started) { Thread.sleep(100); } flag = 2; synchronized (lock) { lock.notifyAll(); } tt1.join(); tt2.join(); assertSame("Bad or redefined class", tt1.cls, tt2.cls); assertEquals("Both threads tried to define class", 1, cl.numFindClassCalled); } /** * @tests java.lang.ClassLoader#getResource(java.lang.String) */ public void test_getResourceLjava_lang_String() { // Test for method java.net.URL // java.lang.ClassLoader.getResource(java.lang.String) java.net.URL u = ClassLoader.getSystemClassLoader().getResource("hyts_Foo.c"); assertNotNull("Unable to find resource", u); java.io.InputStream is = null; try { is = u.openStream(); assertNotNull("Resource returned is invalid", is); is.close(); } catch (java.io.IOException e) { fail("IOException getting stream for resource : " + e.getMessage()); } } /** * @tests java.lang.ClassLoader#getResourceAsStream(java.lang.String) */ public void test_getResourceAsStreamLjava_lang_String() { // Test for method java.io.InputStream // java.lang.ClassLoader.getResourceAsStream(java.lang.String) // Need better test... java.io.InputStream is = null; assertNotNull("Failed to find resource: hyts_Foo.c", (is = ClassLoader .getSystemClassLoader().getResourceAsStream("hyts_Foo.c"))); try { is.close(); } catch (java.io.IOException e) { fail("Exception during getResourceAsStream: " + e.toString()); } } /** * @tests java.lang.ClassLoader#getSystemClassLoader() */ public void test_getSystemClassLoader() { // Test for method java.lang.ClassLoader // java.lang.ClassLoader.getSystemClassLoader() ClassLoader cl = ClassLoader.getSystemClassLoader(); java.io.InputStream is = cl.getResourceAsStream("hyts_Foo.c"); assertNotNull("Failed to find resource from system classpath", is); try { is.close(); } catch (java.io.IOException e) { } } /** * @tests java.lang.ClassLoader#getSystemResource(java.lang.String) */ public void test_getSystemResourceLjava_lang_String() { // Test for method java.net.URL // java.lang.ClassLoader.getSystemResource(java.lang.String) // Need better test... assertNotNull("Failed to find resource: hyts_Foo.c", ClassLoader .getSystemResource("hyts_Foo.c")); } //Regression Test for JIRA-2047 public void test_getResourceAsStream_withSharpChar() throws Exception { InputStream in = this.getClass().getClassLoader().getResourceAsStream( ClassTest.FILENAME); assertNotNull(in); in.close(); } } class DynamicPolicy extends Policy { public PermissionCollection pc; @Override public PermissionCollection getPermissions(ProtectionDomain pd) { return pc; } @Override public PermissionCollection getPermissions(CodeSource codesource) { return pc; } @Override public void refresh() { } } class A { } class Ldr extends ClassLoader { @SuppressWarnings("deprecation") public Class define() throws Exception { Package p = getClass().getPackage(); // Class loader paths use '/' character as separator String path = p == null ? "" : p.getName().replace('.', '/') + '/'; InputStream is = getResourceAsStream(path + "A.class"); byte[] buf = new byte[512]; int len = is.read(buf); return defineClass(buf, 0, len); } }