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