1 package it.com.atlassian.plugin.osgi;
2
3 import com.atlassian.plugin.DefaultModuleDescriptorFactory;
4 import com.atlassian.plugin.JarPluginArtifact;
5 import com.atlassian.plugin.Plugin;
6 import com.atlassian.plugin.hostcontainer.DefaultHostContainer;
7 import com.atlassian.plugin.osgi.AbstractWaitCondition;
8 import com.atlassian.plugin.osgi.AnotherInterface;
9 import com.atlassian.plugin.osgi.Callable2;
10 import com.atlassian.plugin.osgi.DummyModuleDescriptor;
11 import com.atlassian.plugin.osgi.EventTrackingModuleDescriptor;
12 import com.atlassian.plugin.osgi.PluginInContainerTestBase;
13 import com.atlassian.plugin.osgi.SomeInterface;
14 import com.atlassian.plugin.osgi.container.felix.FelixOsgiContainerManager;
15 import com.atlassian.plugin.osgi.factory.OsgiPlugin;
16 import com.atlassian.plugin.osgi.hostcomponents.ComponentRegistrar;
17 import com.atlassian.plugin.osgi.hostcomponents.HostComponentProvider;
18 import com.atlassian.plugin.test.PluginJarBuilder;
19 import com.atlassian.plugin.util.WaitUntil;
20 import org.osgi.util.tracker.ServiceTracker;
21
22 import java.io.File;
23 import java.util.Collections;
24 import java.util.concurrent.Callable;
25
26 public class TestPluginDependencies extends PluginInContainerTestBase
27 {
28 public void testPluginDependentOnPackageImport() throws Exception
29 {
30 PluginJarBuilder parentBuilder = new PluginJarBuilder("parent")
31 .addFormattedResource("atlassian-plugin.xml",
32 "<atlassian-plugin name='Test' key='parent' pluginsVersion='2'>",
33 " <plugin-info>",
34 " <version>1.0</version>",
35 " <bundle-instructions>",
36 " <Import-Package>foo</Import-Package>",
37 " <Export-Package>foo</Export-Package>",
38 " </bundle-instructions>",
39 " </plugin-info>",
40 "</atlassian-plugin>")
41 .addFormattedJava("foo.Bar",
42 "package foo;",
43 "public interface Bar {}");
44
45 new PluginJarBuilder("child", parentBuilder.getClassLoader())
46 .addFormattedResource("atlassian-plugin.xml",
47 "<atlassian-plugin name='Test' key='child' pluginsVersion='2'>",
48 " <plugin-info>",
49 " <version>1.0</version>",
50 " </plugin-info>",
51 "</atlassian-plugin>")
52 .addFormattedJava("second.MyImpl",
53 "package second;",
54 "public class MyImpl {",
55 " public MyImpl(foo.Bar config) {",
56 " }",
57 "}")
58 .build(pluginsDir);
59
60 parentBuilder.build(pluginsDir);
61 initPluginManager();
62 assertEquals(2, pluginManager.getEnabledPlugins().size());
63 assertEquals(Collections.singleton("parent"), pluginManager.getPlugin("child").getRequiredPlugins());
64 }
65
66 public void testPluginDependentOnDynamicPackageImport() throws Exception
67 {
68 PluginJarBuilder parentBuilder = new PluginJarBuilder("parent")
69 .addFormattedResource("atlassian-plugin.xml",
70 "<atlassian-plugin name='Test' key='parent' pluginsVersion='2'>",
71 " <plugin-info>",
72 " <version>1.0</version>",
73 " <bundle-instructions>",
74 " <Import-Package>foo</Import-Package>",
75 " <Export-Package>foo</Export-Package>",
76 " </bundle-instructions>",
77 " </plugin-info>",
78 "</atlassian-plugin>")
79 .addFormattedJava("foo.Bar",
80 "package foo;",
81 "public interface Bar {}");
82
83 new PluginJarBuilder("child", parentBuilder.getClassLoader())
84 .addFormattedResource("atlassian-plugin.xml",
85 "<atlassian-plugin name='Test' key='child' pluginsVersion='2'>",
86 " <plugin-info>",
87 " <version>1.0</version>",
88 " <bundle-instructions>",
89 " <Import-Package />",
90 " <DynamicImport-Package>foo</DynamicImport-Package>",
91 " </bundle-instructions>",
92 " </plugin-info>",
93 "</atlassian-plugin>")
94 .addFormattedJava("second.MyImpl",
95 "package second;",
96 "public class MyImpl {",
97 " public MyImpl(foo.Bar config) {",
98 " }",
99 "}")
100 .build(pluginsDir);
101
102 parentBuilder.build(pluginsDir);
103 initPluginManager();
104 assertEquals(2, pluginManager.getEnabledPlugins().size());
105 Plugin childPlugin = pluginManager.getPlugin("child");
106 childPlugin.loadClass("foo.Bar", null);
107 assertEquals(Collections.singleton("parent"), childPlugin.getRequiredPlugins());
108 }
109
110 public void testUninstallingPluginDependentOnPackageImport() throws Exception
111 {
112 PluginJarBuilder parentBuilder = new PluginJarBuilder("parent")
113 .addFormattedResource("atlassian-plugin.xml",
114 "<atlassian-plugin name='Test' key='parent' pluginsVersion='2'>",
115 " <plugin-info>",
116 " <version>1.0</version>",
117 " <bundle-instructions>",
118 " <Import-Package>foo</Import-Package>",
119 " <Export-Package>foo</Export-Package>",
120 " </bundle-instructions>",
121 " </plugin-info>",
122 "</atlassian-plugin>")
123 .addFormattedJava("foo.Bar",
124 "package foo;",
125 "public interface Bar {}");
126
127 new PluginJarBuilder("child", parentBuilder.getClassLoader())
128 .addFormattedResource("atlassian-plugin.xml",
129 "<atlassian-plugin name='Test' key='child' pluginsVersion='2'>",
130 " <plugin-info>",
131 " <version>1.0</version>",
132 " </plugin-info>",
133 "</atlassian-plugin>")
134 .addFormattedJava("second.MyImpl",
135 "package second;",
136 "public class MyImpl {",
137 " public MyImpl(foo.Bar config) {",
138 " }",
139 "}")
140 .build(pluginsDir);
141
142 parentBuilder.build(pluginsDir);
143 initPluginManager();
144 assertEquals(2, pluginManager.getEnabledPlugins().size());
145 pluginManager.uninstall(pluginManager.getPlugin("parent"));
146 assertEquals(0, pluginManager.getEnabledPlugins().size());
147 }
148
149 public void testUpgradeWithNewComponentImplementation() throws Exception
150 {
151 final DefaultModuleDescriptorFactory factory = new DefaultModuleDescriptorFactory(new DefaultHostContainer());
152 factory.addModuleDescriptor("dummy", DummyModuleDescriptor.class);
153 initPluginManager(new HostComponentProvider()
154 {
155 public void provide(final ComponentRegistrar registrar)
156 {
157 registrar.register(SomeInterface.class).forInstance(new SomeInterface()
158 {});
159 registrar.register(AnotherInterface.class).forInstance(new AnotherInterface()
160 {});
161 }
162 }, factory);
163
164 final File pluginJar = new PluginJarBuilder("first")
165 .addFormattedResource("atlassian-plugin.xml",
166 "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
167 " <plugin-info>",
168 " <version>1.0</version>",
169 " </plugin-info>",
170 " <component key='svc' class='my.ServiceImpl' public='true'>",
171 " <interface>java.util.concurrent.Callable</interface>",
172 " </component>",
173 "</atlassian-plugin>")
174 .addFormattedJava("my.ServiceImpl",
175 "package my;",
176 "import java.util.concurrent.Callable;",
177 "public class ServiceImpl implements Callable {",
178 " public Object call() throws Exception { return 'hi';}",
179 "}")
180 .build();
181 final File pluginJar2 = new PluginJarBuilder("second")
182 .addFormattedResource("atlassian-plugin.xml",
183 "<atlassian-plugin name='Test 2' key='test2.plugin' pluginsVersion='2'>",
184 " <plugin-info>",
185 " <version>1.0</version>",
186 " </plugin-info>",
187 " <component-import key='svc' interface='java.util.concurrent.Callable' />",
188 " <component key='del' class='my2.ServiceDelegate' public='true'>",
189 " <interface>com.atlassian.plugin.osgi.Callable2</interface>",
190 " </component>",
191 "</atlassian-plugin>")
192 .addFormattedJava("my2.ServiceDelegate",
193 "package my2;",
194 "import com.atlassian.plugin.osgi.Callable2;",
195 "import java.util.concurrent.Callable;",
196 "public class ServiceDelegate implements Callable2 {",
197 " private final Callable delegate;",
198 " public ServiceDelegate(Callable foo) { this.delegate = foo;}",
199 " public String call() throws Exception { return (String)delegate.call();}",
200 "}")
201 .build();
202
203 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
204 assertEquals(1, pluginManager.getEnabledPlugins().size());
205
206 pluginManager.installPlugin(new JarPluginArtifact(pluginJar2));
207 final ServiceTracker tracker = osgiContainerManager.getServiceTracker("com.atlassian.plugin.osgi.Callable2");
208
209 for (final Object svc : tracker.getServices())
210 {
211 final Callable2 callable = (Callable2) svc;
212 assertEquals("hi", callable.call());
213 }
214 assertEquals(2, pluginManager.getEnabledPlugins().size());
215
216 final File updatedJar = new PluginJarBuilder("first")
217 .addFormattedResource("atlassian-plugin.xml",
218 "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
219 " <plugin-info>",
220 " <version>1.0</version>",
221 " </plugin-info>",
222 " <component key='svc' class='my.ServiceImpl' public='true'>",
223 " <interface>java.util.concurrent.Callable</interface>",
224 " </component>",
225 "</atlassian-plugin>")
226 .addFormattedJava("my.ServiceImpl",
227 "package my;",
228 "import java.util.concurrent.Callable;",
229 "public class ServiceImpl implements Callable {",
230 " public Object call() throws Exception { return 'bob';}",
231 "}")
232 .build();
233
234 pluginManager.installPlugin(new JarPluginArtifact(updatedJar));
235 WaitUntil.invoke(new AbstractWaitCondition()
236 {
237 public boolean isFinished()
238 {
239 return pluginManager.getEnabledPlugins().size() == 2;
240 }
241 });
242 assertEquals(2, pluginManager.getEnabledPlugins().size());
243 for (final Object svc : tracker.getServices())
244 {
245 final Callable2 callable = (Callable2) svc;
246 assertEquals("bob", callable.call());
247 }
248 }
249
250 public void testUpgradeWithNewComponentImplementationWithInterfaceInPlugin() throws Exception
251 {
252 final DefaultModuleDescriptorFactory factory = new DefaultModuleDescriptorFactory(new DefaultHostContainer());
253 factory.addModuleDescriptor("dummy", DummyModuleDescriptor.class);
254 initPluginManager(new HostComponentProvider()
255 {
256 public void provide(final ComponentRegistrar registrar)
257 {
258 registrar.register(SomeInterface.class).forInstance(new SomeInterface()
259 {});
260 registrar.register(AnotherInterface.class).forInstance(new AnotherInterface()
261 {});
262 }
263 }, factory);
264
265 final PluginJarBuilder builder1 = new PluginJarBuilder("first")
266 .addFormattedResource("atlassian-plugin.xml",
267 "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
268 " <plugin-info>",
269 " <version>1.0</version>",
270 " </plugin-info>",
271 " <component key='svc' class='my.ServiceImpl' public='true'>",
272 " <interface>my.Service</interface>",
273 " </component>",
274 "</atlassian-plugin>")
275 .addFormattedJava("my.Service",
276 "package my;",
277 "public interface Service {",
278 " public Object call() throws Exception;",
279 "}")
280 .addFormattedJava("my.ServiceImpl",
281 "package my;",
282 "public class ServiceImpl implements Service {",
283 " public Object call() throws Exception { return 'hi';}",
284 "}");
285 final File pluginJar = builder1.build();
286 final File pluginJar2 = new PluginJarBuilder("second", builder1.getClassLoader())
287 .addFormattedResource("atlassian-plugin.xml",
288 "<atlassian-plugin name='Test 2' key='test2.plugin' pluginsVersion='2'>",
289 " <plugin-info>",
290 " <version>1.0</version>",
291 " </plugin-info>",
292 " <component-import key='svc' interface='my.Service' />",
293 " <component key='del' class='my2.ServiceDelegate' public='true'>",
294 " <interface>java.util.concurrent.Callable</interface>",
295 " </component>",
296 "</atlassian-plugin>")
297 .addFormattedJava("my2.ServiceDelegate",
298 "package my2;",
299 "import my.Service;",
300 "import java.util.concurrent.Callable;",
301 "public class ServiceDelegate implements Callable {",
302 " private final Service delegate;",
303 " public ServiceDelegate(Service foo) { this.delegate = foo;}",
304 " public Object call() throws Exception { return delegate.call();}",
305 "}")
306 .build();
307
308 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
309 assertEquals(1, pluginManager.getEnabledPlugins().size());
310 final ServiceTracker tracker = osgiContainerManager.getServiceTracker(Callable.class.getName());
311 final ServiceTracker svcTracker = osgiContainerManager.getServiceTracker("my.Service");
312
313 pluginManager.installPlugin(new JarPluginArtifact(pluginJar2));
314 assertEquals("hi", svcTracker.getService().getClass().getMethod("call").invoke(svcTracker.getService()));
315 assertEquals("hi", ((Callable) tracker.getService()).call());
316
317 assertEquals(2, pluginManager.getEnabledPlugins().size());
318
319 final File updatedJar = new PluginJarBuilder("first")
320 .addFormattedResource("atlassian-plugin.xml",
321 "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
322 " <plugin-info>",
323 " <version>1.0</version>",
324 " </plugin-info>",
325 " <component key='svc' class='my.Service2Impl' public='true'>",
326 " <interface>my.Service</interface>",
327 " </component>",
328 "</atlassian-plugin>")
329 .addFormattedJava("my.Service",
330 "package my;",
331 "public interface Service {",
332 " public Object call() throws Exception;",
333 "}")
334 .addFormattedJava("my.Service2Impl",
335 "package my;",
336 "public class Service2Impl implements Service {",
337 " public Object call() throws Exception {return 'bob';}",
338 "}")
339 .build();
340
341 pluginManager.installPlugin(new JarPluginArtifact(updatedJar));
342 assertEquals("bob", svcTracker.getService().getClass().getMethod("call").invoke(svcTracker.getService()));
343 tracker.waitForService(5000);
344 assertEquals("bob", ((Callable) tracker.getService()).call());
345 }
346
347 public void testUpgradeWithRefreshingAffectingOtherPlugins() throws Exception
348 {
349 final DefaultModuleDescriptorFactory factory = new DefaultModuleDescriptorFactory(new DefaultHostContainer());
350 initPluginManager(new HostComponentProvider()
351 {
352 public void provide(final ComponentRegistrar registrar)
353 {
354 }
355 }, factory);
356
357 PluginJarBuilder pluginBuilder = new PluginJarBuilder("first")
358 .addFormattedResource("atlassian-plugin.xml",
359 "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
360 " <plugin-info>",
361 " <version>1.0</version>",
362 " <bundle-instructions><Export-Package>my</Export-Package></bundle-instructions>",
363 " </plugin-info>",
364 " <component key='svc' class='my.ServiceImpl' public='true'>",
365 " <interface>java.util.concurrent.Callable</interface>",
366 " </component>",
367 "</atlassian-plugin>")
368 .addFormattedJava("my.ServiceImpl",
369 "package my;",
370 "import java.util.concurrent.Callable;",
371 "public class ServiceImpl implements Callable {",
372 " public Object call() throws Exception { return 'hi';}",
373 "}");
374 final File pluginJar = pluginBuilder.build();
375
376 final File pluginJar2 = new PluginJarBuilder("second", pluginBuilder.getClassLoader())
377 .addFormattedResource("atlassian-plugin.xml",
378 "<atlassian-plugin name='Test 2' key='test2.plugin' pluginsVersion='2'>",
379 " <plugin-info>",
380 " <version>1.0</version>",
381 " <bundle-instructions><Import-Package>my,*</Import-Package></bundle-instructions>",
382 " </plugin-info>",
383 " <component-import key='svc' interface='java.util.concurrent.Callable' />",
384 " <component-import key='othersvc' interface='com.atlassian.plugin.osgi.Callable3' />",
385 " <component key='del' class='my2.ServiceDelegate' public='true'>",
386 " <interface>com.atlassian.plugin.osgi.Callable2</interface>",
387 " </component>",
388 "</atlassian-plugin>")
389 .addFormattedJava("my2.ServiceDelegate",
390 "package my2;",
391 "import com.atlassian.plugin.osgi.Callable2;",
392 "import com.atlassian.plugin.osgi.Callable3;",
393 "import java.util.concurrent.Callable;",
394 "public class ServiceDelegate implements Callable2 {",
395 " private final Callable delegate;",
396 " private final Callable3 othersvc;",
397 " public ServiceDelegate(Callable foo,Callable3 othersvc) {",
398 " this.delegate = foo;",
399 " this.othersvc = othersvc;",
400 " }",
401 " public String call() throws Exception { return othersvc.call() + (String)delegate.call();}",
402 "}")
403 .build();
404 final File otherSvcJar = new PluginJarBuilder("otherSvc")
405 .addFormattedResource("atlassian-plugin.xml",
406 "<atlassian-plugin name='Test' key='test.othersvc.plugin' pluginsVersion='2'>",
407 " <plugin-info>",
408 " <version>1.0</version>",
409 " </plugin-info>",
410 " <component key='othersvc' class='othersvc.ServiceImpl' public='true'>",
411 " <interface>com.atlassian.plugin.osgi.Callable3</interface>",
412 " </component>",
413 "</atlassian-plugin>")
414 .addFormattedJava("othersvc.ServiceImpl",
415 "package othersvc;",
416 "import com.atlassian.plugin.osgi.Callable3;",
417 "public class ServiceImpl implements Callable3 {",
418 " public String call() throws Exception { return 'hi';}",
419 "}")
420 .build();
421
422
423 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
424 assertEquals(1, pluginManager.getEnabledPlugins().size());
425
426 pluginManager.installPlugin(new JarPluginArtifact(otherSvcJar));
427 pluginManager.installPlugin(new JarPluginArtifact(pluginJar2));
428
429 assertEquals("hi", ((OsgiPlugin)pluginManager.getPlugin("test2.plugin")).autowire(TestPluginInstall.Callable3Aware.class).call());
430 assertEquals(3, pluginManager.getEnabledPlugins().size());
431
432 final File updatedJar = new PluginJarBuilder("first")
433 .addFormattedResource("atlassian-plugin.xml",
434 "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
435 " <plugin-info>",
436 " <version>1.0</version>",
437 " <bundle-instructions><Export-Package>my</Export-Package></bundle-instructions>",
438 " </plugin-info>",
439 " <component key='svc' class='my.ServiceImpl' public='true'>",
440 " <interface>java.util.concurrent.Callable</interface>",
441 " </component>",
442 "</atlassian-plugin>")
443 .addFormattedJava("my.ServiceImpl",
444 "package my;",
445 "import java.util.concurrent.Callable;",
446 "public class ServiceImpl implements Callable {",
447 " public Object call() throws Exception { return 'bob';}",
448 "}")
449 .build();
450
451 pluginManager.installPlugin(new JarPluginArtifact(updatedJar));
452 assertEquals(3, pluginManager.getEnabledPlugins().size());
453 assertEquals("hi", ((OsgiPlugin)pluginManager.getPlugin("test2.plugin")).autowire(TestPluginInstall.Callable3Aware.class).call());
454 }
455
456 public void testUpgradeOfBundledPluginWithRefreshingAffectingOtherPluginsCheckingModuleEvents() throws Exception
457 {
458 DefaultModuleDescriptorFactory factory = new DefaultModuleDescriptorFactory(new DefaultHostContainer());
459 factory.addModuleDescriptor("dummy", EventTrackingModuleDescriptor.class);
460
461
462 PluginJarBuilder hostBuilder = new PluginJarBuilder("first")
463 .addFormattedResource("atlassian-plugin.xml",
464 "<atlassian-plugin name='Test' key='host' pluginsVersion='2'>",
465 " <plugin-info>",
466 " <version>1.0</version>",
467 " <bundle-instructions><Export-Package>my</Export-Package></bundle-instructions>",
468 " </plugin-info>",
469 " <dummy key='foo'/>",
470 "</atlassian-plugin>")
471 .addFormattedJava("my.Serviceable",
472 "package my;",
473 "public interface Serviceable {}");
474 final File hostJar = hostBuilder.build();
475
476 final File clientJar = new PluginJarBuilder("second", hostBuilder.getClassLoader())
477 .addFormattedResource("atlassian-plugin.xml",
478 "<atlassian-plugin name='Test 2' key='client' pluginsVersion='2'>",
479 " <plugin-info>",
480 " <version>1.0</version>",
481 " </plugin-info>",
482 " <dummy key='foo'/>",
483 "</atlassian-plugin>")
484 .addFormattedJava("my2.Service",
485 "package my2;",
486 "public class Service implements my.Serviceable {}")
487 .build();
488
489 initBundlingPluginManager(factory, hostJar);
490 assertEquals(1, pluginManager.getEnabledPlugins().size());
491
492 pluginManager.installPlugin(new JarPluginArtifact(clientJar));
493
494 EventTrackingModuleDescriptor hostModule = (EventTrackingModuleDescriptor) pluginManager.getPlugin("host").getModuleDescriptor("foo");
495 assertEquals(1, hostModule.getEnabledCount());
496 assertEquals(0, hostModule.getDisabledCount());
497
498 EventTrackingModuleDescriptor clientModule = (EventTrackingModuleDescriptor) pluginManager.getPlugin("client").getModuleDescriptor("foo");
499 assertEquals(1, clientModule.getEnabledCount());
500 assertEquals(0, clientModule.getDisabledCount());
501
502 pluginManager.installPlugin(new JarPluginArtifact(hostJar));
503
504 hostModule = (EventTrackingModuleDescriptor) pluginManager.getPlugin("host").getModuleDescriptor("foo");
505 assertEquals(1, hostModule.getEnabledCount());
506 assertEquals(0, hostModule.getDisabledCount());
507
508 clientModule = (EventTrackingModuleDescriptor) pluginManager.getPlugin("client").getModuleDescriptor("foo");
509 assertEquals(1, clientModule.getDisabledCount());
510 assertEquals(2, clientModule.getEnabledCount());
511 }
512
513 public void testUpgradeWithRefreshingAffectingOtherPluginsWithClassLoadingOnShutdown() throws Exception
514 {
515 final DefaultModuleDescriptorFactory factory = new DefaultModuleDescriptorFactory(new DefaultHostContainer());
516 initPluginManager(new HostComponentProvider()
517 {
518 public void provide(final ComponentRegistrar registrar)
519 {
520 }
521 }, factory);
522
523 PluginJarBuilder pluginBuilder = new PluginJarBuilder("first")
524 .addFormattedResource("atlassian-plugin.xml",
525 "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
526 " <plugin-info>",
527 " <version>1.0</version>",
528 " <bundle-instructions><Export-Package>my</Export-Package></bundle-instructions>",
529 " </plugin-info>",
530 " <component key='svc' class='my.ServiceImpl' public='true'>",
531 " <interface>java.util.concurrent.Callable</interface>",
532 " </component>",
533 "</atlassian-plugin>")
534 .addFormattedJava("my.ServiceImpl",
535 "package my;",
536 "import java.util.concurrent.Callable;",
537 "public class ServiceImpl implements Callable {",
538 " public Object call() throws Exception { return 'hi';}",
539 "}");
540 final File pluginJar = pluginBuilder.build();
541
542 final File pluginJar2 = new PluginJarBuilder("second", pluginBuilder.getClassLoader())
543 .addFormattedResource("atlassian-plugin.xml",
544 "<atlassian-plugin name='Test 2' key='test2.plugin' pluginsVersion='2'>",
545 " <plugin-info>",
546 " <version>1.0</version>",
547 " <bundle-instructions><Import-Package>my,*</Import-Package>",
548 " <DynamicImport-Package>foo</DynamicImport-Package></bundle-instructions>",
549 " </plugin-info>",
550 " <component-import key='svc' interface='java.util.concurrent.Callable' />",
551 " <component-import key='othersvc' interface='com.atlassian.plugin.osgi.Callable3' />",
552 " <component key='del' class='my2.ServiceDelegate' public='true'>",
553 " <interface>com.atlassian.plugin.osgi.Callable2</interface>",
554 " </component>",
555 "</atlassian-plugin>")
556 .addFormattedJava("my2.ServiceDelegate",
557 "package my2;",
558 "import com.atlassian.plugin.osgi.Callable2;",
559 "import com.atlassian.plugin.osgi.Callable3;",
560 "import java.util.concurrent.Callable;",
561 "public class ServiceDelegate implements Callable2, org.springframework.beans.factory.DisposableBean {",
562 " private final Callable delegate;",
563 " private final Callable3 othersvc;",
564 " public ServiceDelegate(Callable foo,Callable3 othersvc) {",
565 " this.delegate = foo;",
566 " this.othersvc = othersvc;",
567 " }",
568 " public void destroy() {",
569 " try {",
570 " getClass().getClassLoader().loadClass('foo.bar');",
571 " } catch (ClassNotFoundException ex) {}",
572 " }",
573 " public String call() throws Exception { return othersvc.call() + (String)delegate.call();}",
574 "}")
575 .build();
576 final File otherSvcJar = new PluginJarBuilder("otherSvc")
577 .addFormattedResource("atlassian-plugin.xml",
578 "<atlassian-plugin name='Test' key='test.othersvc.plugin' pluginsVersion='2'>",
579 " <plugin-info>",
580 " <version>1.0</version>",
581 " </plugin-info>",
582 " <component key='othersvc' class='othersvc.ServiceImpl' public='true'>",
583 " <interface>com.atlassian.plugin.osgi.Callable3</interface>",
584 " </component>",
585 "</atlassian-plugin>")
586 .addFormattedJava("othersvc.ServiceImpl",
587 "package othersvc;",
588 "import com.atlassian.plugin.osgi.Callable3;",
589 "public class ServiceImpl implements Callable3 {",
590 " public String call() throws Exception { return 'hi';}",
591 "}")
592 .build();
593
594
595 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
596 assertEquals(1, pluginManager.getEnabledPlugins().size());
597
598 pluginManager.installPlugin(new JarPluginArtifact(otherSvcJar));
599 pluginManager.installPlugin(new JarPluginArtifact(pluginJar2));
600
601 assertEquals("hi", ((OsgiPlugin)pluginManager.getPlugin("test2.plugin")).autowire(TestPluginInstall.Callable3Aware.class).call());
602 assertEquals(3, pluginManager.getEnabledPlugins().size());
603
604 final File updatedJar = new PluginJarBuilder("first")
605 .addFormattedResource("atlassian-plugin.xml",
606 "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
607 " <plugin-info>",
608 " <version>1.0</version>",
609 " <bundle-instructions><Export-Package>my</Export-Package></bundle-instructions>",
610 " </plugin-info>",
611 " <component key='svc' class='my.ServiceImpl' public='true'>",
612 " <interface>java.util.concurrent.Callable</interface>",
613 " </component>",
614 "</atlassian-plugin>")
615 .addFormattedJava("my.ServiceImpl",
616 "package my;",
617 "import java.util.concurrent.Callable;",
618 "public class ServiceImpl implements Callable {",
619 " public Object call() throws Exception { return 'bob';}",
620 "}")
621 .build();
622
623 long start = System.currentTimeMillis();
624 pluginManager.installPlugin(new JarPluginArtifact(updatedJar));
625 long timeWaitingForRefresh = System.currentTimeMillis() - start;
626 assertTrue("Refresh seemed to have timed out, which is bad", timeWaitingForRefresh < FelixOsgiContainerManager.REFRESH_TIMEOUT * 1000);
627 assertEquals(3, pluginManager.getEnabledPlugins().size());
628 assertEquals("hi", ((OsgiPlugin)pluginManager.getPlugin("test2.plugin")).autowire(TestPluginInstall.Callable3Aware.class).call());
629 }
630
631 public void testUninstallWithShutdownAffectingOtherPluginsWithClassLoadingOnShutdown() throws Exception
632 {
633 final DefaultModuleDescriptorFactory factory = new DefaultModuleDescriptorFactory(new DefaultHostContainer());
634 initPluginManager(new HostComponentProvider()
635 {
636 public void provide(final ComponentRegistrar registrar)
637 {
638 }
639 }, factory);
640
641 PluginJarBuilder pluginBuilder = new PluginJarBuilder("first")
642 .addFormattedResource("atlassian-plugin.xml",
643 "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
644 " <plugin-info>",
645 " <version>1.0</version>",
646 " <bundle-instructions><Export-Package>my</Export-Package></bundle-instructions>",
647 " </plugin-info>",
648 " <component key='svc' class='my.ServiceImpl' public='true'>",
649 " <interface>java.util.concurrent.Callable</interface>",
650 " </component>",
651 "</atlassian-plugin>")
652 .addFormattedJava("my.ServiceImpl",
653 "package my;",
654 "import java.util.concurrent.Callable;",
655 "public class ServiceImpl implements Callable {",
656 " public Object call() throws Exception { return 'hi';}",
657 "}");
658 final File pluginJar = pluginBuilder.build();
659
660 final File pluginJar2 = new PluginJarBuilder("second", pluginBuilder.getClassLoader())
661 .addFormattedResource("atlassian-plugin.xml",
662 "<atlassian-plugin name='Test 2' key='test2.plugin' pluginsVersion='2'>",
663 " <plugin-info>",
664 " <version>1.0</version>",
665 " <bundle-instructions><Import-Package>my,*</Import-Package>",
666 " <DynamicImport-Package>foo</DynamicImport-Package></bundle-instructions>",
667 " </plugin-info>",
668 " <component-import key='svc' interface='java.util.concurrent.Callable' />",
669 " <component key='del' class='my2.Consumer'/>",
670 "</atlassian-plugin>")
671 .addFormattedJava("my2.Consumer",
672 "package my2;",
673 "import java.util.concurrent.Callable;",
674 "public class Consumer implements org.springframework.beans.factory.DisposableBean {",
675 " private final Callable delegate;",
676 " public Consumer(Callable foo) {",
677 " this.delegate = foo;",
678 " }",
679 " public void destroy() {",
680 " try {",
681 " getClass().getClassLoader().loadClass('foo.bar');",
682 " } catch (ClassNotFoundException ex) {}",
683 " }",
684 "}")
685 .build();
686
687 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
688 assertEquals(1, pluginManager.getEnabledPlugins().size());
689
690 pluginManager.installPlugin(new JarPluginArtifact(pluginJar2));
691
692 assertEquals(2, pluginManager.getEnabledPlugins().size());
693
694 long start = System.currentTimeMillis();
695 pluginManager.uninstall(pluginManager.getPlugin("test.plugin"));
696 long timeWaitingForRefresh = System.currentTimeMillis() - start;
697 assertTrue("Refresh seemed to have timed out, which is bad", timeWaitingForRefresh < FelixOsgiContainerManager.REFRESH_TIMEOUT * 1000);
698 assertEquals(0, pluginManager.getEnabledPlugins().size());
699 }
700 }