View Javadoc

1   package it.com.atlassian.plugin.classloader;
2   
3   import com.atlassian.plugin.classloader.PluginClassLoader;
4   import com.atlassian.plugin.test.PluginTestUtils;
5   import com.opensymphony.util.BeanUtils;
6   import junit.framework.TestCase;
7   import org.apache.commons.io.IOUtils;
8   import org.apache.commons.io.FileUtils;
9   
10  import java.io.File;
11  import java.io.IOException;
12  import java.io.InputStream;
13  import java.net.URL;
14  import java.util.List;
15  
16  /**
17   * To make this test pass in your IDE, make sure you run Maven to build the necessary plugins and copy
18   * them to the target directory ('mvn package') and when running the tests, set the 'project.version'
19   * system property to the current version in the POM. E.g. -Dproject.version=2.1.0-SNAPSHOT
20   */
21  public class TestPluginClassLoader extends TestCase
22  {
23      private PluginClassLoader pluginClassLoader;
24      private File tmpDir;
25  
26      protected void setUp() throws Exception
27      {
28          super.setUp();
29          tmpDir = PluginTestUtils.createTempDirectory(TestPluginClassLoader.class);
30  
31          final URL url = getClass().getClassLoader().getResource(PluginTestUtils.SIMPLE_TEST_JAR);
32          assertNotNull("Can't find test resource -- see class Javadoc, and 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());  // PLUG-27
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              // expected exception because we deleted the jar
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 (IllegalStateException e)
97          {
98              // expected
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         //N.B This will probably never fail on a non Windows machine
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 }