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
96 loader.removePlugin(plugin);
97 fail();
98 }
99 catch(PluginException pe)
100 {
101
102 }
103
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
187
188
189
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 }