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