1   package com.atlassian.plugin.osgi;
2   
3   import com.atlassian.plugin.osgi.hostcomponents.HostComponentProvider;
4   import com.atlassian.plugin.osgi.hostcomponents.ComponentRegistrar;
5   import com.atlassian.plugin.osgi.factory.OsgiPlugin;
6   import com.atlassian.plugin.test.PluginJarBuilder;
7   import com.atlassian.plugin.JarPluginArtifact;
8   import com.atlassian.plugin.ModuleDescriptor;
9   import com.atlassian.plugin.Plugin;
10  import com.atlassian.plugin.descriptors.UnrecognisedModuleDescriptor;
11  import com.atlassian.plugin.web.descriptors.WebItemModuleDescriptor;
12  import com.atlassian.plugin.util.WaitUntil;
13  
14  import java.io.File;
15  import java.util.Collection;
16  import java.util.List;
17  import java.util.Set;
18  import java.util.Collections;
19  import java.util.HashSet;
20  
21  import org.osgi.framework.BundleContext;
22  import org.osgi.framework.ServiceRegistration;
23  import org.osgi.framework.ServiceReference;
24  import org.osgi.framework.Bundle;
25  
26  public class TestDynamicPluginModule extends PluginInContainerTestBase
27  {
28      public void testDynamicPluginModule() throws Exception
29      {
30          initPluginManager(new HostComponentProvider()
31          {
32              public void provide(final ComponentRegistrar registrar)
33              {
34              }
35          });
36  
37          final File pluginJar = new PluginJarBuilder("pluginType")
38                  .addFormattedResource("atlassian-plugin.xml",
39                          "<atlassian-plugin name='Test' key='test.plugin.module' pluginsVersion='2'>",
40                          "    <plugin-info>",
41                          "        <version>1.0</version>",
42                          "    </plugin-info>",
43                          "    <component key='factory' class='foo.MyModuleDescriptorFactory' public='true'>",
44                          "       <interface>com.atlassian.plugin.ModuleDescriptorFactory</interface>",
45                          "    </component>",
46                          "</atlassian-plugin>")
47                  .addFormattedJava("foo.MyModuleDescriptor",
48                          "package foo;",
49                          "public class MyModuleDescriptor extends com.atlassian.plugin.descriptors.AbstractModuleDescriptor {",
50                          "  public Object getModule(){return null;}",
51                          "}")
52                  .addFormattedJava("foo.MyModuleDescriptorFactory",
53                          "package foo;",
54                          "public class MyModuleDescriptorFactory extends com.atlassian.plugin.DefaultModuleDescriptorFactory {",
55                          "  public MyModuleDescriptorFactory() {",
56                          "    super();",
57                          "    addModuleDescriptor('foo', MyModuleDescriptor.class);",
58                          "  }",
59                          "}")
60                  .build();
61          final File pluginJar2 = new PluginJarBuilder("fooUser")
62                  .addFormattedResource("atlassian-plugin.xml",
63                          "<atlassian-plugin name='Test 2' key='test.plugin' pluginsVersion='2'>",
64                          "    <plugin-info>",
65                          "        <version>1.0</version>",
66                          "    </plugin-info>",
67                          "    <foo key='dum2'/>",
68                          "</atlassian-plugin>")
69                  .build();
70  
71          pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
72          pluginManager.installPlugin(new JarPluginArtifact(pluginJar2));
73          final Collection<ModuleDescriptor<?>> descriptors = pluginManager.getPlugin("test.plugin")
74                  .getModuleDescriptors();
75          assertEquals(1, descriptors.size());
76          final ModuleDescriptor<?> descriptor = descriptors.iterator()
77                  .next();
78          assertEquals("MyModuleDescriptor", descriptor.getClass().getSimpleName());
79      }
80  
81      public void testDynamicPluginModuleNotLinkToAllPlugins() throws Exception
82      {
83          new PluginJarBuilder("pluginType")
84                  .addFormattedResource("atlassian-plugin.xml",
85                          "<atlassian-plugin name='Test' key='test.plugin.module' pluginsVersion='2'>",
86                          "    <plugin-info>",
87                          "        <version>1.0</version>",
88                          "    </plugin-info>",
89                          "    <module-type key='foo' class='foo.MyModuleDescriptor'/>",
90                          "</atlassian-plugin>")
91                  .addFormattedJava("foo.MyModuleDescriptor",
92                          "package foo;",
93                          "public class MyModuleDescriptor extends com.atlassian.plugin.descriptors.AbstractModuleDescriptor {",
94                          "  public Object getModule(){return null;}",
95                          "}")
96                  .build(pluginsDir);
97          new PluginJarBuilder("fooUser")
98                  .addFormattedResource("atlassian-plugin.xml",
99                          "<atlassian-plugin name='Test 2' key='test.plugin' pluginsVersion='2'>",
100                         "    <plugin-info>",
101                         "        <version>1.0</version>",
102                         "    </plugin-info>",
103                         "    <foo key='dum2'/>",
104                         "</atlassian-plugin>")
105                 .build(pluginsDir);
106         new PluginJarBuilder("foootherUser")
107                 .addPluginInformation("unusing.plugin", "Unusing plugin", "1.0")
108                 .build(pluginsDir);
109 
110         initPluginManager(new HostComponentProvider()
111         {
112             public void provide(final ComponentRegistrar registrar)
113             {
114             }
115         });
116 
117         assertEquals("MyModuleDescriptor", pluginManager.getPlugin("test.plugin").getModuleDescriptor("dum2").getClass().getSimpleName());
118         Set<String> deps = findDependentBundles(((OsgiPlugin) pluginManager.getPlugin("test.plugin.module")).getBundle());
119         assertTrue(deps.contains("test.plugin"));
120         assertFalse(deps.contains("unusing.plugin"));
121     }
122 
123     private Set<String> findDependentBundles(Bundle bundle)
124     {
125         Set<String> deps = new HashSet<String>();
126         final ServiceReference[] registeredServices = bundle.getRegisteredServices();
127         if (registeredServices == null)
128         {
129             return deps;
130         }
131 
132         for (final ServiceReference serviceReference : registeredServices)
133         {
134             final Bundle[] usingBundles = serviceReference.getUsingBundles();
135             if (usingBundles == null)
136             {
137                 continue;
138             }
139             for (final Bundle usingBundle : usingBundles)
140             {
141                 deps.add(usingBundle.getSymbolicName());
142             }
143         }
144         return deps;
145     }
146 
147     public void testDynamicPluginModuleUsingModuleTypeDescriptor() throws Exception
148     {
149         initPluginManager(new HostComponentProvider()
150         {
151             public void provide(final ComponentRegistrar registrar)
152             {
153             }
154         });
155 
156         final File pluginJar = new PluginJarBuilder("pluginType")
157                 .addFormattedResource("atlassian-plugin.xml",
158                         "<atlassian-plugin name='Test' key='test.plugin.module' pluginsVersion='2'>",
159                         "    <plugin-info>",
160                         "        <version>1.0</version>",
161                         "    </plugin-info>",
162                         "    <module-type key='foo' class='foo.MyModuleDescriptor' />",
163                         "</atlassian-plugin>")
164                 .addFormattedJava("foo.MyModuleDescriptor",
165                         "package foo;",
166                         "public class MyModuleDescriptor extends com.atlassian.plugin.descriptors.AbstractModuleDescriptor {",
167                         "  public Object getModule(){return null;}",
168                         "}")
169                 .build();
170         final File pluginJar2 = new PluginJarBuilder("fooUser")
171                 .addFormattedResource("atlassian-plugin.xml",
172                         "<atlassian-plugin name='Test 2' key='test.plugin' pluginsVersion='2'>",
173                         "    <plugin-info>",
174                         "        <version>1.0</version>",
175                         "    </plugin-info>",
176                         "    <foo key='dum2'/>",
177                         "</atlassian-plugin>")
178                 .build();
179 
180         pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
181         pluginManager.installPlugin(new JarPluginArtifact(pluginJar2));
182         WaitUntil.invoke(new BasicWaitCondition()
183         {
184             public boolean isFinished()
185             {
186                 return pluginManager.getPlugin("test.plugin")
187                         .getModuleDescriptor("dum2")
188                         .getClass()
189                         .getSimpleName()
190                         .equals("MyModuleDescriptor");
191             }
192         });
193         final Collection<ModuleDescriptor<?>> descriptors = pluginManager.getPlugin("test.plugin")
194                 .getModuleDescriptors();
195         assertEquals(1, descriptors.size());
196         final ModuleDescriptor<?> descriptor = descriptors.iterator()
197                 .next();
198         assertEquals("MyModuleDescriptor", descriptor.getClass().getSimpleName());
199     }
200 
201 
202     public void testDynamicPluginModuleUsingModuleTypeDescriptorAndComponentInjection() throws Exception
203     {
204         initPluginManager(new HostComponentProvider()
205         {
206             public void provide(final ComponentRegistrar registrar)
207             {
208             }
209         });
210 
211         final File pluginJar = new PluginJarBuilder("pluginType")
212                 .addFormattedResource("atlassian-plugin.xml",
213                         "<atlassian-plugin name='Test' key='test.plugin.module' pluginsVersion='2'>",
214                         "    <plugin-info>",
215                         "        <version>1.0</version>",
216                         "    </plugin-info>",
217                         "    <component key='comp' class='foo.MyComponent' />",
218                         "    <module-type key='foo' class='foo.MyModuleDescriptor' />",
219                         "</atlassian-plugin>")
220                 .addFormattedJava("foo.MyComponent",
221                         "package foo;",
222                         "public class MyComponent {",
223                         "}")
224                 .addFormattedJava("foo.MyModuleDescriptor",
225                         "package foo;",
226                         "public class MyModuleDescriptor extends com.atlassian.plugin.descriptors.AbstractModuleDescriptor {",
227                         "  public MyModuleDescriptor(MyComponent comp) {}",
228                         "  public Object getModule(){return null;}",
229                         "}")
230 
231                 .build();
232         final File pluginJar2 = new PluginJarBuilder("fooUser")
233                 .addFormattedResource("atlassian-plugin.xml",
234                         "<atlassian-plugin name='Test 2' key='test.plugin' pluginsVersion='2'>",
235                         "    <plugin-info>",
236                         "        <version>1.0</version>",
237                         "    </plugin-info>",
238                         "    <foo key='dum2'/>",
239                         "</atlassian-plugin>")
240                 .build();
241 
242         pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
243         pluginManager.installPlugin(new JarPluginArtifact(pluginJar2));
244         WaitUntil.invoke(new BasicWaitCondition()
245         {
246             public boolean isFinished()
247             {
248                 return pluginManager.getPlugin("test.plugin")
249                         .getModuleDescriptors()
250                         .iterator()
251                         .next()
252                         .getClass()
253                         .getSimpleName()
254                         .equals("MyModuleDescriptor");
255             }
256         });
257         final Collection<ModuleDescriptor<?>> descriptors = pluginManager.getPlugin("test.plugin")
258                 .getModuleDescriptors();
259         assertEquals(1, descriptors.size());
260         final ModuleDescriptor<?> descriptor = descriptors.iterator()
261                 .next();
262         assertEquals("MyModuleDescriptor", descriptor.getClass().getSimpleName());
263     }
264 
265     public void testDynamicPluginModuleUsingModuleTypeDescriptorAfterTheFact() throws Exception
266     {
267         initPluginManager(new HostComponentProvider()
268         {
269             public void provide(final ComponentRegistrar registrar)
270             {
271             }
272         });
273 
274         final File pluginJar = new PluginJarBuilder("pluginType")
275                 .addFormattedResource("atlassian-plugin.xml",
276                         "<atlassian-plugin name='Test' key='test.plugin.module' pluginsVersion='2'>",
277                         "    <plugin-info>",
278                         "        <version>1.0</version>",
279                         "    </plugin-info>",
280                         "    <module-type key='foo' class='foo.MyModuleDescriptor' />",
281                         "</atlassian-plugin>")
282                 .addFormattedJava("foo.MyModuleDescriptor",
283                         "package foo;",
284                         "public class MyModuleDescriptor extends com.atlassian.plugin.descriptors.AbstractModuleDescriptor {",
285                         "  public Object getModule(){return null;}",
286                         "}")
287                 .build();
288         final File pluginJar2 = new PluginJarBuilder("fooUser")
289                 .addFormattedResource("atlassian-plugin.xml",
290                         "<atlassian-plugin name='Test 2' key='test.plugin' pluginsVersion='2'>",
291                         "    <plugin-info>",
292                         "        <version>1.0</version>",
293                         "    </plugin-info>",
294                         "    <foo key='dum2'/>",
295                         "</atlassian-plugin>")
296                 .build();
297 
298         pluginManager.installPlugin(new JarPluginArtifact(pluginJar2));
299         pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
300         WaitUntil.invoke(new BasicWaitCondition()
301         {
302             public boolean isFinished()
303             {
304                 return pluginManager.getPlugin("test.plugin")
305                         .getModuleDescriptors()
306                         .iterator()
307                         .next()
308                         .getClass()
309                         .getSimpleName()
310                         .equals("MyModuleDescriptor");
311             }
312         });
313 
314         Collection<ModuleDescriptor<?>> descriptors = pluginManager.getPlugin("test.plugin")
315                 .getModuleDescriptors();
316         assertEquals(1, descriptors.size());
317         ModuleDescriptor<?> descriptor = descriptors.iterator()
318                 .next();
319         assertEquals("MyModuleDescriptor", descriptor.getClass().getSimpleName());
320 
321         pluginManager.uninstall(pluginManager.getPlugin("test.plugin.module"));
322         WaitUntil.invoke(new BasicWaitCondition()
323         {
324             public boolean isFinished()
325             {
326                 return pluginManager.getPlugin("test.plugin")
327                         .getModuleDescriptors()
328                         .iterator()
329                         .next()
330                         .getClass()
331                         .getSimpleName()
332                         .equals("UnrecognisedModuleDescriptor");
333             }
334         });
335         descriptors = pluginManager.getPlugin("test.plugin")
336                 .getModuleDescriptors();
337         assertEquals(1, descriptors.size());
338         descriptor = descriptors.iterator()
339                 .next();
340         assertEquals("UnrecognisedModuleDescriptor", descriptor.getClass().getSimpleName());
341 
342         pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
343         descriptors = pluginManager.getPlugin("test.plugin")
344                 .getModuleDescriptors();
345         assertEquals(1, descriptors.size());
346         descriptor = descriptors.iterator()
347                 .next();
348         assertEquals("MyModuleDescriptor", descriptor.getClass().getSimpleName());
349     }
350 
351     public void testDynamicPluginModuleUsingModuleTypeDescriptorAfterTheFactWithException() throws Exception
352     {
353         initPluginManager(new HostComponentProvider()
354         {
355             public void provide(final ComponentRegistrar registrar)
356             {
357             }
358         });
359 
360         final File pluginJar = new PluginJarBuilder("pluginType")
361                 .addFormattedResource("atlassian-plugin.xml",
362                         "<atlassian-plugin name='Test' key='test.plugin.module' pluginsVersion='2'>",
363                         "    <plugin-info>",
364                         "        <version>1.0</version>",
365                         "    </plugin-info>",
366                         "    <module-type key='foo' class='foo.MyModuleDescriptor' />",
367                         "</atlassian-plugin>")
368                 .addFormattedJava("foo.MyModuleDescriptor",
369                         "package foo;",
370                         "public class MyModuleDescriptor extends com.atlassian.plugin.descriptors.AbstractModuleDescriptor {",
371                         "  public MyModuleDescriptor() {",
372                         "    throw new RuntimeException('error loading module');",
373                         "  }",
374                         "  public Object getModule(){return null;}",
375                         "}")
376                 .build();
377         final File pluginJar2 = new PluginJarBuilder("fooUser")
378                 .addFormattedResource("atlassian-plugin.xml",
379                         "<atlassian-plugin name='Test 2' key='test.plugin' pluginsVersion='2'>",
380                         "    <plugin-info>",
381                         "        <version>1.0</version>",
382                         "    </plugin-info>",
383                         "    <foo key='dum2'/>",
384                         "</atlassian-plugin>")
385                 .build();
386 
387         pluginManager.installPlugin(new JarPluginArtifact(pluginJar2));
388         pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
389         assertTrue(WaitUntil.invoke(new BasicWaitCondition()
390         {
391             public boolean isFinished()
392             {
393                 UnrecognisedModuleDescriptor des = (UnrecognisedModuleDescriptor) pluginManager.getPlugin("test.plugin").getModuleDescriptor("dum2");
394                 return des.getErrorText().contains("error loading module");
395             }
396         }));
397 
398     }
399 
400     public void testDynamicPluginModuleUsingModuleTypeDescriptorInSamePlugin() throws Exception
401     {
402         initPluginManager(new HostComponentProvider()
403         {
404             public void provide(final ComponentRegistrar registrar)
405             {
406             }
407         });
408 
409         final File pluginJar = new PluginJarBuilder("pluginType")
410                 .addFormattedResource("atlassian-plugin.xml",
411                         "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
412                         "    <plugin-info>",
413                         "        <version>1.0</version>",
414                         "    </plugin-info>",
415                         "    <module-type key='foo' class='foo.MyModuleDescriptor' />",
416                         "    <foo key='dum2' />",
417                         "</atlassian-plugin>")
418                 .addFormattedJava("foo.MyModuleDescriptor",
419                         "package foo;",
420                         "public class MyModuleDescriptor extends com.atlassian.plugin.descriptors.AbstractModuleDescriptor {",
421                         "  public Object getModule(){return null;}",
422                         "}")
423                 .build();
424 
425         pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
426         WaitUntil.invoke(new BasicWaitCondition()
427         {
428             public boolean isFinished()
429             {
430                 return pluginManager.getPlugin("test.plugin")
431                         .getModuleDescriptor("dum2")
432                         .getClass()
433                         .getSimpleName()
434                         .equals("MyModuleDescriptor");
435             }
436         });
437         final Collection<ModuleDescriptor<?>> descriptors = pluginManager.getPlugin("test.plugin")
438                 .getModuleDescriptors();
439         assertEquals(2, descriptors.size());
440         final ModuleDescriptor<?> descriptor = pluginManager.getPlugin("test.plugin")
441                 .getModuleDescriptor("dum2");
442         assertEquals("MyModuleDescriptor", descriptor.getClass().getSimpleName());
443     }
444 
445     public void testDynamicModuleDescriptor() throws Exception
446     {
447         initPluginManager(null);
448 
449         final File pluginJar = new PluginJarBuilder("pluginType").addPluginInformation("test.plugin", "foo", "1.0")
450                 .build();
451 
452         pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
453         final BundleContext ctx = ((OsgiPlugin) pluginManager.getPlugin("test.plugin")).getBundle()
454                 .getBundleContext();
455         final ServiceRegistration reg = ctx.registerService(ModuleDescriptor.class.getName(), new DummyWebItemModuleDescriptor(), null);
456 
457         final Collection<ModuleDescriptor<?>> descriptors = pluginManager.getPlugin("test.plugin")
458                 .getModuleDescriptors();
459         assertEquals(1, descriptors.size());
460         final ModuleDescriptor<?> descriptor = descriptors.iterator()
461                 .next();
462         assertEquals("DummyWebItemModuleDescriptor", descriptor.getClass().getSimpleName());
463         List<WebItemModuleDescriptor> list = pluginManager.getEnabledModuleDescriptorsByClass(WebItemModuleDescriptor.class);
464         assertEquals(1, list.size());
465         reg.unregister();
466         list = pluginManager.getEnabledModuleDescriptorsByClass(WebItemModuleDescriptor.class);
467         assertEquals(0, list.size());
468     }
469 
470     public void testDynamicModuleDescriptorIsolatedToPlugin() throws Exception
471     {
472         initPluginManager(null);
473 
474         final File pluginJar = new PluginJarBuilder("pluginType").addPluginInformation("test.plugin", "foo", "1.0")
475                 .build();
476 
477         pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
478         final BundleContext ctx = ((OsgiPlugin) pluginManager.getPlugin("test.plugin")).getBundle()
479                 .getBundleContext();
480         ctx.registerService(ModuleDescriptor.class.getName(), new DummyWebItemModuleDescriptor(), null);
481 
482         final File pluginJar2 = new PluginJarBuilder("pluginType").addPluginInformation("test.plugin2", "foo", "1.0")
483                 .build();
484         pluginManager.installPlugin(new JarPluginArtifact(pluginJar2));
485         final BundleContext ctx2 = ((OsgiPlugin) pluginManager.getPlugin("test.plugin2")).getBundle()
486                 .getBundleContext();
487         final ServiceRegistration reg2 = ctx2.registerService(ModuleDescriptor.class.getName(), new DummyWebItemModuleDescriptor(), null);
488 
489         Collection<ModuleDescriptor<?>> descriptors = pluginManager.getPlugin("test.plugin")
490                 .getModuleDescriptors();
491         assertEquals(1, descriptors.size());
492         final ModuleDescriptor<?> descriptor = descriptors.iterator()
493                 .next();
494         assertEquals("DummyWebItemModuleDescriptor", descriptor.getClass().getSimpleName());
495         List<WebItemModuleDescriptor> list = pluginManager.getEnabledModuleDescriptorsByClass(WebItemModuleDescriptor.class);
496         assertEquals(2, list.size());
497         reg2.unregister();
498         list = pluginManager.getEnabledModuleDescriptorsByClass(WebItemModuleDescriptor.class);
499         assertEquals(1, list.size());
500         descriptors = pluginManager.getPlugin("test.plugin")
501                 .getModuleDescriptors();
502         assertEquals(1, descriptors.size());
503     }
504 }