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