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