View Javadoc

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   * To make this test pass in your IDE, make sure you run Maven to build the necessary plugins and copy
17   * them to the target directory ('mvn package') and when running the tests, set the 'project.version'
18   * system property to the current version in the POM. E.g. -Dproject.version=2.1.0-SNAPSHOT
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());  // PLUG-27
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              // expected exception because we deleted the jar
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              // expected
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         //N.B This will probably never fail on a non Windows machine
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 }