1 package com.atlassian.plugin.osgi;
2
3 import com.atlassian.plugin.AutowireCapablePlugin;
4 import com.atlassian.plugin.DefaultModuleDescriptorFactory;
5 import com.atlassian.plugin.JarPluginArtifact;
6 import com.atlassian.plugin.Plugin;
7 import com.atlassian.plugin.PluginRestartState;
8 import com.atlassian.plugin.PluginState;
9 import com.atlassian.plugin.descriptors.AbstractModuleDescriptor;
10 import com.atlassian.plugin.descriptors.RequiresRestart;
11 import com.atlassian.plugin.hostcontainer.DefaultHostContainer;
12 import com.atlassian.plugin.osgi.hostcomponents.ComponentRegistrar;
13 import com.atlassian.plugin.osgi.hostcomponents.HostComponentProvider;
14 import com.atlassian.plugin.test.PluginJarBuilder;
15 import org.osgi.framework.Bundle;
16 import org.osgi.util.tracker.ServiceTracker;
17
18 import java.io.File;
19 import java.io.IOException;
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(((AutowireCapablePlugin)plugin).autowire(plugin.loadClass("my.Foo", this.getClass())));
34 pluginManager.disablePlugin("enabledisable");
35 pluginManager.enablePlugin("enabledisable");
36
37 plugin = pluginManager.getPlugin("enabledisable");
38
39 assertNotNull(((AutowireCapablePlugin)plugin).autowire(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(((AutowireCapablePlugin)plugin).autowire(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(((AutowireCapablePlugin)plugin).autowire(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
218 public void testStoppedOsgiPluginDetected() throws Exception
219 {
220 new PluginJarBuilder("osgi")
221 .addPluginInformation("my", "foo", "1.0")
222 .build(pluginsDir);
223 initPluginManager();
224 Plugin plugin = pluginManager.getPlugin("my");
225 assertTrue(pluginManager.isPluginEnabled("my"));
226 assertTrue(plugin.getPluginState() == PluginState.ENABLED);
227
228 for (Bundle bundle : osgiContainerManager.getBundles())
229 {
230 if (bundle.getSymbolicName().equals("my"))
231 {
232 bundle.stop();
233 }
234 }
235
236 assertFalse(pluginManager.isPluginEnabled("my"));
237 assertTrue(plugin.getPluginState() == PluginState.DISABLED);
238
239 }
240
241
242 public void testEnableEnablesDependentPluginsWithBundles() throws Exception
243 {
244 PluginJarBuilder builderProvider = new PluginJarBuilder("enabledisable-prov")
245 .addFormattedResource("META-INF/MANIFEST.MF",
246 "Manifest-Version: 1.0",
247 "Bundle-SymbolicName: my",
248 "Atlassian-Plugin-Key: provider",
249 "Export-Package: my",
250 "")
251 .addJava("my.Foo", "package my;" +
252 "public interface Foo {}");
253
254
255
256 PluginJarBuilder builderConsumer = new PluginJarBuilder("enabledisable-con", builderProvider.getClassLoader())
257 .addFormattedResource("atlassian-plugin.xml",
258 "<atlassian-plugin name='Test' key='consumer' pluginsVersion='2'>",
259 " <plugin-info>",
260 " <version>1.0</version>",
261 " <bundle-instructions><Import-Package>my</Import-Package></bundle-instructions>",
262 " </plugin-info>",
263 "</atlassian-plugin>")
264 .addJava("my2.Bar", "package my2;" +
265 "public class Bar implements my.Foo {}");
266
267 initPluginManager(null);
268 pluginManager.installPlugin(new JarPluginArtifact(builderProvider.build()));
269 pluginManager.installPlugin(new JarPluginArtifact(builderConsumer.build()));
270
271 Plugin provider = pluginManager.getPlugin("provider");
272 Plugin consumer = pluginManager.getPlugin("consumer");
273 assertEquals(PluginState.ENABLED, provider.getPluginState());
274 assertEquals(PluginState.ENABLED, consumer.getPluginState());
275
276 pluginManager.disablePlugin("provider");
277 pluginManager.disablePlugin("consumer");
278
279 assertEquals(PluginState.DISABLED, provider.getPluginState());
280 assertEquals(PluginState.DISABLED, consumer.getPluginState());
281
282 pluginManager.enablePlugin("consumer");
283 assertEquals(PluginState.ENABLED, consumer.getPluginState());
284 assertEquals(PluginState.ENABLED, provider.getPluginState());
285 }
286
287 public void testDisableDoesNotKillLongRunningOperation() throws Exception
288 {
289 File pluginJar = new PluginJarBuilder("longrunning")
290 .addFormattedResource("atlassian-plugin.xml",
291 "<atlassian-plugin name='Test' key='longrunning' pluginsVersion='2'>",
292 " <plugin-info>",
293 " <version>1.0</version>",
294 " </plugin-info>",
295 " <component key='comp' class='my.Foo' public='true'>",
296 " <interface>com.atlassian.plugin.osgi.Callable3</interface>",
297 " </component>",
298 "</atlassian-plugin>")
299 .addFormattedJava("my.Foo",
300 "package my;",
301 "import com.atlassian.plugin.osgi.*;",
302 "public class Foo implements Callable3{",
303 " private Callable2 callable;",
304 " public Foo(Callable2 callable) {",
305 " this.callable = callable;",
306 " }",
307 " public String call() throws Exception {",
308 " Thread.sleep(2000);",
309 " return callable.call();",
310 " }",
311 "}")
312 .build();
313 initPluginManager(new HostComponentProvider()
314 {
315 public void provide(ComponentRegistrar registrar)
316 {
317 registrar.register(Callable2.class).forInstance(new Callable2()
318 {
319
320 public String call()
321 {
322 return "called";
323 }
324 }).withName("foobar");
325 }
326 });
327
328 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
329 assertTrue(pluginManager.getPlugin("longrunning").getPluginState() == PluginState.ENABLED);
330 final ServiceTracker tracker = osgiContainerManager.getServiceTracker("com.atlassian.plugin.osgi.Callable3");
331 final Callable3 service = (Callable3) tracker.getService();
332 final StringBuilder sb = new StringBuilder();
333 Thread t = new Thread()
334 {
335 public void run()
336 {
337 try
338 {
339 sb.append(service.call());
340 }
341 catch (Exception e)
342 {
343 throw new RuntimeException(e);
344 }
345 }
346 };
347 t.start();
348 pluginManager.disablePlugin("longrunning");
349 t.join();
350 assertEquals("called", sb.toString());
351 }
352
353 @RequiresRestart
354 public static class RequiresRestartModuleDescriptor extends AbstractModuleDescriptor
355 {
356 @Override
357 public Void getModule()
358 {
359 throw new UnsupportedOperationException("You should never be getting a module from this descriptor " + this.getClass().getName());
360 }
361 }
362 }