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