View Javadoc

1   package com.atlassian.plugin.loaders;
2   
3   import java.io.File;
4   import java.util.Arrays;
5   
6   import com.atlassian.plugin.ModuleDescriptorFactory;
7   import com.atlassian.plugin.Plugin;
8   import com.atlassian.plugin.PluginArtifact;
9   import com.atlassian.plugin.PluginArtifactFactory;
10  import com.atlassian.plugin.PluginException;
11  import com.atlassian.plugin.event.PluginEventManager;
12  import com.atlassian.plugin.event.events.PluginFrameworkShutdownEvent;
13  import com.atlassian.plugin.factories.PluginFactory;
14  import com.atlassian.plugin.impl.AbstractDelegatingPlugin;
15  import com.atlassian.plugin.impl.UnloadablePlugin;
16  import com.atlassian.plugin.loaders.classloading.DeploymentUnit;
17  import com.atlassian.plugin.loaders.classloading.Scanner;
18  
19  import com.google.common.collect.Iterables;
20  
21  import org.junit.Before;
22  import org.junit.Test;
23  import org.junit.runner.RunWith;
24  import org.mockito.Mock;
25  import org.mockito.runners.MockitoJUnitRunner;
26  
27  import static org.hamcrest.Matchers.containsInAnyOrder;
28  import static org.junit.Assert.assertEquals;
29  import static org.junit.Assert.assertNotNull;
30  import static org.junit.Assert.assertNotSame;
31  import static org.junit.Assert.assertSame;
32  import static org.junit.Assert.assertThat;
33  import static org.junit.Assert.assertTrue;
34  import static org.junit.Assert.fail;
35  import static org.mockito.Mockito.mock;
36  import static org.mockito.Mockito.never;
37  import static org.mockito.Mockito.verify;
38  import static org.mockito.Mockito.when;
39  
40  @RunWith (MockitoJUnitRunner.class)
41  public class TestScanningPluginLoader
42  {
43      @Mock
44      private PluginArtifactFactory pluginArtifactFactory;
45  
46      @Mock
47      private PluginArtifact pluginArtifact;
48  
49      @Mock
50      private PluginFactory pluginFactory;
51  
52      @Mock
53      private ModuleDescriptorFactory moduleDescriptorFactory;
54  
55      @Mock
56      private Plugin plugin;
57  
58      @Mock
59      private Scanner scanner;
60  
61      @Mock
62      private PluginEventManager pluginEventManager;
63  
64      @Before
65      public void configureMocks()
66      {
67          DeploymentUnit unit = new DeploymentUnit(new File("foo.jar"));
68          when(pluginArtifactFactory.create(unit.getPath().toURI())).thenReturn(pluginArtifact);
69          when(pluginFactory.canCreate(pluginArtifact)).thenReturn("foo");
70          when(scanner.getDeploymentUnits()).thenReturn(Arrays.asList(unit));
71      }
72  
73      @Test
74      public void loadAllPluginsLoadsPlugin()
75      {
76          when(pluginFactory.create(pluginArtifact, moduleDescriptorFactory)).thenReturn(plugin);
77  
78          ScanningPluginLoader loader = buildScanningPluginLoader();
79          Iterable<Plugin> plugins = loader.loadAllPlugins(moduleDescriptorFactory);
80          assertThat(plugins, containsInAnyOrder(plugin));
81      }
82  
83      @Test
84      public void discardedPluginIsNotTracked()
85      {
86          when(plugin.isUninstallable()).thenReturn(true);
87          when(pluginFactory.create(pluginArtifact, moduleDescriptorFactory)).thenReturn(plugin);
88  
89          ScanningPluginLoader loader = buildScanningPluginLoader();
90          Iterable<Plugin> plugins = loader.loadAllPlugins(moduleDescriptorFactory);
91          assertThat(plugins, containsInAnyOrder(plugin));
92          loader.discardPlugin(plugin);
93          try
94          {
95              // Discarded, so removal should fail event though isUninstallable
96              loader.removePlugin(plugin);
97              fail();
98          }
99          catch(PluginException pe)
100         {
101             // Expected
102         }
103         // Shutdown should not result in uninstall of discarded plugin
104         loader.onShutdown(mock(PluginFrameworkShutdownEvent.class));
105         verify(plugin, never()).uninstall();
106     }
107 
108     @Test
109     public void shutdownUninstallsUninstallablePlugin()
110     {
111         when(plugin.isUninstallable()).thenReturn(true);
112         when(pluginFactory.create(pluginArtifact, moduleDescriptorFactory)).thenReturn(plugin);
113 
114         ScanningPluginLoader loader = buildScanningPluginLoader();
115         loader.loadAllPlugins(moduleDescriptorFactory);
116         loader.onShutdown(mock(PluginFrameworkShutdownEvent.class));
117         verify(plugin).uninstall();
118     }
119 
120     @Test
121     public void shutdownDoesNotUninstallNotUninstallablePlugin()
122     {
123         when(plugin.isUninstallable()).thenReturn(false);
124         when(pluginFactory.create(pluginArtifact, moduleDescriptorFactory)).thenReturn(plugin);
125 
126         ScanningPluginLoader loader = buildScanningPluginLoader();
127         loader.loadAllPlugins(moduleDescriptorFactory);
128         loader.onShutdown(mock(PluginFrameworkShutdownEvent.class));
129         verify(plugin, never()).uninstall();
130     }
131 
132     @Test
133     public void factoryThrowingRuntimeExceptionYieldsUnloadablePlugin()
134     {
135         factoryThrowingYieldsUnloadablePlugin(new IllegalArgumentException());
136     }
137 
138     @Test
139     public void factoryThrowingErrorYieldsUnloadablePlugin()
140     {
141         factoryThrowingYieldsUnloadablePlugin(new NoClassDefFoundError());
142     }
143 
144     private void factoryThrowingYieldsUnloadablePlugin(final Throwable throwable)
145     {
146         when(pluginFactory.create(pluginArtifact, moduleDescriptorFactory)).thenThrow(throwable);
147 
148         ScanningPluginLoader loader = buildScanningPluginLoader();
149         Iterable<Plugin> plugins = loader.loadAllPlugins(moduleDescriptorFactory);
150         assertNotNull(plugins);
151         assertEquals(1, Iterables.size(plugins));
152         assertTrue(Iterables.getOnlyElement(plugins) instanceof UnloadablePlugin);
153     }
154 
155     @Test
156     public void pluginLoaderCallsPostProcess()
157     {
158         when(plugin.isUninstallable()).thenReturn(true);
159         when(pluginFactory.create(pluginArtifact, moduleDescriptorFactory)).thenReturn(plugin);
160 
161         ScanningPluginLoader loader = new ScanningPluginLoader(
162             scanner, Arrays.asList(pluginFactory), pluginArtifactFactory, pluginEventManager)
163         {
164             @Override
165             protected Plugin postProcess(Plugin plugin)
166             {
167                 return new WrappedPlugin(plugin);
168             }
169         };
170         Iterable<Plugin> allPlugins = loader.loadAllPlugins(moduleDescriptorFactory);
171         assertPluginsIsWrapperFor(allPlugins, plugin);
172 
173         DeploymentUnit unitB = new DeploymentUnit(new File("bar.jar"));
174         PluginArtifact pluginArtifactB = mock(PluginArtifact.class);
175         Plugin pluginB = mock(Plugin.class);
176         when(scanner.scan()).thenReturn(Arrays.asList(unitB));
177         when(pluginArtifactFactory.create(unitB.getPath().toURI())).thenReturn(pluginArtifactB);
178         when(pluginFactory.canCreate(pluginArtifactB)).thenReturn("bar");
179         when(pluginFactory.create(pluginArtifactB, moduleDescriptorFactory)).thenReturn(pluginB);
180 
181         Iterable<Plugin> foundPlugins = loader.loadFoundPlugins(moduleDescriptorFactory);
182         assertPluginsIsWrapperFor(foundPlugins, pluginB);
183     }
184 
185     /**
186      * A wrapper class for the postProcess test.
187      *
188      * By using a wrapper here, we guarantee postProcess is called, because no one else
189      * could have an instance of this private class.
190      */
191     private class WrappedPlugin extends AbstractDelegatingPlugin
192     {
193         public WrappedPlugin(final Plugin plugin)
194         {
195             super(plugin);
196         }
197     }
198 
199     private void assertPluginsIsWrapperFor(final Iterable<Plugin> plugins, final Plugin originalPlugin)
200     {
201         assertNotNull(plugins);
202         assertEquals(1, Iterables.size(plugins));
203         Plugin loadedPlugin = Iterables.getOnlyElement(plugins);
204         assertNotSame(loadedPlugin, originalPlugin);
205         assertTrue(loadedPlugin instanceof WrappedPlugin);
206         WrappedPlugin wrappedPlugin = (WrappedPlugin) loadedPlugin;
207         assertSame(wrappedPlugin.getDelegate(), originalPlugin);
208     }
209 
210     private ScanningPluginLoader buildScanningPluginLoader()
211     {
212         return new ScanningPluginLoader(scanner, Arrays.asList(pluginFactory), pluginArtifactFactory, pluginEventManager);
213     }
214 }