1 package com.atlassian.plugin.util;
2
3 import com.atlassian.plugin.test.PluginJarBuilder;
4 import org.apache.commons.io.IOUtils;
5 import org.junit.Test;
6
7 import java.io.IOException;
8 import java.net.URL;
9 import java.net.URLClassLoader;
10 import java.util.Enumeration;
11 import java.util.HashMap;
12 import java.util.Map;
13
14 import static java.util.Collections.singletonMap;
15 import static org.junit.Assert.assertEquals;
16
17 public class TestChainingClassLoader {
18
19 @Test
20 public void testLoadClassInFirst() throws Exception {
21 final ClassLoader cl1 = new PluginJarBuilder().addFormattedJava("my.Foo", "package my; public class Foo {}").getClassLoader();
22 final ClassLoader cl2 = new PluginJarBuilder().getClassLoader();
23
24 assertEquals(cl1, new ChainingClassLoader(cl1, cl2).loadClass("my.Foo").getClassLoader());
25 }
26
27 @Test
28 public void testLoadClassInSecond() throws Exception {
29 final ClassLoader cl1 = new PluginJarBuilder().getClassLoader();
30 final ClassLoader cl2 = new PluginJarBuilder().addFormattedJava("my.Foo", "package my; public class Foo {}").getClassLoader();
31
32 assertEquals(cl2, new ChainingClassLoader(cl1, cl2).loadClass("my.Foo").getClassLoader());
33 }
34
35 @Test
36 public void testLoadClassInFirstHidesSecond() throws Exception {
37 final ClassLoader cl1 = new PluginJarBuilder().addFormattedJava("my.Foo", "package my; public class Foo {}").getClassLoader();
38 final ClassLoader cl2 = new PluginJarBuilder().addFormattedJava("my.Foo", "package my; public class Foo {}").getClassLoader();
39
40 assertEquals(cl1, new ChainingClassLoader(cl1, cl2).loadClass("my.Foo").getClassLoader());
41 }
42
43 @Test
44 public void testLoadResourceInFirst() throws Exception {
45 ClassLoader cl1 = buildClassLoaderWithResources(new HashMap<String, String>() {{
46 put("my/foo.txt", "foo");
47 }});
48 ClassLoader cl2 = buildClassLoaderWithResources(new HashMap<String, String>() {{
49 }});
50 ChainingClassLoader ccl = new ChainingClassLoader(cl1, cl2);
51 assertEquals("foo", IOUtils.readLines(ccl.getResourceAsStream("my/foo.txt")).get(0));
52 }
53
54 @Test
55 public void testLoadResourceInSecond() throws Exception {
56 ClassLoader cl1 = buildClassLoaderWithResources(new HashMap<String, String>() {{
57 }});
58 ClassLoader cl2 = buildClassLoaderWithResources(new HashMap<String, String>() {{
59 put("my/foo.txt", "foo");
60 }});
61 ChainingClassLoader ccl = new ChainingClassLoader(cl1, cl2);
62 assertEquals("foo", IOUtils.readLines(ccl.getResourceAsStream("my/foo.txt")).get(0));
63 }
64
65 @Test
66 public void testLoadResourceInFirstHidesSecond() throws Exception {
67 ClassLoader cl1 = buildClassLoaderWithResources(new HashMap<String, String>() {{
68 put("my/foo.txt", "foo");
69 }});
70 ClassLoader cl2 = buildClassLoaderWithResources(new HashMap<String, String>() {{
71 put("my/foo.txt", "bar");
72 }});
73 ChainingClassLoader ccl = new ChainingClassLoader(cl1, cl2);
74 assertEquals("foo", IOUtils.readLines(ccl.getResourceAsStream("my/foo.txt")).get(0));
75 }
76
77 @Test
78 public void testLoadResources() throws Exception {
79 ClassLoader cl1 = buildClassLoaderWithResources(new HashMap<String, String>() {{
80 put("my/foo.txt", "foo");
81 }});
82 ClassLoader cl2 = buildClassLoaderWithResources(new HashMap<String, String>() {{
83 put("my/foo.txt", "bar");
84 }});
85 ChainingClassLoader ccl = new ChainingClassLoader(cl1, cl2);
86 Enumeration<URL> e = ccl.getResources("my/foo.txt");
87 assertEquals("foo", IOUtils.readLines(e.nextElement().openStream()).get(0));
88 assertEquals("bar", IOUtils.readLines(e.nextElement().openStream()).get(0));
89 }
90
91 @Test
92 public void testLoadResourceWithNameOverride() throws Exception {
93 ClassLoader cl1 = buildClassLoaderWithResources(new HashMap<String, String>() {{
94 put("my/foo.txt", "foo");
95 put("my/bar.txt", "bar");
96 }});
97 ClassLoader cl2 = buildClassLoaderWithResources(new HashMap<String, String>() {{
98 }});
99 ChainingClassLoader ccl = new ChainingClassLoader(singletonMap("my/bar.txt", "my/foo.txt"), cl1, cl2);
100 assertEquals("foo", IOUtils.readLines(ccl.getResourceAsStream("my/bar.txt")).get(0));
101 assertEquals("foo", IOUtils.readLines(ccl.getResourceAsStream("my/foo.txt")).get(0));
102 }
103
104 @Test
105 public void testLoadClassOnlyInChainedClassloaders() throws Exception {
106 ClassLoader cl1 = new PluginJarBuilder().
107 getClassLoader();
108 ClassLoader cl2 = new PluginJarBuilder().
109 getClassLoader();
110 ChainingClassLoader ccl = new ChainingClassLoader(cl1, cl2);
111 assertEquals(cl1, ccl.loadClass(getClass().getName()).getClassLoader());
112 }
113
114 private URLClassLoader buildClassLoaderWithResources(Map<String, String> files)
115 throws IOException {
116 PluginJarBuilder builder = new PluginJarBuilder();
117 for (Map.Entry<String, String> entry : files.entrySet()) {
118 builder.addResource(entry.getKey(), entry.getValue());
119 }
120 return new URLClassLoader(new URL[]{builder.build().toURI().toURL()}, null);
121 }
122 }