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