1 package it.com.atlassian.plugin.osgi;
2
3 import com.atlassian.plugin.DefaultModuleDescriptorFactory;
4 import com.atlassian.plugin.JarPluginArtifact;
5 import com.atlassian.plugin.Plugin;
6 import com.atlassian.plugin.PluginRestartState;
7 import com.atlassian.plugin.PluginState;
8 import com.atlassian.plugin.descriptors.AbstractModuleDescriptor;
9 import com.atlassian.plugin.descriptors.RequiresRestart;
10 import com.atlassian.plugin.hostcontainer.DefaultHostContainer;
11 import com.atlassian.plugin.module.ContainerManagedPlugin;
12 import com.atlassian.plugin.module.ModuleFactory;
13 import com.atlassian.plugin.osgi.Callable2;
14 import com.atlassian.plugin.osgi.Callable3;
15 import com.atlassian.plugin.osgi.PluginInContainerTestBase;
16 import com.atlassian.plugin.osgi.hostcomponents.ComponentRegistrar;
17 import com.atlassian.plugin.osgi.hostcomponents.HostComponentProvider;
18 import com.atlassian.plugin.test.PluginJarBuilder;
19 import org.junit.Test;
20 import org.osgi.framework.Bundle;
21 import org.osgi.util.tracker.ServiceTracker;
22
23 import java.io.File;
24
25 import static org.junit.Assert.assertEquals;
26 import static org.junit.Assert.assertFalse;
27 import static org.junit.Assert.assertNotNull;
28 import static org.junit.Assert.assertTrue;
29
30 public class TestEnableDisablePlugin extends PluginInContainerTestBase {
31 @Test
32 public void testEnableDisableEnable() throws Exception {
33 File pluginJar = new PluginJarBuilder("enabledisabletest")
34 .addPluginInformation("enabledisable", "foo", "1.0")
35 .addJava("my.Foo", "package my;" +
36 "public class Foo {}")
37 .build();
38 initPluginManager(null);
39 pluginController.installPlugins(new JarPluginArtifact(pluginJar));
40 Plugin plugin = pluginAccessor.getPlugin("enabledisable");
41 assertNotNull(((ContainerManagedPlugin) plugin).getContainerAccessor().createBean(plugin.loadClass("my.Foo", this.getClass())));
42 pluginController.disablePlugin("enabledisable");
43 pluginController.enablePlugins("enabledisable");
44
45 plugin = pluginAccessor.getPlugin("enabledisable");
46
47 assertNotNull(((ContainerManagedPlugin) plugin).getContainerAccessor().createBean(plugin.loadClass("my.Foo", this.getClass())));
48 }
49
50 @Test
51 public void testEnableDisableEnableWithPublicComponent() throws Exception {
52 File pluginJar = new PluginJarBuilder("enabledisabletest")
53 .addFormattedResource("atlassian-plugin.xml",
54 "<atlassian-plugin name='Test 2' key='enabledisablewithcomponent' pluginsVersion='2'>",
55 " <plugin-info>",
56 " <version>1.0</version>",
57 " </plugin-info>",
58 " <component key='foo' class='my.Foo' public='true' interface='my.Fooable'/>",
59 "</atlassian-plugin>")
60 .addJava("my.Fooable", "package my;" +
61 "public interface Fooable {}")
62 .addFormattedJava("my.Foo", "package my;",
63 "public class Foo implements Fooable, org.springframework.beans.factory.DisposableBean {",
64 " public void destroy() throws Exception { Thread.sleep(500); }",
65 "}")
66 .build();
67 initPluginManager(null);
68 pluginController.installPlugins(new JarPluginArtifact(pluginJar));
69 Plugin plugin = pluginAccessor.getPlugin("enabledisablewithcomponent");
70 assertEquals(PluginState.ENABLED, plugin.getPluginState());
71 assertNotNull(((ContainerManagedPlugin) plugin).getContainerAccessor().createBean(plugin.loadClass("my.Foo", this.getClass())));
72 pluginController.disablePlugin("enabledisablewithcomponent");
73 pluginController.enablePlugins("enabledisablewithcomponent");
74
75 plugin = pluginAccessor.getPlugin("enabledisablewithcomponent");
76 assertEquals(PluginState.ENABLED, plugin.getPluginState());
77
78 assertNotNull(((ContainerManagedPlugin) plugin).getContainerAccessor().createBean(plugin.loadClass("my.Foo", this.getClass())));
79 }
80
81 @Test
82 public void testDisableEnableOfPluginThatRequiresRestart() throws Exception {
83 final DefaultModuleDescriptorFactory factory = new DefaultModuleDescriptorFactory(new DefaultHostContainer());
84 factory.addModuleDescriptor("requiresRestart", RequiresRestartModuleDescriptor.class);
85 new PluginJarBuilder()
86 .addFormattedResource("atlassian-plugin.xml",
87 "<atlassian-plugin name='Test 2' key='test.restartrequired' pluginsVersion='2'>",
88 " <plugin-info>",
89 " <version>1.0</version>",
90 " </plugin-info>",
91 " <requiresRestart key='foo' />",
92 "</atlassian-plugin>")
93 .build(pluginsDir);
94
95 initPluginManager(null, factory);
96
97 assertEquals(1, pluginAccessor.getPlugins().size());
98 assertNotNull(pluginAccessor.getPlugin("test.restartrequired"));
99 assertTrue(pluginAccessor.isPluginEnabled("test.restartrequired"));
100 assertEquals(1, pluginAccessor.getEnabledModuleDescriptorsByClass(RequiresRestartModuleDescriptor.class).size());
101 assertEquals(PluginRestartState.NONE, pluginAccessor.getPluginRestartState("test.restartrequired"));
102
103 pluginController.disablePlugin("test.restartrequired");
104 assertFalse(pluginAccessor.isPluginEnabled("test.restartrequired"));
105 pluginController.enablePlugins("test.restartrequired");
106
107 assertEquals(1, pluginAccessor.getPlugins().size());
108 assertNotNull(pluginAccessor.getPlugin("test.restartrequired"));
109 assertTrue(pluginAccessor.isPluginEnabled("test.restartrequired"));
110 assertEquals(PluginRestartState.NONE, pluginAccessor.getPluginRestartState("test.restartrequired"));
111 assertEquals(1, pluginAccessor.getEnabledModuleDescriptorsByClass(RequiresRestartModuleDescriptor.class).size());
112 }
113
114 @Test
115 public void testEnableEnablesDependentPlugins() throws Exception {
116 installDependentPlugins();
117
118 Plugin provider = pluginAccessor.getPlugin("provider");
119 Plugin consumer = pluginAccessor.getPlugin("consumer");
120 assertEquals(PluginState.ENABLED, provider.getPluginState());
121 assertEquals(PluginState.ENABLED, consumer.getPluginState());
122
123 pluginController.disablePlugin("provider");
124 pluginController.disablePlugin("consumer");
125
126 assertEquals(PluginState.DISABLED, provider.getPluginState());
127 assertEquals(PluginState.DISABLED, consumer.getPluginState());
128
129 pluginController.enablePlugins("consumer");
130 assertEquals(PluginState.ENABLED, consumer.getPluginState());
131 assertEquals(PluginState.ENABLED, provider.getPluginState());
132 }
133
134 @Test
135 public void testDisablePersistsDisablesOfDependentPlugins() throws Exception {
136 installDependentPlugins();
137
138 Plugin provider = pluginAccessor.getPlugin("provider");
139 Plugin consumer = pluginAccessor.getPlugin("consumer");
140 assertEquals(PluginState.ENABLED, provider.getPluginState());
141 assertEquals(PluginState.ENABLED, consumer.getPluginState());
142
143 pluginController.disablePlugin("provider");
144
145 assertFalse("The provider should be disabled as we've disabled it explicitly", store.load().isEnabled(provider));
146 assertFalse("The consumer should be disabled as it depends on the provider", store.load().isEnabled(consumer));
147
148 }
149
150 @Test
151 public void testStoppedOsgiBundleDetected() throws Exception {
152 new PluginJarBuilder("osgi")
153 .addFormattedResource("META-INF/MANIFEST.MF",
154 "Manifest-Version: 1.0",
155 "Bundle-SymbolicName: my",
156 "Bundle-Version: 1.0",
157 "")
158 .build(pluginsDir);
159 initPluginManager();
160 Plugin plugin = pluginAccessor.getPlugin("my-1.0");
161 assertTrue("Enabled in accessor", pluginAccessor.isPluginEnabled("my-1.0"));
162 assertTrue("Enabled in plugin", plugin.getPluginState() == PluginState.ENABLED);
163
164 for (Bundle bundle : osgiContainerManager.getBundles()) {
165 if (bundle.getSymbolicName().equals("my")) {
166 bundle.stop();
167 }
168 }
169
170 assertFalse("Disabled in accessor", pluginAccessor.isPluginEnabled("my-1.0"));
171 assertTrue("Disabled in plugin", plugin.getPluginState() == PluginState.DISABLED);
172
173 }
174
175 @Test
176 public void testStoppedOsgiPluginDetected() throws Exception {
177 new PluginJarBuilder("osgi")
178 .addPluginInformation("my", "foo", "1.0")
179 .build(pluginsDir);
180 initPluginManager();
181 Plugin plugin = pluginAccessor.getPlugin("my");
182 assertTrue(pluginAccessor.isPluginEnabled("my"));
183 assertTrue(plugin.getPluginState() == PluginState.ENABLED);
184
185 for (Bundle bundle : osgiContainerManager.getBundles()) {
186 if (bundle.getSymbolicName().equals("my")) {
187 bundle.stop();
188 }
189 }
190
191 assertFalse(pluginAccessor.isPluginEnabled("my"));
192 assertTrue(plugin.getPluginState() == PluginState.DISABLED);
193
194 }
195
196 @Test
197 public void testEnableEnablesDependentPluginsWithBundles() throws Exception {
198 PluginJarBuilder builderProvider = new PluginJarBuilder("enabledisable-prov")
199 .addFormattedResource("META-INF/MANIFEST.MF",
200 "Manifest-Version: 1.0",
201 "Bundle-SymbolicName: my",
202 "Atlassian-Plugin-Key: provider",
203 "Export-Package: my",
204 "")
205 .addJava("my.Foo", "package my;" +
206 "public interface Foo {}");
207
208
209 PluginJarBuilder builderConsumer = new PluginJarBuilder("enabledisable-con", builderProvider.getClassLoader())
210 .addFormattedResource("atlassian-plugin.xml",
211 "<atlassian-plugin name='Test' key='consumer' pluginsVersion='2'>",
212 " <plugin-info>",
213 " <version>1.0</version>",
214 " <bundle-instructions><Import-Package>my</Import-Package></bundle-instructions>",
215 " </plugin-info>",
216 "</atlassian-plugin>")
217 .addJava("my2.Bar", "package my2;" +
218 "public class Bar implements my.Foo {}");
219
220 initPluginManager(null);
221 pluginController.installPlugins(new JarPluginArtifact(builderProvider.build()));
222 pluginController.installPlugins(new JarPluginArtifact(builderConsumer.build()));
223
224 Plugin provider = pluginAccessor.getPlugin("provider");
225 Plugin consumer = pluginAccessor.getPlugin("consumer");
226 assertEquals(PluginState.ENABLED, provider.getPluginState());
227 assertEquals(PluginState.ENABLED, consumer.getPluginState());
228
229 pluginController.disablePlugin("provider");
230 pluginController.disablePlugin("consumer");
231
232 assertEquals(PluginState.DISABLED, provider.getPluginState());
233 assertEquals(PluginState.DISABLED, consumer.getPluginState());
234
235 pluginController.enablePlugins("consumer");
236 assertEquals(PluginState.ENABLED, consumer.getPluginState());
237 assertEquals(PluginState.ENABLED, provider.getPluginState());
238 }
239
240 @Test
241 public void testDisableDoesNotKillLongRunningOperation() throws Exception {
242 File pluginJar = new PluginJarBuilder("longrunning")
243 .addFormattedResource("atlassian-plugin.xml",
244 "<atlassian-plugin name='Test' key='longrunning' pluginsVersion='2'>",
245 " <plugin-info>",
246 " <version>1.0</version>",
247 " </plugin-info>",
248 " <component key='comp' class='my.Foo' public='true'>",
249 " <interface>com.atlassian.plugin.osgi.Callable3</interface>",
250 " </component>",
251 "</atlassian-plugin>")
252 .addFormattedJava("my.Foo",
253 "package my;",
254 "import com.atlassian.plugin.osgi.*;",
255 "public class Foo implements Callable3{",
256 " private Callable2 callable;",
257 " public Foo(Callable2 callable) {",
258 " this.callable = callable;",
259 " }",
260 " public String call() throws Exception {",
261 " Thread.sleep(2000);",
262 " return callable.call();",
263 " }",
264 "}")
265 .build();
266 initPluginManager(new HostComponentProvider() {
267 public void provide(ComponentRegistrar registrar) {
268 registrar.register(Callable2.class).forInstance(new Callable2() {
269
270 public String call() {
271 return "called";
272 }
273 }).withName("foobar");
274 }
275 });
276
277 pluginController.installPlugins(new JarPluginArtifact(pluginJar));
278 assertTrue(pluginAccessor.getPlugin("longrunning").getPluginState() == PluginState.ENABLED);
279 final ServiceTracker tracker = osgiContainerManager.getServiceTracker("com.atlassian.plugin.osgi.Callable3");
280 final Callable3 service = (Callable3) tracker.getService();
281 final StringBuilder sb = new StringBuilder();
282 Thread t = new Thread() {
283 public void run() {
284 try {
285 sb.append(service.call());
286 } catch (Exception e) {
287 throw new RuntimeException(e);
288 }
289 }
290 };
291 t.start();
292 pluginController.disablePlugin("longrunning");
293 t.join();
294 assertEquals("called", sb.toString());
295 }
296
297 @RequiresRestart
298 public static class RequiresRestartModuleDescriptor extends AbstractModuleDescriptor<Void> {
299 public RequiresRestartModuleDescriptor() {
300 super(ModuleFactory.LEGACY_MODULE_FACTORY);
301 }
302
303 @Override
304 public Void getModule() {
305 throw new UnsupportedOperationException("You should never be getting a module from this descriptor " + this.getClass().getName());
306 }
307 }
308
309 private void installDependentPlugins() throws Exception
310 {
311 PluginJarBuilder builderProvider = new PluginJarBuilder("enabledisable-prov")
312 .addFormattedResource("atlassian-plugin.xml",
313 "<atlassian-plugin name='Test' key='provider' pluginsVersion='2'>",
314 " <plugin-info>",
315 " <version>1.0</version>",
316 " <bundle-instructions><Export-Package>my</Export-Package></bundle-instructions>",
317 " </plugin-info>",
318 "</atlassian-plugin>")
319 .addJava("my.Foo", "package my;" +
320 "public interface Foo {}");
321
322 PluginJarBuilder builderConsumer = new PluginJarBuilder("enabledisable-con", builderProvider.getClassLoader())
323 .addFormattedResource("atlassian-plugin.xml",
324 "<atlassian-plugin name='Test' key='consumer' pluginsVersion='2'>",
325 " <plugin-info>",
326 " <version>1.0</version>",
327 " <bundle-instructions><Import-Package>my</Import-Package></bundle-instructions>",
328 " </plugin-info>",
329 "</atlassian-plugin>")
330 .addJava("my2.Bar", "package my2;" +
331 "public class Bar implements my.Foo {}");
332
333 initPluginManager(null);
334 pluginController.installPlugins(new JarPluginArtifact(builderProvider.build()));
335 pluginController.installPlugins(new JarPluginArtifact(builderConsumer.build()));
336 }
337 }