URLClassLoaderTest.java revision 743fc438ecba5ee39e44e4e8b36dfbe9381340bd
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 dalvik.annotation.BrokenTest;
21import dalvik.annotation.SideEffect;
22import dalvik.annotation.TestLevel;
23import dalvik.annotation.TestTargetClass;
24import dalvik.annotation.TestTargetNew;
25import dalvik.annotation.TestTargets;
26
27import org.apache.harmony.security.tests.support.TestCertUtils;
28
29import tests.support.Support_Configuration;
30import tests.support.Support_PortManager;
31import tests.support.Support_TestWebData;
32import tests.support.Support_TestWebServer;
33import tests.support.resource.Support_Resources;
34
35import java.io.File;
36import java.io.FileOutputStream;
37import java.io.IOException;
38import java.io.InputStream;
39import java.net.MalformedURLException;
40import java.net.URL;
41import java.net.URLClassLoader;
42import java.net.URLStreamHandler;
43import java.net.URLStreamHandlerFactory;
44import java.security.CodeSource;
45import java.security.Permission;
46import java.security.PermissionCollection;
47import java.security.cert.Certificate;
48import java.util.ArrayList;
49import java.util.Enumeration;
50import java.util.List;
51import java.util.Vector;
52import java.util.jar.Manifest;
53
54@TestTargetClass(
55    value = URLClassLoader.class,
56    untestedMethods = {
57        @TestTargetNew(
58            level = TestLevel.NOT_NECESSARY,
59            notes = "findClass uses defineClass which is not implemented",
60            method = "findClass",
61            args = {java.lang.String.class}
62        )
63    }
64)
65public class URLClassLoaderTest extends junit.framework.TestCase {
66
67    class BogusClassLoader extends ClassLoader {
68        public URL getResource(String res) {
69            try {
70                return new URL("http://test/BogusClassLoader");
71            } catch (MalformedURLException e) {
72                return null;
73            }
74        }
75    }
76
77    public class URLClassLoaderExt extends URLClassLoader {
78
79        public URLClassLoaderExt(URL[] urls) {
80            super(urls);
81        }
82
83        public Class<?> findClass(String cl) throws ClassNotFoundException {
84            return super.findClass(cl);
85        }
86    }
87
88    URLClassLoader ucl;
89    SecurityManager sm = new SecurityManager() {
90
91        public void checkPermission(Permission perm) {
92        }
93
94        public void checkCreateClassLoader() {
95            throw new SecurityException();
96        }
97    };
98
99    /**
100     * @tests java.net.URLClassLoader#URLClassLoader(java.net.URL[])
101     */
102    @TestTargetNew(
103        level = TestLevel.COMPLETE,
104        notes = "",
105        method = "URLClassLoader",
106        args = {java.net.URL[].class}
107    )
108    public void test_Constructor$Ljava_net_URL() throws MalformedURLException {
109        URL[] u = new URL[0];
110        ucl = new URLClassLoader(u);
111        assertTrue("Failed to set parent", ucl != null
112                && ucl.getParent() == URLClassLoader.getSystemClassLoader());
113
114
115        URL [] urls = {new URL("http://foo.com/foo"),
116                       new URL("jar:file://foo.jar!/foo.c"),
117                       new URL("ftp://foo1/foo2/foo.c")};
118
119        URLClassLoader ucl1 = new URLClassLoader(urls);
120        assertTrue(urls.length == ucl1.getURLs().length);
121
122        try {
123            Class.forName("test", false, ucl);
124            fail("Should throw ClassNotFoundException");
125        } catch (ClassNotFoundException e) {
126            // expected
127        }
128
129        SecurityManager oldSm = System.getSecurityManager();
130        System.setSecurityManager(sm);
131        try {
132            new URLClassLoader(u);
133            fail("SecurityException should be thrown.");
134        } catch (SecurityException e) {
135            // expected
136        } finally {
137            System.setSecurityManager(oldSm);
138        }
139
140        try {
141            new URLClassLoader(new URL[] { null });
142        } catch(Exception e) {
143            fail("Unexpected exception was thrown: " + e.getMessage());
144        }
145    }
146
147    /**
148     * @tests java.net.URLClassLoader#URLClassLoader(java.net.URL[],
149     *        java.lang.ClassLoader)
150     */
151    @TestTargetNew(
152        level = TestLevel.COMPLETE,
153        notes = "",
154        method = "URLClassLoader",
155        args = {java.net.URL[].class, java.lang.ClassLoader.class}
156    )
157    public void test_Constructor$Ljava_net_URLLjava_lang_ClassLoader() {
158        ClassLoader cl = new BogusClassLoader();
159        URL[] u = new URL[0];
160        ucl = new URLClassLoader(u, cl);
161        URL res = ucl.getResource("J");
162        assertNotNull(res);
163        assertEquals("Failed to set parent", "/BogusClassLoader", res.getFile());
164
165        SecurityManager oldSm = System.getSecurityManager();
166        System.setSecurityManager(sm);
167        try {
168            new URLClassLoader(u, cl);
169            fail("SecurityException should be thrown.");
170        } catch (SecurityException e) {
171            // expected
172        } finally {
173            System.setSecurityManager(oldSm);
174        }
175    }
176
177    /**
178     * @tests java.net.URLClassLoader#findResources(java.lang.String)
179     */
180    @TestTargetNew(
181        level = TestLevel.COMPLETE,
182        notes = "IOException checking missing. "
183            + "A test case that loads a resource from a webserver is missing.",
184        method = "findResources",
185        args = {java.lang.String.class}
186    )
187    @SideEffect("Support_TestWebServer requires isolation.")
188    public void test_findResourcesLjava_lang_String() throws Exception {
189        Enumeration<URL> res = null;
190        String[] resValues = { "This is a test resource file.",
191                "This is a resource from a subdir"};
192
193        String tmp = System.getProperty("java.io.tmpdir") + "/";
194
195        File tmpDir = new File(tmp);
196        File test1 = new File(tmp + "test0");
197        test1.deleteOnExit();
198        FileOutputStream out = new FileOutputStream(test1);
199        out.write(resValues[0].getBytes());
200        out.flush();
201        out.close();
202
203        File subDir = new File(tmp + "subdir/");
204        subDir.mkdir();
205        File test2 = new File(tmp + "subdir/test0");
206        test2.deleteOnExit();
207        out = new FileOutputStream(test2);
208        out.write(resValues[1].getBytes());
209        out.flush();
210        out.close();
211
212        URL[] urls = new URL[2];
213        urls[0] = new URL("file://" + tmpDir.getAbsolutePath() + "/");
214        urls[1] = new URL("file://" + subDir.getAbsolutePath() + "/");
215
216        ucl = new URLClassLoader(urls);
217        res = ucl.findResources("test0");
218        assertNotNull("Failed to locate resources", res);
219
220        int i = 0;
221        while (res.hasMoreElements()) {
222            StringBuffer sb = getResContent(res.nextElement());
223            assertEquals("Returned incorrect resource/or in wrong order",
224                    resValues[i++], sb.toString());
225        }
226        assertEquals("Incorrect number of resources returned", 2, i);
227    }
228
229    /**
230     * @tests java.net.URLClassLoader#getURLs()
231     */
232    @TestTargetNew(
233        level = TestLevel.COMPLETE,
234        notes = "",
235        method = "getURLs",
236        args = {}
237    )
238    public void test_getURLs() throws MalformedURLException {
239        URL[] urls = new URL[4];
240        urls[0] = new URL("http://" + Support_Configuration.HomeAddress);
241        urls[1] = new URL("http://" + Support_Configuration.TestResources + "/");
242        urls[2] = new URL("ftp://" + Support_Configuration.TestResources + "/");
243        urls[3] = new URL("jar:file:c://" + Support_Configuration.TestResources
244                + "!/");
245        ucl = new URLClassLoader(urls);
246        URL[] ucUrls = ucl.getURLs();
247        for (int i = 0; i < urls.length; i++) {
248            assertEquals("Returned incorrect URL[]", urls[i], ucUrls[i]);
249        }
250    }
251
252    /**
253     * @tests java.net.URLClassLoader#newInstance(java.net.URL[])
254     */
255    @TestTargetNew(
256        level = TestLevel.COMPLETE,
257        notes = "",
258        method = "newInstance",
259        args = {java.net.URL[].class}
260    )
261    @BrokenTest("web address used from support doesn't work anymore")
262    public void test_newInstance$Ljava_net_URL() throws MalformedURLException,
263            ClassNotFoundException {
264        // Verify that loaded class' have correct permissions
265        Class cl = null;
266        URL res = null;
267        URL[] urls = new URL[1];
268        urls[0] = new URL(Support_Resources.getResourceURL("/UCL/UCL.jar"));
269        ucl = URLClassLoader.newInstance(urls);
270        cl = ucl.loadClass("ucl.ResClass");
271
272        res = cl.getClassLoader().getResource("XX.class");
273        assertNotNull("Failed to load class", cl);
274        assertNotNull(
275                "Loaded class unable to access resource from same codeSource",
276                res);
277        cl = null;
278
279        urls[0] = new URL("jar:"
280                + Support_Resources.getResourceURL("/UCL/UCL.jar!/"));
281        ucl = URLClassLoader.newInstance(urls);
282        cl = ucl.loadClass("ucl.ResClass");
283        assertNotNull("Failed to load class from explicit jar URL", cl);
284    }
285
286    /**
287     * @tests java.net.URLClassLoader#newInstance(java.net.URL[],
288     *        java.lang.ClassLoader)
289     */
290    @TestTargetNew(
291        level = TestLevel.COMPLETE,
292        notes = "",
293        method = "newInstance",
294        args = {java.net.URL[].class, java.lang.ClassLoader.class}
295    )
296    public void test_newInstance$Ljava_net_URLLjava_lang_ClassLoader() {
297        ClassLoader cl = new BogusClassLoader();
298        URL[] u = new URL[0];
299        ucl = URLClassLoader.newInstance(u, cl);
300        URL res = ucl.getResource("J");
301        assertNotNull(res);
302        assertEquals("Failed to set parent", "/BogusClassLoader", res.getFile());
303    }
304
305    /**
306     * @tests java.net.URLClassLoader#URLClassLoader(java.net.URL[],
307     *        java.lang.ClassLoader, java.net.URLStreamHandlerFactory)
308     */
309    @TestTargetNew(
310        level = TestLevel.COMPLETE,
311        notes = "",
312        method = "URLClassLoader",
313        args = {java.net.URL[].class, java.lang.ClassLoader.class,
314                java.net.URLStreamHandlerFactory.class}
315    )
316    public void test_Constructor$Ljava_net_URLLjava_lang_ClassLoaderLjava_net_URLStreamHandlerFactory() {
317        class TestFactory implements URLStreamHandlerFactory {
318            public URLStreamHandler createURLStreamHandler(String protocol) {
319                return null;
320            }
321        }
322        ClassLoader cl = new BogusClassLoader();
323        URL[] u = new URL[0];
324        ucl = new URLClassLoader(u, cl, new TestFactory());
325        URL res = ucl.getResource("J");
326        assertNotNull(res);
327        assertEquals("Failed to set parent", "/BogusClassLoader", res.getFile());
328
329        SecurityManager oldSm = System.getSecurityManager();
330        System.setSecurityManager(sm);
331        try {
332            new URLClassLoader(u, cl, new TestFactory());
333            fail("SecurityException should be thrown.");
334        } catch (SecurityException e) {
335            // expected
336        } finally {
337            System.setSecurityManager(oldSm);
338        }
339    }
340
341    @TestTargetNew(
342        level = TestLevel.COMPLETE,
343        notes = "",
344        method = "addURL",
345        args = { URL.class }
346    )
347    public void test_addURLLjava_net_URL() throws MalformedURLException {
348        URL[] u = new URL[0];
349
350        URL [] urls = {new URL("http://foo.com/foo"),
351                       new URL("jar:file://foo.jar!/foo.c"),
352                       new URL("ftp://foo1/foo2/foo.c"), null};
353
354        TestURLClassLoader tucl = new TestURLClassLoader(u);
355
356        for(int i = 0; i < urls.length;) {
357            tucl.addURL(urls[i]);
358            i++;
359            URL [] result = tucl.getURLs();
360            assertEquals("Result array length is incorrect: " + i,
361                                                            i, result.length);
362            for(int j = 0; j < result.length; j++) {
363                assertEquals("Result array item is incorrect: " + j,
364                                                            urls[j], result[j]);
365            }
366        }
367    }
368
369    @TestTargetNew(
370        level = TestLevel.SUFFICIENT,
371        notes = "",
372        method = "getPermissions",
373        args = { CodeSource.class }
374    )
375    public void test_getPermissions() throws MalformedURLException {
376        URL url = new URL("http://" + Support_Configuration.SpecialInetTestAddress);
377        Certificate[] chain = TestCertUtils.getCertChain();
378        CodeSource cs = new CodeSource(url, chain);
379        TestURLClassLoader cl = new TestURLClassLoader(new URL[] {url});
380        PermissionCollection permCol = cl.getPermissions(cs);
381        assertNotNull(permCol);
382
383        URL url1 = new URL("file://foo/foo.c");
384        TestURLClassLoader cl1 = new TestURLClassLoader(new URL[] {url});
385        CodeSource cs1 = new CodeSource(url1, chain);
386        PermissionCollection permCol1 = cl1.getPermissions(cs1);
387        assertNotNull(permCol1);
388    }
389
390    @TestTargetNew(
391        level = TestLevel.COMPLETE,
392        notes = "",
393        method = "definePackage",
394        args = { java.lang.String.class, java.util.jar.Manifest.class,
395                 java.net.URL.class }
396    )
397    public void test_definePackage() throws MalformedURLException {
398        Manifest manifest = new Manifest();
399        URL[] u = new URL[0];
400        TestURLClassLoader tucl = new TestURLClassLoader(u);
401
402        URL [] urls = {new URL("http://foo.com/foo"),
403                new URL("jar:file://foo.jar!/foo.c"),
404                new URL("ftp://foo1/foo2/foo.c"),
405                new URL("file://new/package/name/"),
406                null};
407
408        String packageName = "new.package.name";
409
410        for(int i = 0; i < urls.length; i++) {
411            Package pack = tucl.definePackage(packageName + i, manifest, urls[i]);
412            assertEquals(packageName + i, pack.getName());
413            assertNull("Implementation Title is not null",
414                    pack.getImplementationTitle());
415            assertNull("Implementation Vendor is not null",
416                    pack.getImplementationVendor());
417            assertNull("Implementation Version is not null.",
418                    pack.getImplementationVersion());
419        }
420
421        try {
422            tucl.definePackage(packageName + "0", manifest, null);
423            fail("IllegalArgumentException was not thrown.");
424        } catch(IllegalArgumentException iae) {
425            //expected
426        }
427    }
428
429    class TestURLClassLoader extends URLClassLoader {
430        public TestURLClassLoader(URL[] urls) {
431            super(urls);
432        }
433
434        public void addURL(URL url) {
435            super.addURL(url);
436        }
437
438        public Package definePackage(String name,
439                                     Manifest man,
440                                     URL url)
441                                     throws IllegalArgumentException {
442            return super.definePackage(name, man, url);
443        }
444
445        public Class<?> findClass(String name)
446                                        throws ClassNotFoundException {
447            return super.findClass(name);
448        }
449
450        protected PermissionCollection getPermissions(CodeSource codesource) {
451            return super.getPermissions(codesource);
452        }
453    }
454
455    /**
456     * @tests java.net.URLClassLoader#findResource(java.lang.String)
457     */
458    @TestTargetNew(
459        level = TestLevel.PARTIAL_COMPLETE,
460        notes = "",
461        method = "findResource",
462        args = {java.lang.String.class}
463    )
464    @SideEffect("Support_TestWebServer requires isolation.")
465    public void test_findResourceLjava_lang_String() throws Exception {
466        int port = Support_PortManager.getNextPort();
467        File tmp = File.createTempFile("test", ".txt");
468
469        Support_TestWebServer server = new Support_TestWebServer();
470        try {
471
472            server.initServer(port, tmp.getAbsolutePath(), "text/html");
473
474            URL[] urls = { new URL("http://localhost:" + port + "/") };
475            ucl = new URLClassLoader(urls);
476            URL res = ucl.findResource("test1");
477            assertNotNull("Failed to locate resource", res);
478
479            StringBuffer sb = getResContent(res);
480            assertEquals("Returned incorrect resource", new String(Support_TestWebData.test1),
481                    sb.toString());
482        } finally {
483            server.close();
484        }
485    }
486
487    @TestTargets({
488        @TestTargetNew(
489            level = TestLevel.PARTIAL,
490            notes = "Checks getResource, indirectly checks findResource",
491            clazz = ClassLoader.class,
492            method = "getResource",
493            args = {java.lang.String.class}
494        ),
495        @TestTargetNew(
496            level = TestLevel.PARTIAL_COMPLETE,
497            notes = "Checks getResource, indirectly checks findResource",
498            method = "findResource",
499            args = {java.lang.String.class}
500        )
501    })
502    public void testFindResource_H3461() throws Exception {
503        File tmpDir = new File(System.getProperty("java.io.tmpdir"));
504        File dir = new File(tmpDir, "encode#me");
505        File f, f2;
506        URLClassLoader loader;
507        URL dirUrl;
508
509        if (!dir.exists()) {
510            dir.mkdir();
511        }
512        dir.deleteOnExit();
513        dirUrl = dir.toURI().toURL();
514        loader = new URLClassLoader( new URL[] { dirUrl });
515
516        f = File.createTempFile("temp", ".dat", dir);
517        f.deleteOnExit();
518        f2 = File.createTempFile("bad#name#", ".dat", dir);
519        f2.deleteOnExit();
520
521        assertNotNull("Unable to load resource from path with problematic name",
522            loader.getResource(f.getName()));
523        assertEquals("URL was not correctly encoded",
524            f2.toURI().toURL(),
525            loader.getResource(f2.getName()));
526    }
527
528    /**
529     * @tests java.net.URLClassLoader#getResource(java.lang.String)
530     */
531    @TestTargetNew(
532        level = TestLevel.COMPLETE,
533        notes = "",
534        method = "getResource",
535        args = {java.lang.String.class}
536    )
537    public void test_getResourceLjava_lang_String()
538            throws MalformedURLException {
539        URL url1 = new URL("file:///");
540        URLClassLoader loader = new URLClassLoader(new URL[] { url1 });
541        long start = System.currentTimeMillis();
542        // try without the leading /
543        URL result = loader.getResource("dir1/file1");
544        long end = System.currentTimeMillis();
545        long time = end - start;
546        if (time < 100) {
547            time = 100;
548        }
549
550        start = System.currentTimeMillis();
551        // try with the leading forward slash
552        result = loader.getResource("/dir1/file1");
553        end = System.currentTimeMillis();
554        long uncTime = end - start;
555        assertTrue("too long. UNC path formed? UNC time: " + uncTime
556                + " regular time: " + time, uncTime <= (time * 4));
557    }
558
559    /**
560     * Regression for Harmony-2237
561     */
562    @TestTargetNew(
563        level = TestLevel.PARTIAL_COMPLETE,
564        notes = "Regression test",
565        method = "findResource",
566        args = {java.lang.String.class}
567    )
568    @SideEffect("Support_TestWebServer requires isolation.")
569    public void test_findResource_String() throws Exception {
570        File tempFile1 = File.createTempFile("textFile", ".txt");
571        tempFile1.createNewFile();
572        tempFile1.deleteOnExit();
573        File tempFile2 = File.createTempFile("jarFile", ".jar");
574        tempFile2.delete();
575        tempFile2.deleteOnExit();
576
577        Support_TestWebServer server = new Support_TestWebServer();
578        int port = Support_PortManager.getNextPort();
579        try {
580            server.initServer(port, false);
581
582            String tempPath1 = tempFile1.getParentFile().getAbsolutePath() + "/";
583            InputStream is = getClass().getResourceAsStream(
584                    "/tests/resources/hyts_patch.jar");
585            Support_Resources.copyLocalFileto(tempFile2, is);
586            String tempPath2 = tempFile2.getAbsolutePath();
587            String tempPath3 = "http://localhost:" + port + "/";
588            URLClassLoader urlLoader = getURLClassLoader(tempPath1, tempPath2);
589            assertNull("Found inexistant resource",
590                    urlLoader.findResource("XXX")); //$NON-NLS-1$
591            assertNotNull("Couldn't find resource from directory",
592                    urlLoader.findResource(tempFile1.getName())); //$NON-NLS-1$
593            assertNotNull("Couldn't find resource from jar",
594                    urlLoader.findResource("Blah.txt")); //$NON-NLS-1$
595            urlLoader = getURLClassLoader(tempPath1, tempPath2, tempPath3);
596            assertNotNull("Couldn't find resource from web",
597                    urlLoader.findResource("test1")); //$NON-NLS-1$
598            assertNull("Found inexistant resource from web",
599                    urlLoader.findResource("test3")); //$NON-NLS-1$
600        } finally {
601            server.close();
602        }
603    }
604
605    private static URLClassLoader getURLClassLoader(String... classPath)
606            throws MalformedURLException {
607        List<URL> urlList = new ArrayList<URL>();
608        for (String path : classPath) {
609            String url;
610            File f = new File(path);
611            if (f.isDirectory()) {
612                url = "file:" + path;
613            } else if (path.startsWith("http")) {
614                url = path;
615            } else {
616                url = "jar:file:" + path + "!/";
617            }
618            urlList.add(new URL(url));
619        }
620        return new URLClassLoader(urlList.toArray(new URL[urlList.size()]));
621    }
622
623    private StringBuffer getResContent(URL res) throws IOException {
624        StringBuffer sb = new StringBuffer();
625        InputStream is = res.openStream();
626
627        int c;
628        while ((c = is.read()) != -1) {
629            sb.append((char) c);
630        }
631        is.close();
632        return sb;
633    }
634}
635