1 package it.com.atlassian.plugin.osgi;
2
3 import com.atlassian.fugue.Pair;
4 import com.atlassian.plugin.DefaultModuleDescriptorFactory;
5 import com.atlassian.plugin.PluginArtifact;
6 import com.atlassian.plugin.event.PluginEventListener;
7 import com.atlassian.plugin.event.events.PluginModuleDisabledEvent;
8 import com.atlassian.plugin.event.events.PluginModuleEnabledEvent;
9 import com.atlassian.plugin.osgi.BasicWaitCondition;
10 import com.atlassian.plugin.osgi.DummyModuleDescriptorWithKey;
11 import com.atlassian.plugin.osgi.EventTrackingModuleDescriptor;
12 import com.atlassian.plugin.osgi.PluginInContainerTestBase;
13 import com.atlassian.plugin.osgi.hostcomponents.HostComponentProvider;
14 import com.atlassian.plugin.osgi.hostcomponents.ComponentRegistrar;
15 import com.atlassian.plugin.osgi.factory.OsgiPlugin;
16 import com.atlassian.plugin.test.PluginJarBuilder;
17 import com.atlassian.plugin.JarPluginArtifact;
18 import com.atlassian.plugin.ModuleDescriptor;
19 import com.atlassian.plugin.descriptors.UnrecognisedModuleDescriptor;
20 import com.atlassian.plugin.util.WaitUntil;
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.util.Collection;
25 import java.util.List;
26 import java.util.Set;
27 import java.util.HashSet;
28
29 import my.FooModule;
30 import my.FooModuleDescriptor;
31 import org.osgi.framework.BundleContext;
32 import org.osgi.framework.ServiceRegistration;
33 import org.osgi.framework.ServiceReference;
34 import org.osgi.framework.Bundle;
35
36 public class TestDynamicPluginModule extends PluginInContainerTestBase
37 {
38 public void testDynamicPluginModule() throws Exception
39 {
40 initPluginManager(new HostComponentProvider()
41 {
42 public void provide(final ComponentRegistrar registrar)
43 {
44 }
45 });
46
47 final File pluginJar = new PluginJarBuilder("pluginType")
48 .addFormattedResource("atlassian-plugin.xml",
49 "<atlassian-plugin name='Test' key='test.plugin.module' pluginsVersion='2'>",
50 " <plugin-info>",
51 " <version>1.0</version>",
52 " </plugin-info>",
53 " <component key='factory' class='foo.MyModuleDescriptorFactory' public='true'>",
54 " <interface>com.atlassian.plugin.ModuleDescriptorFactory</interface>",
55 " </component>",
56 "</atlassian-plugin>")
57 .addFormattedJava(getMyModuleDescriptorClass().left(), getMyModuleDescriptorClass().right())
58 .addFormattedJava("foo.MyModuleDescriptorFactory",
59 "package foo;",
60 "public class MyModuleDescriptorFactory extends com.atlassian.plugin.DefaultModuleDescriptorFactory {",
61 " public MyModuleDescriptorFactory() {",
62 " super();",
63 " addModuleDescriptor('foo', MyModuleDescriptor.class);",
64 " }",
65 "}")
66 .build();
67 final File pluginJar2 = buildDynamicModuleClientJar();
68
69 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
70 pluginManager.installPlugin(new JarPluginArtifact(pluginJar2));
71 final Collection<ModuleDescriptor<?>> descriptors = pluginManager.getPlugin("test.plugin").getModuleDescriptors();
72 assertEquals(1, descriptors.size());
73 final ModuleDescriptor<?> descriptor = descriptors.iterator()
74 .next();
75 assertEquals("MyModuleDescriptor", descriptor.getClass().getSimpleName());
76 }
77
78 public void testDynamicPluginModuleUsingModuleTypeDescriptorWithReinstall() throws Exception
79 {
80 initPluginManager();
81
82 final File pluginJar = new PluginJarBuilder("pluginType")
83 .addFormattedResource("atlassian-plugin.xml",
84 "<atlassian-plugin name='Test' key='test.plugin.module' pluginsVersion='2'>",
85 " <plugin-info>",
86 " <version>1.0</version>",
87 " </plugin-info>",
88 " <module-type key='foo' class='foo.MyModuleDescriptor' />",
89 "</atlassian-plugin>")
90 .addFormattedJava(getMyModuleDescriptorClass().left(), getMyModuleDescriptorClass().right())
91 .build();
92 final File pluginJar2 = buildDynamicModuleClientJar();
93
94 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
95 pluginManager.installPlugin(new JarPluginArtifact(pluginJar2));
96 assertTrue(waitForDynamicModuleEnabled());
97
98
99 pluginManager.uninstall(pluginManager.getPlugin("test.plugin.module"));
100 WaitUntil.invoke(new BasicWaitCondition()
101 {
102 public boolean isFinished()
103 {
104 ModuleDescriptor<?> descriptor = pluginManager.getPlugin("test.plugin")
105 .getModuleDescriptors()
106 .iterator()
107 .next();
108 boolean enabled = pluginManager.isPluginModuleEnabled(descriptor.getCompleteKey());
109 return descriptor
110 .getClass()
111 .getSimpleName()
112 .equals("UnrecognisedModuleDescriptor")
113 && !enabled;
114 }
115 });
116
117 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
118 assertTrue(waitForDynamicModuleEnabled());
119 }
120
121 public void testDynamicPluginModuleUsingModuleTypeDescriptorWithImmediateReinstall() throws Exception
122 {
123 initPluginManager();
124
125 final File pluginJar = new PluginJarBuilder("pluginType")
126 .addFormattedResource("atlassian-plugin.xml",
127 "<atlassian-plugin name='Test' key='test.plugin.module' pluginsVersion='2'>",
128 " <plugin-info>",
129 " <version>1.0</version>",
130 " </plugin-info>",
131 " <module-type key='foo' class='foo.MyModuleDescriptor' />",
132 "</atlassian-plugin>")
133 .addFormattedJava(getMyModuleDescriptorClass().left(), getMyModuleDescriptorClass().right())
134 .build();
135 final File pluginJar2 = buildDynamicModuleClientJar();
136
137 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
138 pluginManager.installPlugin(new JarPluginArtifact(pluginJar2));
139 assertTrue(waitForDynamicModuleEnabled());
140
141 PluginModuleDisabledListener disabledListener = new PluginModuleDisabledListener("dum2");
142 PluginModuleEnabledListener enabledListener = new PluginModuleEnabledListener("dum2");
143 pluginEventManager.register(disabledListener);
144 pluginEventManager.register(enabledListener);
145
146
147 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
148 assertTrue(waitForDynamicModuleEnabled());
149
150 assertEquals(1, enabledListener.called);
151 assertEquals(1, disabledListener.called);
152 }
153
154 public void testDynamicPluginModuleUsingModuleTypeDescriptorWithImmediateReinstallOfBoth() throws Exception
155 {
156 initPluginManager();
157
158 final File pluginJar = new PluginJarBuilder("pluginType")
159 .addFormattedResource("atlassian-plugin.xml",
160 "<atlassian-plugin name='Test' key='test.plugin.module' pluginsVersion='2'>",
161 " <plugin-info>",
162 " <version>1.0</version>",
163 " </plugin-info>",
164 " <module-type key='foo' class='foo.MyModuleDescriptor' />",
165 "</atlassian-plugin>")
166 .addFormattedJava(getMyModuleDescriptorClass().left(), getMyModuleDescriptorClass().right())
167 .build();
168 final File pluginJar2 = buildDynamicModuleClientJar();
169
170 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
171 pluginManager.installPlugin(new JarPluginArtifact(pluginJar2));
172
173 assertTrue(waitForDynamicModuleEnabled());
174
175 PluginModuleDisabledListener disabledListener = new PluginModuleDisabledListener("dum2");
176 PluginModuleEnabledListener enabledListener = new PluginModuleEnabledListener("dum2");
177 pluginEventManager.register(disabledListener);
178 pluginEventManager.register(enabledListener);
179
180
181 pluginManager.installPlugins(new JarPluginArtifact(pluginJar2), new JarPluginArtifact(pluginJar));
182 assertTrue(waitForDynamicModuleEnabled());
183
184 assertEquals(pluginManager.getPluginModule("test.plugin:dum2").getClass(), pluginManager.getPlugin("test.plugin.module").<Object>loadClass("foo.MyModuleDescriptor", null));
185
186 assertEquals(1, enabledListener.called);
187 assertEquals(1, disabledListener.called);
188 }
189
190 private File buildDynamicModuleClientJar() throws IOException
191 {
192 return new PluginJarBuilder("fooUser")
193 .addFormattedResource("atlassian-plugin.xml",
194 "<atlassian-plugin name='Test 2' key='test.plugin' pluginsVersion='2'>",
195 " <plugin-info>",
196 " <version>1.0</version>",
197 " </plugin-info>",
198 " <foo key='dum2'/>",
199 "</atlassian-plugin>")
200 .build();
201 }
202
203 private boolean waitForDynamicModuleEnabled()
204 {
205 return WaitUntil.invoke(new BasicWaitCondition()
206 {
207 public boolean isFinished()
208 {
209 return pluginManager.getPlugin("test.plugin").getModuleDescriptors().iterator().next().getClass().getSimpleName().equals("MyModuleDescriptor");
210 }
211 });
212 }
213
214 public void testUpgradeOfBundledPluginWithDynamicModule() throws Exception
215 {
216 final File pluginJar = new PluginJarBuilder("pluginType")
217 .addFormattedResource("atlassian-plugin.xml",
218 "<atlassian-plugin name='Test' key='test.plugin.module' pluginsVersion='2'>",
219 " <plugin-info>",
220 " <version>1.0</version>",
221 " </plugin-info>",
222 " <module-type key='foo' class='foo.MyModuleDescriptor' />",
223 "</atlassian-plugin>")
224 .addFormattedJava(getMyModuleDescriptorClass().left(), getMyModuleDescriptorClass().right())
225 .build();
226
227 final DefaultModuleDescriptorFactory factory = new DefaultModuleDescriptorFactory(hostContainer);
228 initBundlingPluginManager(factory, pluginJar);
229 assertEquals(1, pluginManager.getEnabledPlugins().size());
230
231 final File pluginClientOld = buildDynamicModuleClientJar();
232 final File pluginClientNew = new PluginJarBuilder("fooUser")
233 .addFormattedResource("atlassian-plugin.xml",
234 "<atlassian-plugin name='Test 2' key='test.plugin' pluginsVersion='2'>",
235 " <plugin-info>",
236 " <version>2.0</version>",
237 " </plugin-info>",
238 " <foo key='dum2'/>",
239 "</atlassian-plugin>")
240 .build();
241 pluginManager.installPlugins(new JarPluginArtifact(pluginClientOld), new JarPluginArtifact(pluginClientNew));
242
243 assertTrue(waitForDynamicModuleEnabled());
244
245 assertEquals(2, pluginManager.getEnabledPlugins().size());
246 assertEquals("2.0", pluginManager.getPlugin("test.plugin").getPluginInformation().getVersion());
247 }
248
249 public void testDynamicPluginModuleNotLinkToAllPlugins() throws Exception
250 {
251 new PluginJarBuilder("pluginType")
252 .addFormattedResource("atlassian-plugin.xml",
253 "<atlassian-plugin name='Test' key='test.plugin.module' pluginsVersion='2'>",
254 " <plugin-info>",
255 " <version>1.0</version>",
256 " </plugin-info>",
257 " <module-type key='foo' class='foo.MyModuleDescriptor'/>",
258 "</atlassian-plugin>")
259 .addFormattedJava(getMyModuleDescriptorClass().left(), getMyModuleDescriptorClass().right())
260 .build(pluginsDir);
261 new PluginJarBuilder("fooUser")
262 .addFormattedResource("atlassian-plugin.xml",
263 "<atlassian-plugin name='Test 2' key='test.plugin' pluginsVersion='2'>",
264 " <plugin-info>",
265 " <version>1.0</version>",
266 " </plugin-info>",
267 " <foo key='dum2'/>",
268 "</atlassian-plugin>")
269 .build(pluginsDir);
270 new PluginJarBuilder("foootherUser")
271 .addPluginInformation("unusing.plugin", "Unusing plugin", "1.0")
272 .build(pluginsDir);
273
274 initPluginManager(new HostComponentProvider()
275 {
276 public void provide(final ComponentRegistrar registrar)
277 {
278 }
279 });
280
281 assertEquals("MyModuleDescriptor", pluginManager.getPlugin("test.plugin").getModuleDescriptor("dum2").getClass().getSimpleName());
282 Set<String> deps = findDependentBundles(((OsgiPlugin) pluginManager.getPlugin("test.plugin.module")).getBundle());
283 assertTrue(deps.contains("test.plugin"));
284 assertFalse(deps.contains("unusing.plugin"));
285 }
286
287 private Set<String> findDependentBundles(Bundle bundle)
288 {
289 Set<String> deps = new HashSet<String>();
290 final ServiceReference[] registeredServices = bundle.getRegisteredServices();
291 if (registeredServices == null)
292 {
293 return deps;
294 }
295
296 for (final ServiceReference serviceReference : registeredServices)
297 {
298 final Bundle[] usingBundles = serviceReference.getUsingBundles();
299 if (usingBundles == null)
300 {
301 continue;
302 }
303 for (final Bundle usingBundle : usingBundles)
304 {
305 deps.add(usingBundle.getSymbolicName());
306 }
307 }
308 return deps;
309 }
310
311 public void testDynamicPluginModuleUsingModuleTypeDescriptor() throws Exception
312 {
313 initPluginManager(new HostComponentProvider()
314 {
315 public void provide(final ComponentRegistrar registrar)
316 {
317 }
318 });
319
320 final File pluginJar = new PluginJarBuilder("pluginType")
321 .addFormattedResource("atlassian-plugin.xml",
322 "<atlassian-plugin name='Test' key='test.plugin.module' pluginsVersion='2'>",
323 " <plugin-info>",
324 " <version>1.0</version>",
325 " </plugin-info>",
326 " <module-type key='foo' class='foo.MyModuleDescriptor' />",
327 "</atlassian-plugin>")
328 .addFormattedJava(getMyModuleDescriptorClass().left(), getMyModuleDescriptorClass().right())
329 .build();
330 final File pluginJar2 = buildDynamicModuleClientJar();
331
332 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
333 pluginManager.installPlugin(new JarPluginArtifact(pluginJar2));
334 WaitUntil.invoke(new BasicWaitCondition()
335 {
336 public boolean isFinished()
337 {
338 return pluginManager.getPlugin("test.plugin")
339 .getModuleDescriptor("dum2")
340 .getClass()
341 .getSimpleName()
342 .equals("MyModuleDescriptor");
343 }
344 });
345 final Collection<ModuleDescriptor<?>> descriptors = pluginManager.getPlugin("test.plugin")
346 .getModuleDescriptors();
347 assertEquals(1, descriptors.size());
348 final ModuleDescriptor<?> descriptor = descriptors.iterator()
349 .next();
350 assertEquals("MyModuleDescriptor", descriptor.getClass().getSimpleName());
351 }
352
353 public void testDynamicPluginModuleWithClientAndHostEnabledSimultaneouslyCheckEvents() throws Exception
354 {
355 initPluginManager();
356
357 final File pluginJar = new PluginJarBuilder("pluginType")
358 .addFormattedResource("atlassian-plugin.xml",
359 "<atlassian-plugin name='Test' key='host' pluginsVersion='2'>",
360 " <plugin-info>",
361 " <version>1.0</version>",
362 " </plugin-info>",
363 " <component key='foo' class='foo.MyModuleDescriptorFactory' public='true'>",
364 " <interface>com.atlassian.plugin.osgi.external.ListableModuleDescriptorFactory</interface>",
365 " </component>",
366 "</atlassian-plugin>")
367 .addFormattedJava("foo.MyModuleDescriptorFactory",
368 "package foo;",
369 "public class MyModuleDescriptorFactory extends com.atlassian.plugin.DefaultModuleDescriptorFactory ",
370 " implements com.atlassian.plugin.osgi.external.ListableModuleDescriptorFactory{",
371 " public MyModuleDescriptorFactory() throws Exception{",
372 " super();",
373 " Thread.sleep(500);",
374 " System.out.println('starting descriptor factory');",
375 " addModuleDescriptor('foo', com.atlassian.plugin.osgi.EventTrackingModuleDescriptor.class);",
376 " }",
377 " public Iterable getModuleDescriptorKeys() {",
378 " return java.util.Collections.singleton('foo');",
379 " }",
380 " public java.util.Set getModuleDescriptorClasses() {",
381 " return java.util.Collections.singleton(com.atlassian.plugin.osgi.EventTrackingModuleDescriptor.class);",
382 " }",
383 "}")
384 .build();
385 final File pluginJar2 = new PluginJarBuilder("fooUser")
386 .addFormattedResource("atlassian-plugin.xml",
387 "<atlassian-plugin name='Test 2' key='client' pluginsVersion='2'>",
388 " <plugin-info>",
389 " <version>1.0</version>",
390 " </plugin-info>",
391 " <foo key='dum2'/>",
392 "</atlassian-plugin>")
393 .build();
394
395 pluginManager.installPlugins(new JarPluginArtifact(pluginJar), new JarPluginArtifact(pluginJar2));
396
397 WaitUntil.invoke(new BasicWaitCondition()
398 {
399 public boolean isFinished()
400 {
401 return pluginManager.getPlugin("client").getModuleDescriptor("dum2").getClass().getSimpleName().equals("EventTrackingModuleDescriptor");
402 }
403 });
404 EventTrackingModuleDescriptor desc = (EventTrackingModuleDescriptor) pluginManager.getPlugin("client").getModuleDescriptor("dum2");
405 assertEquals(1, desc.getEnabledCount());
406 }
407
408
409 public void testDynamicPluginModuleUsingModuleTypeDescriptorAndComponentInjection() throws Exception
410 {
411 initPluginManager(new HostComponentProvider()
412 {
413 public void provide(final ComponentRegistrar registrar)
414 {
415 }
416 });
417
418 final File pluginJar = new PluginJarBuilder("pluginType")
419 .addFormattedResource("atlassian-plugin.xml",
420 "<atlassian-plugin name='Test' key='test.plugin.module' pluginsVersion='2'>",
421 " <plugin-info>",
422 " <version>1.0</version>",
423 " </plugin-info>",
424 " <component key='comp' class='foo.MyComponent' />",
425 " <module-type key='foo' class='foo.MyModuleDescriptor' />",
426 "</atlassian-plugin>")
427 .addFormattedJava("foo.MyComponent", "package foo;", "public class MyComponent {", "}")
428 .addFormattedJava(getMyModuleDescriptorClass().left(), getMyModuleDescriptorClass().right())
429 .build();
430 final File pluginJar2 = buildDynamicModuleClientJar();
431
432 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
433 pluginManager.installPlugin(new JarPluginArtifact(pluginJar2));
434 assertTrue(waitForDynamicModuleEnabled());
435 final Collection<ModuleDescriptor<?>> descriptors = pluginManager.getPlugin("test.plugin")
436 .getModuleDescriptors();
437 assertEquals(1, descriptors.size());
438 final ModuleDescriptor<?> descriptor = descriptors.iterator()
439 .next();
440 assertEquals("MyModuleDescriptor", descriptor.getClass().getSimpleName());
441 }
442
443 public void testDynamicPluginModuleUsingModuleTypeDescriptorAfterTheFact() throws Exception
444 {
445 initPluginManager(new HostComponentProvider()
446 {
447 public void provide(final ComponentRegistrar registrar)
448 {
449 }
450 });
451
452 final File pluginJar = new PluginJarBuilder("pluginType")
453 .addFormattedResource("atlassian-plugin.xml",
454 "<atlassian-plugin name='Test' key='test.plugin.module' pluginsVersion='2'>",
455 " <plugin-info>",
456 " <version>1.0</version>",
457 " </plugin-info>",
458 " <module-type key='foo' class='foo.MyModuleDescriptor' />",
459 "</atlassian-plugin>")
460 .addFormattedJava(getMyModuleDescriptorClass().left(), getMyModuleDescriptorClass().right())
461 .build();
462 final File pluginJar2 = buildDynamicModuleClientJar();
463
464 pluginManager.installPlugin(new JarPluginArtifact(pluginJar2));
465 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
466 waitForDynamicModuleEnabled();
467
468 Collection<ModuleDescriptor<?>> descriptors = pluginManager.getPlugin("test.plugin")
469 .getModuleDescriptors();
470 assertEquals(1, descriptors.size());
471 ModuleDescriptor<?> descriptor = descriptors.iterator()
472 .next();
473 assertEquals("MyModuleDescriptor", descriptor.getClass().getSimpleName());
474
475 pluginManager.uninstall(pluginManager.getPlugin("test.plugin.module"));
476 WaitUntil.invoke(new BasicWaitCondition()
477 {
478 public boolean isFinished()
479 {
480 return pluginManager.getPlugin("test.plugin")
481 .getModuleDescriptors()
482 .iterator()
483 .next()
484 .getClass()
485 .getSimpleName()
486 .equals("UnrecognisedModuleDescriptor");
487 }
488 });
489 descriptors = pluginManager.getPlugin("test.plugin")
490 .getModuleDescriptors();
491 assertEquals(1, descriptors.size());
492 descriptor = descriptors.iterator()
493 .next();
494 assertEquals("UnrecognisedModuleDescriptor", descriptor.getClass().getSimpleName());
495
496 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
497 descriptors = pluginManager.getPlugin("test.plugin")
498 .getModuleDescriptors();
499 assertEquals(1, descriptors.size());
500 descriptor = descriptors.iterator()
501 .next();
502 assertEquals("MyModuleDescriptor", descriptor.getClass().getSimpleName());
503 }
504
505 public void testDynamicPluginModuleUsingModuleTypeDescriptorAfterTheFactWithException() throws Exception
506 {
507 initPluginManager(new HostComponentProvider()
508 {
509 public void provide(final ComponentRegistrar registrar)
510 {
511 }
512 });
513
514 final File pluginJar = new PluginJarBuilder("pluginType")
515 .addFormattedResource("atlassian-plugin.xml",
516 "<atlassian-plugin name='Test' key='test.plugin.module' pluginsVersion='2'>",
517 " <plugin-info>",
518 " <version>1.0</version>",
519 " </plugin-info>",
520 " <module-type key='foo' class='foo.MyModuleDescriptor' />",
521 "</atlassian-plugin>")
522 .addFormattedJava("foo.MyModuleDescriptor",
523 "package foo;",
524 "import com.atlassian.plugin.module.ModuleFactory;",
525 "public class MyModuleDescriptor extends com.atlassian.plugin.descriptors.AbstractModuleDescriptor {",
526 " public MyModuleDescriptor() {",
527 " super(ModuleFactory.LEGACY_MODULE_FACTORY);",
528 " throw new RuntimeException('error loading module');",
529 " }",
530 " public Object getModule(){return null;}",
531 "}")
532 .build();
533 final File pluginJar2 = buildDynamicModuleClientJar();
534
535 pluginManager.installPlugin(new JarPluginArtifact(pluginJar2));
536 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
537 assertTrue(WaitUntil.invoke(new BasicWaitCondition()
538 {
539 public boolean isFinished()
540 {
541 UnrecognisedModuleDescriptor des = (UnrecognisedModuleDescriptor) pluginManager.getPlugin("test.plugin").getModuleDescriptor("dum2");
542 return des.getErrorText().contains("error loading module");
543 }
544 }));
545 }
546
547 public void testDynamicPluginModuleUsingModuleTypeDescriptorInSamePlugin() throws Exception
548 {
549 initPluginManager(new HostComponentProvider()
550 {
551 public void provide(final ComponentRegistrar registrar)
552 {
553 }
554 });
555
556 final File pluginJar = new PluginJarBuilder("pluginType")
557 .addFormattedResource("atlassian-plugin.xml",
558 "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
559 " <plugin-info>",
560 " <version>1.0</version>",
561 " </plugin-info>",
562 " <module-type key='foo' class='foo.MyModuleDescriptor' />",
563 " <foo key='dum2' />",
564 "</atlassian-plugin>")
565 .addFormattedJava(getMyModuleDescriptorClass().left(), getMyModuleDescriptorClass().right())
566 .build();
567
568 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
569 WaitUntil.invoke(new BasicWaitCondition()
570 {
571 public boolean isFinished()
572 {
573 return pluginManager.getPlugin("test.plugin")
574 .getModuleDescriptor("dum2")
575 .getClass()
576 .getSimpleName()
577 .equals("MyModuleDescriptor");
578 }
579 });
580 final Collection<ModuleDescriptor<?>> descriptors = pluginManager.getPlugin("test.plugin")
581 .getModuleDescriptors();
582 assertEquals(2, descriptors.size());
583 final ModuleDescriptor<?> descriptor = pluginManager.getPlugin("test.plugin")
584 .getModuleDescriptor("dum2");
585 assertEquals("MyModuleDescriptor", descriptor.getClass().getSimpleName());
586 }
587
588 public void testDynamicPluginModuleUsingModuleTypeDescriptorInSamePluginWithRestart() throws Exception
589 {
590 initPluginManager();
591
592 final File pluginJar = new PluginJarBuilder("pluginType")
593 .addFormattedResource("atlassian-plugin.xml",
594 "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
595 " <plugin-info>",
596 " <version>1.0</version>",
597 " </plugin-info>",
598 " <module-type key='foo' class='foo.MyModuleDescriptor' />",
599 " <foo key='dum2' />",
600 "</atlassian-plugin>")
601 .addFormattedJava(getMyModuleDescriptorClass().left(), getMyModuleDescriptorClass().right())
602 .build();
603
604 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
605 WaitUntil.invoke(new BasicWaitCondition()
606 {
607 public boolean isFinished()
608 {
609 return pluginManager.getPlugin("test.plugin")
610 .getModuleDescriptor("dum2")
611 .getClass()
612 .getSimpleName()
613 .equals("MyModuleDescriptor");
614 }
615 });
616 Collection<ModuleDescriptor<?>> descriptors = pluginManager.getPlugin("test.plugin")
617 .getModuleDescriptors();
618 assertEquals(2, descriptors.size());
619 ModuleDescriptor<?> descriptor = pluginManager.getPlugin("test.plugin")
620 .getModuleDescriptor("dum2");
621 assertEquals("MyModuleDescriptor", descriptor.getClass().getSimpleName());
622
623 PluginModuleDisabledListener disabledListener = new PluginModuleDisabledListener("dum2");
624 PluginModuleEnabledListener enabledListener = new PluginModuleEnabledListener("dum2");
625 pluginEventManager.register(disabledListener);
626 pluginEventManager.register(enabledListener);
627
628 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
629 WaitUntil.invoke(new BasicWaitCondition()
630 {
631 public boolean isFinished()
632 {
633 return pluginManager.getPlugin("test.plugin")
634 .getModuleDescriptor("dum2")
635 .getClass()
636 .getSimpleName()
637 .equals("MyModuleDescriptor");
638 }
639 });
640 descriptors = pluginManager.getPlugin("test.plugin")
641 .getModuleDescriptors();
642 assertEquals(2, descriptors.size());
643 ModuleDescriptor<?> newdescriptor = pluginManager.getPlugin("test.plugin")
644 .getModuleDescriptor("dum2");
645 assertEquals("MyModuleDescriptor", newdescriptor.getClass().getSimpleName());
646 assertTrue(descriptor.getClass() != newdescriptor.getClass());
647 assertEquals(1, disabledListener.called);
648 assertEquals(1, enabledListener.called);
649 }
650
651 public void testDynamicModuleDescriptor() throws Exception
652 {
653 initPluginManager(null);
654
655 final File pluginJar = new PluginJarBuilder("pluginType").addPluginInformation("test.plugin", "foo", "1.0")
656 .build();
657
658 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
659 final BundleContext ctx = ((OsgiPlugin) pluginManager.getPlugin("test.plugin")).getBundle()
660 .getBundleContext();
661 final ServiceRegistration reg = ctx.registerService(ModuleDescriptor.class.getName(), new DummyModuleDescriptorWithKey(), null);
662
663 final Collection<ModuleDescriptor<?>> descriptors = pluginManager.getPlugin("test.plugin")
664 .getModuleDescriptors();
665 assertEquals(1, descriptors.size());
666 final ModuleDescriptor<?> descriptor = descriptors.iterator()
667 .next();
668 assertEquals("DummyModuleDescriptorWithKey", descriptor.getClass().getSimpleName());
669 List<DummyModuleDescriptorWithKey> list = pluginManager.getEnabledModuleDescriptorsByClass(DummyModuleDescriptorWithKey.class);
670 assertEquals(1, list.size());
671 reg.unregister();
672 list = pluginManager.getEnabledModuleDescriptorsByClass(DummyModuleDescriptorWithKey.class);
673 assertEquals(0, list.size());
674 }
675
676 public void testDynamicModuleDescriptorIsolatedToPlugin() throws Exception
677 {
678 initPluginManager(null);
679
680 final File pluginJar = new PluginJarBuilder("pluginType").addPluginInformation("test.plugin", "foo", "1.0")
681 .build();
682
683 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
684 final BundleContext ctx = ((OsgiPlugin) pluginManager.getPlugin("test.plugin")).getBundle()
685 .getBundleContext();
686 ctx.registerService(ModuleDescriptor.class.getName(), new DummyModuleDescriptorWithKey(), null);
687
688 final File pluginJar2 = new PluginJarBuilder("pluginType").addPluginInformation("test.plugin2", "foo", "1.0")
689 .build();
690 pluginManager.installPlugin(new JarPluginArtifact(pluginJar2));
691 final BundleContext ctx2 = ((OsgiPlugin) pluginManager.getPlugin("test.plugin2")).getBundle()
692 .getBundleContext();
693 final ServiceRegistration reg2 = ctx2.registerService(ModuleDescriptor.class.getName(), new DummyModuleDescriptorWithKey(), null);
694
695 Collection<ModuleDescriptor<?>> descriptors = pluginManager.getPlugin("test.plugin")
696 .getModuleDescriptors();
697 assertEquals(1, descriptors.size());
698 final ModuleDescriptor<?> descriptor = descriptors.iterator()
699 .next();
700 assertEquals("DummyModuleDescriptorWithKey", descriptor.getClass().getSimpleName());
701 List<DummyModuleDescriptorWithKey> list = pluginManager.getEnabledModuleDescriptorsByClass(DummyModuleDescriptorWithKey.class);
702 assertEquals(2, list.size());
703 reg2.unregister();
704 list = pluginManager.getEnabledModuleDescriptorsByClass(DummyModuleDescriptorWithKey.class);
705 assertEquals(1, list.size());
706 descriptors = pluginManager.getPlugin("test.plugin")
707 .getModuleDescriptors();
708 assertEquals(1, descriptors.size());
709 }
710
711 public void testInstallUninstallInstallWithModuleTypePlugin() throws Exception
712 {
713 final PluginArtifact moduleTypeProviderArtifact = new JarPluginArtifact(new PluginJarBuilder()
714 .addFormattedResource(
715 "atlassian-plugin.xml",
716 "<atlassian-plugin name='Foo Module Type Provider' key='test.fooModuleTypeProvider' pluginsVersion='2'>",
717 " <plugin-info>",
718 " <version>1.0</version>",
719 " <bundle-instructions>",
720 " <Export-Package>my</Export-Package>",
721 " </bundle-instructions>",
722 " </plugin-info>",
723 " <module-type key='foo-module' class='my.FooModuleDescriptor'/>",
724 "</atlassian-plugin>")
725 .addClass(FooModule.class)
726 .addClass(FooModuleDescriptor.class)
727 .build());
728 final PluginArtifact moduleTypeImplementerArtifact = new JarPluginArtifact(new PluginJarBuilder().addFormattedResource("atlassian-plugin.xml",
729 "<atlassian-plugin name='Foo Module Type Implementer' key='test.fooModuleTypeImplementer' pluginsVersion='2'>",
730 " <plugin-info>",
731 " <version>1.0</version>",
732 " <bundle-instructions>",
733 " <Import-Package>my</Import-Package>",
734 " </bundle-instructions>",
735 " </plugin-info>",
736 " <foo-module key='myFooModule' class='my.impl.FooModuleImpl'/>",
737 "</atlassian-plugin>")
738 .addFormattedJava(
739 "my.impl.FooModuleImpl",
740 "package my.impl;",
741 "",
742 "import my.FooModule;",
743 "",
744 "public class FooModuleImpl implements FooModule {",
745 "}")
746 .build());
747
748 initPluginManager();
749 pluginManager.installPlugin(moduleTypeProviderArtifact);
750 pluginManager.installPlugin(moduleTypeImplementerArtifact);
751
752 final long foo1InitialisationTime = assertFooImplEnabledAndGetInitialisationTime();
753
754 pluginManager.installPlugin(moduleTypeProviderArtifact);
755
756 final long foo2InitialisationTime = assertFooImplEnabledAndGetInitialisationTime();
757
758 assertTrue("FooModuleImpl implements old version of FooModule", foo2InitialisationTime > foo1InitialisationTime);
759 }
760
761 private long assertFooImplEnabledAndGetInitialisationTime() throws IllegalAccessException, NoSuchFieldException
762 {
763 assertTrue(pluginManager.isPluginModuleEnabled("test.fooModuleTypeProvider:foo-module"));
764 assertTrue(pluginManager.isPluginModuleEnabled("test.fooModuleTypeImplementer:myFooModule"));
765 final ModuleDescriptor<?> fooDescriptor = pluginManager.getEnabledPluginModule("test.fooModuleTypeImplementer:myFooModule");
766 assertNotNull(fooDescriptor);
767 final Object foo = fooDescriptor.getModule();
768 assertNotNull(foo);
769 final Class<? extends Object> fooClass = foo.getClass();
770 assertTrue(fooClass.getName().equals("my.impl.FooModuleImpl"));
771 return fooClass.getField("INITIALISATION_TIME").getLong(foo);
772 }
773
774 private static Pair<String, String[]> getMyModuleDescriptorClass()
775 {
776 return Pair.pair(
777 "foo.MyModuleDescriptor",
778 new String[]{
779 "package foo;",
780 "import com.atlassian.plugin.module.ModuleFactory;",
781 "public class MyModuleDescriptor extends com.atlassian.plugin.descriptors.AbstractModuleDescriptor {",
782 " public MyModuleDescriptor(){ super(ModuleFactory.LEGACY_MODULE_FACTORY); }",
783 " public Object getModule(){return null;}",
784 "}"
785 });
786 }
787
788 public static class PluginModuleEnabledListener
789 {
790 public volatile int called;
791 private final String key;
792
793 public PluginModuleEnabledListener(String key)
794 {
795 this.key = key;
796 }
797
798 @PluginEventListener
799 public void onEnable(PluginModuleEnabledEvent event)
800 {
801 if (event.getModule().getKey().equals(key))
802 {
803 called++;
804 }
805 }
806 }
807
808 public static class PluginModuleDisabledListener
809 {
810 public volatile int called;
811 private final String key;
812
813 public PluginModuleDisabledListener(String key)
814 {
815 this.key = key;
816 }
817
818 @PluginEventListener
819 public void onDisable(PluginModuleDisabledEvent event)
820 {
821 if (event.getModule().getKey().equals(key))
822 {
823 called++;
824 }
825 }
826 }
827 }