URLClassLoaderTest.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 tests.api.java.net;
19
20import java.io.File;
21import java.io.IOException;
22import java.io.InputStream;
23import java.net.MalformedURLException;
24import java.net.URI;
25import java.net.URL;
26import java.net.URLClassLoader;
27import java.net.URLStreamHandler;
28import java.net.URLStreamHandlerFactory;
29import java.util.Enumeration;
30import java.util.NoSuchElementException;
31import java.util.StringTokenizer;
32import java.util.Vector;
33
34import org.apache.harmony.luni.util.InvalidJarIndexException;
35
36import tests.support.Support_Configuration;
37import tests.support.resource.Support_Resources;
38
39public class URLClassLoaderTest extends junit.framework.TestCase {
40
41    class BogusClassLoader extends ClassLoader {
42        public URL getResource(String res) {
43            try {
44                return new URL("http://test/BogusClassLoader");
45            } catch (MalformedURLException e) {
46                return null;
47            }
48        }
49    }
50
51    public class URLClassLoaderExt extends URLClassLoader {
52
53        public URLClassLoaderExt(URL[] urls) {
54            super(urls);
55        }
56
57        public Class<?> findClass(String cl) throws ClassNotFoundException {
58            return super.findClass(cl);
59        }
60    }
61
62    URLClassLoader ucl;
63
64    /**
65     * @tests java.net.URLClassLoader#URLClassLoader(java.net.URL[])
66     */
67    public void test_Constructor$Ljava_net_URL() {
68        URL[] u = new URL[0];
69        ucl = new URLClassLoader(u);
70        assertTrue("Failed to set parent", ucl != null
71                && ucl.getParent() == URLClassLoader.getSystemClassLoader());
72
73        URLClassLoader loader = new URLClassLoader(new URL[] { null });
74        boolean exception = false;
75        try {
76            Class.forName("test", false, loader);
77            fail("Should throw ClassNotFoundException");
78        } catch (ClassNotFoundException e) {
79            // expected
80        }
81    }
82
83    /**
84     * @tests java.net.URLClassLoader#URLClassLoader(java.net.URL[],
85     *        java.lang.ClassLoader)
86     */
87    public void test_Constructor$Ljava_net_URLLjava_lang_ClassLoader() {
88        ClassLoader cl = new BogusClassLoader();
89        URL[] u = new URL[0];
90        ucl = new URLClassLoader(u, cl);
91        URL res = ucl.getResource("J");
92        assertNotNull(res);
93        assertEquals("Failed to set parent", "/BogusClassLoader", res.getFile());
94    }
95
96    /**
97     * @tests java.net.URLClassLoader#findResources(java.lang.String)
98     */
99    public void test_findResourcesLjava_lang_String() throws IOException {
100        Enumeration res = null;
101        String[] resValues = { "This is a test resource file.",
102                "This is a resource from a subdir" };
103
104        URL[] urls = new URL[2];
105        urls[0] = new URL(Support_Resources.getResourceURL("/"));
106        urls[1] = new URL(Support_Resources.getResourceURL("/subdir1/"));
107        ucl = new URLClassLoader(urls);
108        res = ucl.findResources("RESOURCE.TXT");
109        assertNotNull("Failed to locate resources", res);
110
111        int i = 0;
112        while (res.hasMoreElements()) {
113            StringBuffer sb = new StringBuffer();
114            InputStream is = ((URL) res.nextElement()).openStream();
115            int c;
116            while ((c = is.read()) != -1) {
117                sb.append((char) c);
118            }
119            assertEquals("Returned incorrect resource/or in wrong order",
120                    resValues[i++], sb.toString());
121        }
122        assertTrue("Incorrect number of resources returned: " + i, i == 2);
123    }
124
125    /**
126     * @tests java.net.URLClassLoader#getURLs()
127     */
128    public void test_getURLs() throws MalformedURLException {
129        URL[] urls = new URL[4];
130        urls[0] = new URL("http://" + Support_Configuration.HomeAddress);
131        urls[1] = new URL("http://" + Support_Configuration.TestResources + "/");
132        urls[2] = new URL("ftp://" + Support_Configuration.TestResources + "/");
133        urls[3] = new URL("jar:file:c://" + Support_Configuration.TestResources
134                + "!/");
135        ucl = new URLClassLoader(urls);
136        URL[] ucUrls = ucl.getURLs();
137        for (int i = 0; i < urls.length; i++) {
138            assertEquals("Returned incorrect URL[]", urls[i], ucUrls[i]);
139        }
140    }
141
142    /**
143     * @tests java.net.URLClassLoader#newInstance(java.net.URL[])
144     */
145    public void test_newInstance$Ljava_net_URL() throws MalformedURLException,
146            ClassNotFoundException {
147        // Verify that loaded class' have correct permissions
148        Class cl = null;
149        URL res = null;
150        URL[] urls = new URL[1];
151        urls[0] = new URL(Support_Resources.getResourceURL("/UCL/UCL.jar"));
152        ucl = URLClassLoader.newInstance(urls);
153        cl = ucl.loadClass("ucl.ResClass");
154
155        res = cl.getClassLoader().getResource("XX.class");
156        assertNotNull("Failed to load class", cl);
157        assertNotNull(
158                "Loaded class unable to access resource from same codeSource",
159                res);
160        cl = null;
161
162        urls[0] = new URL("jar:"
163                + Support_Resources.getResourceURL("/UCL/UCL.jar!/"));
164        ucl = URLClassLoader.newInstance(urls);
165        cl = ucl.loadClass("ucl.ResClass");
166        assertNotNull("Failed to load class from explicit jar URL", cl);
167    }
168
169    /**
170     * @tests java.net.URLClassLoader#newInstance(java.net.URL[],
171     *        java.lang.ClassLoader)
172     */
173    public void test_newInstance$Ljava_net_URLLjava_lang_ClassLoader() {
174        ClassLoader cl = new BogusClassLoader();
175        URL[] u = new URL[0];
176        ucl = URLClassLoader.newInstance(u, cl);
177        URL res = ucl.getResource("J");
178        assertNotNull(res);
179        assertEquals("Failed to set parent", "/BogusClassLoader", res.getFile());
180    }
181
182    /**
183     * @tests java.net.URLClassLoader#URLClassLoader(java.net.URL[],
184     *        java.lang.ClassLoader, java.net.URLStreamHandlerFactory)
185     */
186    public void test_Constructor$Ljava_net_URLLjava_lang_ClassLoaderLjava_net_URLStreamHandlerFactory() {
187        class TestFactory implements URLStreamHandlerFactory {
188            public URLStreamHandler createURLStreamHandler(String protocol) {
189                return null;
190            }
191        }
192        ClassLoader cl = new BogusClassLoader();
193        URL[] u = new URL[0];
194        ucl = new URLClassLoader(u, cl, new TestFactory());
195        URL res = ucl.getResource("J");
196        assertNotNull(res);
197        assertEquals("Failed to set parent", "/BogusClassLoader", res.getFile());
198    }
199
200    /**
201     * @throws ClassNotFoundException
202     * @throws IOException
203     * @tests java.net.URLClassLoader#findClass(java.lang.String)
204     */
205    public void test_findClassLjava_lang_String()
206            throws ClassNotFoundException, IOException {
207        File resources = Support_Resources.createTempFolder();
208        String resPath = resources.toString();
209        if (resPath.charAt(0) == '/' || resPath.charAt(0) == '\\') {
210            resPath = resPath.substring(1);
211        }
212
213        java.net.URL[] urls = new java.net.URL[1];
214        java.net.URLClassLoader ucl = null;
215        boolean classFound;
216        boolean exception;
217        boolean goodException;
218        Enumeration en;
219        boolean resourcesFound;
220        Support_Resources.copyFile(resources, "JarIndex", "hyts_11.jar");
221        Support_Resources.copyFile(resources, "JarIndex", "hyts_12.jar");
222        Support_Resources.copyFile(resources, "JarIndex", "hyts_13.jar");
223        Support_Resources.copyFile(resources, "JarIndex", "hyts_14.jar");
224        urls[0] = new URL("file:/" + resPath + "/JarIndex/hyts_11.jar");
225        ucl = URLClassLoader.newInstance(urls, null);
226        URL resURL = ucl.findResource("Test.txt");
227        URL reference = new URL("jar:file:/" + resPath.replace('\\', '/')
228                + "/JarIndex/hyts_14.jar!/Test.txt");
229        assertTrue("Resource not found: " + resURL + " ref: " + reference,
230                resURL.equals(reference));
231
232        Class c = Class.forName("cpack.CNothing", true, ucl);
233        assertNotNull(c);
234
235        Support_Resources.copyFile(resources, "JarIndex", "hyts_21.jar");
236        Support_Resources.copyFile(resources, "JarIndex", "hyts_22.jar");
237        Support_Resources.copyFile(resources, "JarIndex", "hyts_23.jar");
238        urls[0] = new URL("file:/" + resPath + "/JarIndex/hyts_21.jar");
239        ucl = URLClassLoader.newInstance(urls, null);
240        en = ucl.findResources("bpack/");
241
242        try {
243            resourcesFound = true;
244            URL url1 = (URL) en.nextElement();
245            URL url2 = (URL) en.nextElement();
246            System.out.println(url1);
247            System.out.println(url2);
248            resourcesFound = resourcesFound
249                    && url1.equals(new URL("jar:file:/"
250                            + resPath.replace('\\', '/')
251                            + "/JarIndex/hyts_22.jar!/bpack/"));
252            resourcesFound = resourcesFound
253                    && url2.equals(new URL("jar:file:/"
254                            + resPath.replace('\\', '/')
255                            + "/JarIndex/hyts_23.jar!/bpack/"));
256            if (en.hasMoreElements()) {
257                resourcesFound = false;
258            }
259        } catch (NoSuchElementException e) {
260            resourcesFound = false;
261        }
262        assertTrue("Resources not found (1)", resourcesFound);
263
264        Class c2 = Class.forName("bpack.Homer", true, ucl);
265        assertNotNull(c2);
266
267        try {
268            Class.forName("bpack.Bart", true, ucl);
269            fail("InvalidJarIndexException should be thrown");
270        } catch (InvalidJarIndexException e) {
271            // expected
272        }
273
274        try {
275            Class.forName("Main4", true, ucl);
276            fail("ClassNotFoundException should be thrown");
277        } catch (ClassNotFoundException e) {
278            // Expected
279        }
280
281        Support_Resources.copyFile(resources, "JarIndex", "hyts_22-new.jar");
282        urls[0] = new URL("file:/" + resPath + "/JarIndex/hyts_22-new.jar");
283        ucl = URLClassLoader.newInstance(urls, null);
284        assertNotNull("Cannot find resource", ucl.findResource("cpack/"));
285        Support_Resources.copyFile(resources, "JarIndex", "hyts_11.jar");
286        urls[0] = new URL("file:/" + resPath + "/JarIndex/hyts_31.jar");
287        ucl = URLClassLoader.newInstance(urls, null);
288
289        try {
290            Class.forName("cpack.Mock", true, ucl);
291            fail("ClassNotFoundException should be thrown");
292        } catch (ClassNotFoundException e) {
293            // Expected
294        }
295
296        // testing circular reference
297        Support_Resources.copyFile(resources, "JarIndex", "hyts_41.jar");
298        Support_Resources.copyFile(resources, "JarIndex", "hyts_42.jar");
299        urls[0] = new URL("file:/" + resPath + "/JarIndex/hyts_41.jar");
300        ucl = URLClassLoader.newInstance(urls, null);
301        en = ucl.findResources("bpack/");
302        resourcesFound = resourcesFound
303                && ((URL) en.nextElement()).equals(new URL("jar:file:/"
304                        + resPath.replace('\\', '/')
305                        + "/JarIndex/hyts_42.jar!/bpack/"));
306        assertTrue("Resources not found (2)", resourcesFound);
307        assertFalse("No more resources expected", en.hasMoreElements());
308
309        // Regression test for HARMONY-2357.
310        try {
311            URLClassLoaderExt cl = new URLClassLoaderExt(new URL[557]);
312            cl.findClass("0");
313            fail("NullPointerException should be thrown");
314        } catch (NullPointerException npe) {
315            // Expected
316        }
317
318        // Regression test for HARMONY-2871.
319        URLClassLoader cl = new URLClassLoader(new URL[] { new URL("file:/foo.jar") });
320
321        try {
322            Class.forName("foo.Foo", false, cl);
323        } catch (Exception ex) {
324            // Don't care
325        }
326
327        try {
328            Class.forName("foo.Foo", false, cl);
329            fail("NullPointerException should be thrown");
330        } catch (ClassNotFoundException cnfe) {
331            // Expected
332        }
333    }
334
335    /**
336     * @tests java.net.URLClassLoader#findResource(java.lang.String)
337     */
338    public void test_findResourceLjava_lang_String()
339            throws MalformedURLException {
340        URL res = null;
341
342        URL[] urls = new URL[2];
343        urls[0] = new URL("http://" + Support_Configuration.HomeAddress);
344        urls[1] = new URL(Support_Resources.getResourceURL("/"));
345        ucl = new URLClassLoader(urls);
346        res = ucl.findResource("RESOURCE.TXT");
347        assertNotNull("Failed to locate resource", res);
348
349        StringBuffer sb = new StringBuffer();
350        try {
351            java.io.InputStream is = res.openStream();
352
353            int c;
354            while ((c = is.read()) != -1) {
355                sb.append((char) c);
356            }
357            is.close();
358        } catch (IOException e) {
359        }
360        assertTrue("Returned incorrect resource", !sb.toString().equals(
361                "This is a test resource file"));
362    }
363
364    public void testFindResource_H3461() throws Exception {
365        File userDir = new File(System.getProperty("user.dir"));
366        File dir = new File(userDir, "encode#me");
367        File f, f2;
368        URLClassLoader loader;
369        URL dirUrl;
370
371        if (!dir.exists()) {
372            dir.mkdir();
373        }
374        dir.deleteOnExit();
375        dirUrl = dir.toURI().toURL();
376        loader = new URLClassLoader( new URL[] { dirUrl });
377
378        f = File.createTempFile("temp", ".dat", dir);
379        f.deleteOnExit();
380        f2 = File.createTempFile("bad#name#", ".dat", dir);
381        f2.deleteOnExit();
382
383        assertNotNull("Unable to load resource from path with problematic name",
384            loader.getResource(f.getName()));
385        assertEquals("URL was not correctly encoded",
386            f2.toURI().toURL(),
387            loader.getResource(f2.getName()));
388    }
389
390    /**
391     * @tests java.net.URLClassLoader#getResource(java.lang.String)
392     */
393    public void test_getResourceLjava_lang_String()
394            throws MalformedURLException {
395        URL url1 = new URL("file:///");
396        URLClassLoader loader = new URLClassLoader(new URL[] { url1 }, null);
397        long start = System.currentTimeMillis();
398        // try without the leading /
399        URL result = loader.getResource("dir1/file1");
400        long end = System.currentTimeMillis();
401        long time = end - start;
402        if (time < 100) {
403            time = 100;
404        }
405
406        start = System.currentTimeMillis();
407        // try with the leading forward slash
408        result = loader.getResource("/dir1/file1");
409        end = System.currentTimeMillis();
410        long uncTime = end - start;
411        assertTrue("too long. UNC path formed? UNC time: " + uncTime
412                + " regular time: " + time, uncTime <= (time * 4));
413    }
414
415    /**
416	 * Regression for Harmony-2237
417	 */
418	public void test_getResource() throws Exception {
419		URLClassLoader urlLoader = getURLClassLoader();
420		assertNull(urlLoader.findResource("XXX")); //$NON-NLS-1$
421	}
422
423	private static URLClassLoader getURLClassLoader() {
424		String classPath = System.getProperty("java.class.path");
425        StringTokenizer tok = new StringTokenizer(classPath, File.pathSeparator);
426        Vector<URL> urlVec = new Vector<URL>();
427        String resPackage = Support_Resources.RESOURCE_PACKAGE;
428        try {
429            while (tok.hasMoreTokens()) {
430                String path = tok.nextToken();
431                String url;
432                if (new File(path).isDirectory())
433                    url = "file:" + path + resPackage + "subfolder/";
434                else
435                    url = "jar:file:" + path + "!" + resPackage + "subfolder/";
436                urlVec.addElement(new URL(url));
437            }
438        } catch (MalformedURLException e) {
439        	// do nothing
440        }
441        URL[] urls = new URL[urlVec.size()];
442        for (int i = 0; i < urlVec.size(); i++) {
443        	urls[i] = urlVec.elementAt(i);
444        }
445        URLClassLoader loader = new URLClassLoader(urls, null);
446		return loader;
447	}
448}
449