ClassLoaderTest.java revision 2ad60cfc28e14ee8f0bb038720836a4696c478ad
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.File;
21import java.io.FileOutputStream;
22import java.io.InputStream;
23import java.security.CodeSource;
24import java.security.Permission;
25import java.security.PermissionCollection;
26import java.security.Policy;
27import java.security.ProtectionDomain;
28import java.security.SecurityPermission;
29import junit.framework.TestCase;
30
31public class ClassLoaderTest extends TestCase {
32
33    public static volatile int flag;
34
35    /**
36     * Tests that Classloader.defineClass() assigns appropriate
37     * default domains to the defined classes.
38     */
39    public void test_defineClass_defaultDomain() throws Exception {
40        // Regression for HARMONY-765
41        DynamicPolicy plc = new DynamicPolicy();
42        Policy back = Policy.getPolicy();
43        try {
44            Policy.setPolicy(plc);
45
46            Class<?> a = new Ldr().define();
47
48            Permission p = new SecurityPermission("abc");
49            assertFalse("impossible! misconfiguration?", a.getProtectionDomain().implies(p));
50
51            plc.pc = p.newPermissionCollection();
52            plc.pc.add(p);
53            assertTrue("default domain is not dynamic", a.getProtectionDomain().implies(p));
54        } finally {
55            Policy.setPolicy(back);
56        }
57    }
58
59    static class SyncTestClassLoader extends ClassLoader {
60        Object lock;
61        volatile int numFindClassCalled;
62
63        SyncTestClassLoader(Object o) {
64            this.lock = o;
65            numFindClassCalled = 0;
66        }
67
68        /*
69         * Byte array of bytecode equivalent to the following source code:
70         * public class TestClass {
71         * }
72         */
73        private byte[] classData = new byte[] {
74            -54, -2, -70, -66, 0, 0, 0, 49, 0, 13,
75            10, 0, 3, 0, 10, 7, 0, 11, 7, 0,
76            12, 1, 0, 6, 60, 105, 110, 105, 116, 62,
77            1, 0, 3, 40, 41, 86, 1, 0, 4, 67,
78            111, 100, 101, 1, 0, 15, 76, 105, 110, 101,
79            78, 117, 109, 98, 101, 114, 84, 97, 98, 108,
80            101, 1, 0, 10, 83, 111, 117, 114, 99, 101,
81            70, 105, 108, 101, 1, 0, 14, 84, 101, 115,
82            116, 67, 108, 97, 115, 115, 46, 106, 97, 118,
83            97, 12, 0, 4, 0, 5, 1, 0, 9, 84,
84            101, 115, 116, 67, 108, 97, 115, 115, 1, 0,
85            16, 106, 97, 118, 97, 47, 108, 97, 110, 103,
86            47, 79, 98, 106, 101, 99, 116, 0, 33, 0,
87            2, 0, 3, 0, 0, 0, 0, 0, 1, 0,
88            1, 0, 4, 0, 5, 0, 1, 0, 6, 0,
89            0, 0, 29, 0, 1, 0, 1, 0, 0, 0,
90            5, 42, -73, 0, 1, -79, 0, 0, 0, 1,
91            0, 7, 0, 0, 0, 6, 0, 1, 0, 0,
92            0, 1, 0, 1, 0, 8, 0, 0, 0, 2,
93            0, 9 };
94
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            } else {
108                throw new ClassNotFoundException("Class " + name + " not found.");
109            }
110        }
111    }
112
113    static class SyncLoadTestThread extends Thread {
114        volatile boolean started;
115        ClassLoader cl;
116        Class cls;
117
118        SyncLoadTestThread(ClassLoader cl) {
119            this.cl = cl;
120        }
121
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        /*
230         * The Harmony resource could not be found anywhere, so we take
231         * our own.
232         */
233        InputStream in = this.getClass().getClassLoader().getResourceAsStream(
234                "test#.properties" /* ClassTest.FILENAME */);
235        assertNotNull(in);
236        in.close();
237    }
238}
239
240class DynamicPolicy extends Policy {
241
242    public PermissionCollection pc;
243
244    @Override
245    public PermissionCollection getPermissions(ProtectionDomain pd) {
246        return pc;
247    }
248
249    @Override
250    public PermissionCollection getPermissions(CodeSource codesource) {
251        return pc;
252    }
253
254    @Override
255    public void refresh() {
256    }
257}
258
259class A {
260}
261
262class Ldr extends ClassLoader {
263    @SuppressWarnings("deprecation")
264    public Class<?> define() throws Exception {
265        Package p = getClass().getPackage();
266        String path = p == null ? "" : p.getName().replace('.', File.separatorChar)
267                + File.separator;
268        InputStream is = getResourceAsStream(path + "A.class");
269        byte[] buf = new byte[512];
270        int len = is.read(buf);
271        return defineClass("org.apache.harmony.luni.tests.java.lang.A", buf, 0, len);
272    }
273}
274