1 package it.com.atlassian.plugin.classloader;
2
3 import com.atlassian.plugin.classloader.PluginClassLoader;
4 import com.atlassian.plugin.test.PluginTestUtils;
5 import org.apache.commons.io.FileUtils;
6 import org.apache.commons.io.IOUtils;
7 import org.junit.Before;
8 import org.junit.Rule;
9 import org.junit.Test;
10 import org.junit.rules.TemporaryFolder;
11
12 import java.io.File;
13 import java.io.IOException;
14 import java.io.InputStream;
15 import java.lang.reflect.Method;
16 import java.net.URL;
17 import java.util.List;
18
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertNotNull;
21 import static org.junit.Assert.assertTrue;
22 import static org.junit.Assert.fail;
23
24
25
26
27
28
29 public class TestPluginClassLoader {
30
31 @Rule
32 public final TemporaryFolder temporaryFolder = new TemporaryFolder();
33
34 private PluginClassLoader pluginClassLoader;
35
36 @Before
37 public void setUp() throws Exception {
38 final URL url = getClass().getClassLoader().getResource(PluginTestUtils.SIMPLE_TEST_JAR);
39 assertNotNull("Can't find test resource '" + PluginTestUtils.SIMPLE_TEST_JAR + "' -- see class Javadoc, and be sure to set the 'project.version' system property!", url);
40 pluginClassLoader = new PluginClassLoader(new File(url.toURI()), getClass().getClassLoader(), temporaryFolder.getRoot());
41 }
42
43 @Test
44 public void testPluginClassLoaderFindsInnerJars() {
45 List innerJars = pluginClassLoader.getPluginInnerJars();
46 assertEquals(2, innerJars.size());
47 }
48
49 @Test
50 public void testPluginClassLoaderLoadsResourceFromOuterJarFirst() throws Exception {
51 URL resourceUrl = pluginClassLoader.getResource("testresource.txt");
52 assertNotNull(resourceUrl);
53 assertEquals("outerjar", IOUtils.toString(resourceUrl.openStream()));
54 }
55
56 @Test
57 public void testPluginClassLoaderLoadsClassFromOuterJar() throws Exception {
58 Class c = pluginClassLoader.loadClass("com.atlassian.plugin.simpletest.TestClassOne");
59 assertEquals("com.atlassian.plugin.simpletest", c.getPackage().getName());
60 assertEquals("com.atlassian.plugin.simpletest.TestClassOne", c.getName());
61 }
62
63 @Test
64 public void testPluginClassLoaderHandlesDeletedExtractedInnerJars() throws Exception {
65 File tmpDir = temporaryFolder.getRoot();
66 InputStream inputStream = pluginClassLoader.getResource("innerresource.txt").openStream();
67 assertNotNull(inputStream);
68 inputStream.close();
69 FileUtils.deleteDirectory(tmpDir);
70 assertTrue(tmpDir.mkdirs());
71 try {
72 assertNotNull(pluginClassLoader.getResource("innerresource.txt").openStream());
73 fail("underlying extracted inner jar was deleted and should throw FileNotFoundException");
74 } catch (IOException e) {
75
76 }
77 }
78
79 @Test
80 public void testPluginClassLoaderExtractsInnerJarsToSpecifiedDirectory() {
81 final List<File> files = pluginClassLoader.getPluginInnerJars();
82 for (File file : files) {
83 assertEquals(temporaryFolder.getRoot(), file.getParentFile());
84 }
85 }
86
87 @Test
88 public void testPluginClassLoaderDetectsMissingTempDirectory() {
89 try {
90 new PluginClassLoader(null, getClass().getClassLoader(), new File("/doesnotexisthopefully"));
91 fail("should throw IllegalArgumentException when temp directory does not exist");
92 } catch (IllegalStateException e) {
93
94 }
95 }
96
97 @Test
98 public void testPluginClassLoaderLoadsResourceFromInnerJarIfNotInOuterJar() throws Exception {
99 final URL resourceUrl = pluginClassLoader.getResource("innerresource.txt");
100 assertNotNull(resourceUrl);
101 InputStream inputStream = resourceUrl.openStream();
102 assertEquals("innerresource", IOUtils.toString(inputStream));
103 inputStream.close();
104 }
105
106 @Test
107 public void testPluginClassLoaderDoesNotSwallowClassesFromADifferentClassLoader() throws Exception {
108 final Class c = Class.forName(getClass().getName(), true, pluginClassLoader);
109 assertEquals(getClass().getClassLoader(), c.getClassLoader());
110 }
111
112 @Test
113 public void testPluginClassLoaderOverridesContainerClassesWithInnerJarClasses() throws Exception {
114 Class mockVersionedClass =
115 Class.forName("com.atlassian.plugin.mock.MockVersionedClass", true, pluginClassLoader);
116 Object instance = mockVersionedClass.getConstructor().newInstance();
117 Method getVersion = instance.getClass().getMethod("getVersion");
118 Object version = getVersion.invoke(instance);
119
120 assertEquals("PluginClassLoader is searching the parent classloader for classes before inner JARs",
121 2, version);
122 }
123
124 @Test
125 public void testPluginClassLoaderDoesNotLockTheJarsPermanently() throws Exception {
126
127 File original = new File(getClass().getClassLoader().getResource(PluginTestUtils.SIMPLE_TEST_JAR).toURI());
128 File tmpFile = new File(original.getAbsolutePath() + ".tmp");
129 FileUtils.copyFile(original, tmpFile);
130
131 PluginClassLoader pluginClassLoaderThatHasNotLockedFileYet = new
132 PluginClassLoader(tmpFile, getClass().getClassLoader());
133 Class mockVersionedClass =
134 Class.forName("com.atlassian.plugin.mock.MockVersionedClass", true, pluginClassLoader);
135 assertTrue(tmpFile.delete());
136 }
137 }