View Javadoc

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     /* This won't work until we do detection at a higher level than the plugin object
178     public void testStartedOsgiBundleDetected() throws Exception
179     {
180         new PluginJarBuilder("osgi")
181                 .addFormattedResource("META-INF/MANIFEST.MF",
182                     "Manifest-Version: 1.0",
183                     "Bundle-SymbolicName: my",
184                     "Bundle-Version: 1.0",
185                     "")
186                 .build(pluginsDir);
187         initPluginManager();
188         Plugin plugin = pluginManager.getPlugin("my-1.0");
189         assertTrue(pluginManager.isPluginEnabled("my-1.0"));
190         assertTrue(plugin.getPluginState() == PluginState.ENABLED);
191 
192         for (Bundle bundle : osgiContainerManager.getBundles())
193         {
194             if (bundle.getSymbolicName().equals("my"))
195             {
196                 bundle.stop();
197                 bundle.start();
198             }
199         }
200 
201         assertTrue(WaitUntil.invoke(new WaitUntil.WaitCondition()
202         {
203             public boolean isFinished()
204             {
205                 return pluginManager.isPluginEnabled("my-1.0");
206             }
207 
208             public String getWaitMessage()
209             {
210                 return null;
211             }
212         }));
213         assertTrue(pluginManager.isPluginEnabled("my-1.0"));
214         assertTrue(plugin.getPluginState() == PluginState.ENABLED);
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 }