View Javadoc
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 }