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.PluginState;
7 import com.atlassian.plugin.hostcontainer.DefaultHostContainer;
8 import com.atlassian.plugin.impl.UnloadablePlugin;
9 import com.atlassian.plugin.osgi.external.SingleModuleDescriptorFactory;
10 import com.atlassian.plugin.osgi.factory.OsgiPlugin;
11 import com.atlassian.plugin.osgi.hostcomponents.ComponentRegistrar;
12 import com.atlassian.plugin.osgi.hostcomponents.HostComponentProvider;
13 import com.atlassian.plugin.servlet.DefaultServletModuleManager;
14 import com.atlassian.plugin.servlet.ServletModuleManager;
15 import com.atlassian.plugin.servlet.descriptors.ServletModuleDescriptor;
16 import com.atlassian.plugin.test.PluginJarBuilder;
17 import com.atlassian.plugin.util.PluginUtils;
18 import com.atlassian.plugin.util.WaitUntil;
19 import com.google.common.collect.ImmutableMap;
20 import org.osgi.framework.Constants;
21
22 import javax.servlet.ServletConfig;
23 import javax.servlet.ServletContext;
24 import javax.servlet.http.HttpServlet;
25 import java.io.File;
26 import java.util.Collections;
27 import java.util.concurrent.TimeUnit;
28 import java.util.concurrent.locks.Lock;
29 import java.util.concurrent.locks.ReentrantLock;
30
31 import static org.mockito.Mockito.mock;
32 import static org.mockito.Mockito.when;
33
34 public final class TestPluginInstall extends PluginInContainerTestBase
35 {
36 private static final String EMPTY_SPRING_CONFIG = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
37 + "<beans xmlns=\"http://www.springframework.org/schema/beans\"\n"
38 + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
39 + " xmlns:osgi=\"http://www.springframework.org/schema/osgi\"\n"
40 + " xsi:schemaLocation=\"http://www.springframework.org/schema/beans\n"
41 + " http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\n"
42 + " http://www.springframework.org/schema/osgi\n"
43 + " http://www.springframework.org/schema/osgi/spring-osgi.xsd\"\n"
44 + ">\n"
45 + "</beans>";
46
47 private static void assertExists(File f)
48 {
49 assertTrue("File should exist: " + f, f.exists());
50 }
51
52 private static void assertDoesNotExist(File f)
53 {
54 assertFalse("File should not exist: " + f, f.exists());
55 }
56
57 public void testUpgradeOfBundledPlugin() throws Exception
58 {
59 final DefaultModuleDescriptorFactory factory = new DefaultModuleDescriptorFactory(hostContainer);
60 factory.addModuleDescriptor("object", ObjectModuleDescriptor.class);
61
62 final File pluginJar = new PluginJarBuilder("testUpgradeOfBundledPlugin")
63 .addFormattedResource("atlassian-plugin.xml",
64 "<atlassian-plugin name='Test' key='test.bundled.plugin' pluginsVersion='2'>",
65 " <plugin-info>",
66 " <version>1.0</version>",
67 " </plugin-info>",
68 " <object key='obj' class='my.Foo'/>",
69 "</atlassian-plugin>")
70 .addFormattedJava("my.Foo",
71 "package my;",
72 "public class Foo {}")
73 .build();
74 initBundlingPluginManager(factory, pluginJar);
75 assertEquals(1, pluginManager.getEnabledPlugins().size());
76 assertEquals("Test", pluginManager.getPlugin("test.bundled.plugin").getName());
77 assertEquals("my.Foo", pluginManager.getPlugin("test.bundled.plugin").getModuleDescriptor("obj").getModule().getClass().getName());
78
79 final File pluginJar2 = new PluginJarBuilder("testUpgradeOfBundledPlugin")
80 .addFormattedResource("atlassian-plugin.xml",
81 "<atlassian-plugin name='Test' key='test.bundled.plugin' pluginsVersion='2'>",
82 " <plugin-info>",
83 " <version>1.0</version>",
84 " </plugin-info>",
85 " <object key='obj' class='my.Bar'/>",
86 "</atlassian-plugin>")
87 .addFormattedJava("my.Bar",
88 "package my;",
89 "public class Bar {}")
90 .build();
91
92 pluginManager.installPlugin(new JarPluginArtifact(pluginJar2));
93
94 assertEquals(1, pluginManager.getEnabledPlugins().size());
95 assertEquals("Test", pluginManager.getPlugin("test.bundled.plugin").getName());
96 assertEquals("my.Bar", pluginManager.getPlugin("test.bundled.plugin").getModuleDescriptor("obj").getModule().getClass().getName());
97
98 }
99
100 public void testUpgradeOfBadPlugin() throws Exception
101 {
102 new PluginJarBuilder("testUpgradeOfBundledPlugin-old")
103 .addFormattedResource("atlassian-plugin.xml",
104 "<atlassian-plugin name='Test' key='test.bundled.plugin' pluginsVersion='2'>",
105 " <plugin-info>",
106 " <version>1.0</version>",
107 " </plugin-info>",
108 " <component key='obj' class='my.Foo'/>",
109 "</atlassian-plugin>")
110 .addFormattedJava("my.Foo",
111 "package my;",
112 "public class Foo {",
113 " public Foo() { throw new RuntimeException('bad plugin');}",
114 "}")
115 .build(pluginsDir);
116 new PluginJarBuilder("testUpgradeOfBundledPlugin-new")
117 .addFormattedResource("atlassian-plugin.xml",
118 "<atlassian-plugin name='Test' key='test.bundled.plugin' pluginsVersion='2'>",
119 " <plugin-info>",
120 " <version>2.0</version>",
121 " </plugin-info>",
122 " <component key='obj' class='my.Foo'/>",
123 "</atlassian-plugin>")
124 .addFormattedJava("my.Foo",
125 "package my;",
126 "public class Foo {",
127 " public Foo() {}",
128 "}")
129 .build(pluginsDir);
130 initPluginManager();
131 assertEquals(1, pluginManager.getEnabledPlugins().size());
132 assertEquals("Test", pluginManager.getPlugin("test.bundled.plugin").getName());
133 assertEquals("2.0", pluginManager.getPlugin("test.bundled.plugin").getPluginInformation().getVersion());
134 }
135
136 public void testUpgradeWithNewComponentImports() throws Exception
137 {
138 final DefaultModuleDescriptorFactory factory = new DefaultModuleDescriptorFactory(new DefaultHostContainer());
139 factory.addModuleDescriptor("dummy", DummyModuleDescriptor.class);
140 initPluginManager(new HostComponentProvider()
141 {
142 public void provide(final ComponentRegistrar registrar)
143 {
144 registrar.register(SomeInterface.class).forInstance(new SomeInterface()
145 {
146 });
147 registrar.register(AnotherInterface.class).forInstance(new AnotherInterface()
148 {
149 });
150 }
151 }, factory);
152
153 final File pluginJar = new PluginJarBuilder("first")
154 .addFormattedResource("atlassian-plugin.xml",
155 "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
156 " <plugin-info>",
157 " <version>1.0</version>",
158 " </plugin-info>",
159 " <component-import key='comp1' interface='com.atlassian.plugin.osgi.SomeInterface' />",
160 " <dummy key='dum1'/>", "</atlassian-plugin>")
161 .build();
162 final File pluginJar2 = new PluginJarBuilder("second")
163 .addFormattedResource("atlassian-plugin.xml",
164 "<atlassian-plugin name='Test 2' key='test.plugin' pluginsVersion='2'>",
165 " <plugin-info>",
166 " <version>1.0</version>",
167 " </plugin-info>",
168 " <component-import key='comp1' interface='com.atlassian.plugin.osgi.SomeInterface' />",
169 " <component-import key='comp2' interface='com.atlassian.plugin.osgi.AnotherInterface' />",
170 " <dummy key='dum1'/>",
171 " <dummy key='dum2'/>",
172 "</atlassian-plugin>")
173 .build();
174
175 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
176 assertEquals(1, pluginManager.getEnabledPlugins().size());
177 assertEquals("Test", pluginManager.getPlugin("test.plugin").getName());
178 assertEquals(2, pluginManager.getPlugin("test.plugin").getModuleDescriptors().size());
179 pluginManager.installPlugin(new JarPluginArtifact(pluginJar2));
180 assertEquals(1, pluginManager.getEnabledPlugins().size());
181 assertEquals(4, pluginManager.getPlugin("test.plugin").getModuleDescriptors().size());
182 assertEquals("Test 2", pluginManager.getPlugin("test.plugin").getName());
183 }
184
185 public void testInstallWithClassConstructorReferencingHostClassWithHostComponent() throws Exception
186 {
187 final DefaultModuleDescriptorFactory factory = new DefaultModuleDescriptorFactory(hostContainer);
188 factory.addModuleDescriptor("object", ObjectModuleDescriptor.class);
189 initPluginManager(new HostComponentProvider()
190 {
191 public void provide(final ComponentRegistrar registrar)
192 {
193 registrar.register(SomeInterface.class).forInstance(new SomeInterface()
194 {
195 });
196 }
197 }, factory);
198
199 final File pluginJar = new PluginJarBuilder("testUpgradeOfBundledPlugin")
200 .addFormattedResource("atlassian-plugin.xml",
201 "<atlassian-plugin name='Test' key='hostClass' pluginsVersion='2'>",
202 " <plugin-info>",
203 " <version>1.0</version>",
204 " </plugin-info>",
205 " <object key='hostClass' class='com.atlassian.plugin.osgi.HostClassUsingHostComponentConstructor'/>",
206 "</atlassian-plugin>")
207 .build();
208
209 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
210 assertEquals(1, pluginManager.getEnabledPlugins().size());
211 assertEquals("Test", pluginManager.getPlugin("hostClass").getName());
212 assertEquals(1, pluginManager.getPlugin("hostClass").getModuleDescriptors().size());
213
214 HostClassUsingHostComponentConstructor module = (HostClassUsingHostComponentConstructor) pluginManager.getPlugin("hostClass").getModuleDescriptor("hostClass").getModule();
215 assertNotNull(module);
216 }
217
218 public void testInstallWithClassSetterReferencingHostClassWithHostComponent() throws Exception
219 {
220 final DefaultModuleDescriptorFactory factory = new DefaultModuleDescriptorFactory(hostContainer);
221 factory.addModuleDescriptor("object", ObjectModuleDescriptor.class);
222
223 initPluginManager(new HostComponentProvider()
224 {
225 public void provide(final ComponentRegistrar registrar)
226 {
227 registrar.register(SomeInterface.class).forInstance(new SomeInterface()
228 {
229 });
230 }
231 }, factory);
232
233 final File pluginJar = new PluginJarBuilder("testUpgradeOfBundledPlugin")
234 .addFormattedResource("atlassian-plugin.xml",
235 "<atlassian-plugin name='Test' key='hostClass' pluginsVersion='2'>",
236 " <plugin-info>",
237 " <version>1.0</version>",
238 " </plugin-info>",
239 " <object key='hostClass' class='com.atlassian.plugin.osgi.HostClassUsingHostComponentSetter'/>",
240 "</atlassian-plugin>")
241 .build();
242
243 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
244 assertEquals(1, pluginManager.getEnabledPlugins().size());
245 assertEquals("Test", pluginManager.getPlugin("hostClass").getName());
246 assertEquals(1, pluginManager.getPlugin("hostClass").getModuleDescriptors().size());
247
248 HostClassUsingHostComponentSetter module = (HostClassUsingHostComponentSetter) pluginManager.getPlugin("hostClass").getModuleDescriptor("hostClass").getModule();
249 assertNotNull(module);
250 assertNotNull(module.getSomeInterface());
251 }
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278 public void testUpgradeWithNoAutoDisable() throws Exception
279 {
280 DefaultModuleDescriptorFactory factory = new DefaultModuleDescriptorFactory(new DefaultHostContainer());
281 factory.addModuleDescriptor("dummy", DummyModuleDescriptor.class);
282 initPluginManager(new HostComponentProvider(){
283 public void provide(ComponentRegistrar registrar)
284 {
285 registrar.register(SomeInterface.class).forInstance(new SomeInterface(){});
286 registrar.register(AnotherInterface.class).forInstance(new AnotherInterface(){});
287 }
288 }, factory);
289
290 File pluginJar = new PluginJarBuilder("first")
291 .addFormattedResource("atlassian-plugin.xml",
292 "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
293 " <plugin-info>",
294 " <version>1.0</version>",
295 " </plugin-info>",
296 " <component-import key='comp1' interface='com.atlassian.plugin.osgi.SomeInterface' />",
297 " <dummy key='dum1'/>",
298 "</atlassian-plugin>")
299 .build();
300 final File pluginJar2 = new PluginJarBuilder("second")
301 .addFormattedResource("atlassian-plugin.xml",
302 "<atlassian-plugin name='Test 2' key='test.plugin' pluginsVersion='2'>",
303 " <plugin-info>",
304 " <version>1.0</version>",
305 " </plugin-info>",
306 " <component-import key='comp1' interface='com.atlassian.plugin.osgi.SomeInterface' />",
307 " <dummy key='dum1'/>",
308 " <dummy key='dum2'/>",
309 "</atlassian-plugin>")
310 .build();
311
312 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
313 assertTrue(pluginManager.isPluginEnabled("test.plugin"));
314
315 final Lock lock = new ReentrantLock();
316 Thread upgradeThread = new Thread()
317 {
318 public void run()
319 {
320 lock.lock();
321 pluginManager.installPlugin(new JarPluginArtifact(pluginJar2));
322 lock.unlock();
323 }
324 };
325
326 Thread isEnabledThread = new Thread()
327 {
328 public void run()
329 {
330 try
331 {
332 while (!lock.tryLock(10, TimeUnit.SECONDS))
333 pluginManager.isPluginEnabled("test.plugin");
334 }
335 catch (InterruptedException e)
336 {
337 fail();
338 }
339 }
340 };
341 upgradeThread.start();
342 isEnabledThread.start();
343
344 upgradeThread.join(10000);
345
346 assertTrue(pluginManager.isPluginEnabled("test.plugin"));
347 }
348
349 public void testUpgradeTestingForCachedXml() throws Exception
350 {
351 final DefaultModuleDescriptorFactory factory = new DefaultModuleDescriptorFactory(new DefaultHostContainer());
352 factory.addModuleDescriptor("dummy", DummyModuleDescriptor.class);
353 initPluginManager(new HostComponentProvider()
354 {
355 public void provide(final ComponentRegistrar registrar)
356 {
357 registrar.register(SomeInterface.class).forInstance(new SomeInterface()
358 {});
359 registrar.register(AnotherInterface.class).forInstance(new AnotherInterface()
360 {});
361 }
362 }, factory);
363
364 final File pluginJar = new PluginJarBuilder("first").addFormattedResource("atlassian-plugin.xml",
365 "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>", " <plugin-info>", " <version>1.0</version>",
366 " </plugin-info>", " <component key='comp1' interface='com.atlassian.plugin.osgi.SomeInterface' class='my.ServiceImpl' />",
367 "</atlassian-plugin>").addFormattedJava("my.ServiceImpl", "package my;",
368 "public class ServiceImpl implements com.atlassian.plugin.osgi.SomeInterface {}").build();
369 final File pluginJar2 = new PluginJarBuilder("second").addFormattedResource("atlassian-plugin.xml",
370 "<atlassian-plugin name='Test 2' key='test.plugin' pluginsVersion='2'>", " <plugin-info>", " <version>1.0</version>",
371 " </plugin-info>", "</atlassian-plugin>").build();
372
373 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
374 assertEquals(1, pluginManager.getEnabledPlugins().size());
375 assertEquals("Test", pluginManager.getPlugin("test.plugin").getName());
376 pluginManager.installPlugin(new JarPluginArtifact(pluginJar2));
377 assertEquals(1, pluginManager.getEnabledPlugins().size());
378 assertEquals("Test 2", pluginManager.getPlugin("test.plugin").getName());
379 }
380
381 public void testPluginDependentOnPackageImport() throws Exception
382 {
383 HostComponentProvider prov = new HostComponentProvider()
384 {
385 public void provide(final ComponentRegistrar registrar)
386 {
387 registrar.register(ServletConfig.class).forInstance(new HttpServlet() {});
388 }
389 };
390 File servletJar = new PluginJarBuilder("first")
391 .addFormattedResource("META-INF/MANIFEST.MF",
392 "Export-Package: javax.servlet.http;version='4.0.0',javax.servlet;version='4.0.0'",
393 "Import-Package: javax.servlet.http;version='4.0.0',javax.servlet;version='4.0.0'",
394 "Bundle-SymbolicName: first",
395 "Bundle-Version: 4.0.0",
396 "Manifest-Version: 1.0",
397 "")
398 .addFormattedJava("javax.servlet.Servlet",
399 "package javax.servlet;",
400 "public interface Servlet {}")
401 .addFormattedJava("javax.servlet.http.HttpServlet",
402 "package javax.servlet.http;",
403 "public abstract class HttpServlet implements javax.servlet.Servlet{}")
404 .build();
405
406 File pluginJar = new PluginJarBuilder("asecond")
407 .addFormattedResource("atlassian-plugin.xml",
408 "<atlassian-plugin name='Test' key='second' pluginsVersion='2'>",
409 " <plugin-info>",
410 " <version>1.0</version>",
411 " <bundle-instructions><Import-Package>javax.servlet.http;version='[2.3,2.3]',javax.servlet;version='[2.3,2.3]',*</Import-Package></bundle-instructions>",
412 " </plugin-info>",
413 "</atlassian-plugin>")
414 .addFormattedJava("second.MyImpl",
415 "package second;",
416 "public class MyImpl {",
417 " public MyImpl(javax.servlet.ServletConfig config) {",
418 " }",
419 "}")
420 .build();
421
422 initPluginManager(prov);
423 pluginManager.installPlugin(new JarPluginArtifact(servletJar));
424 pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
425 WaitUntil.invoke(new BasicWaitCondition()
426 {
427 public boolean isFinished()
428 {
429 return pluginManager.getEnabledPlugins().size() == 2;
430 }
431 });
432
433 assertEquals(2, pluginManager.getEnabledPlugins().size());
434 assertNotNull(pluginManager.getPlugin("first-4.0.0"));
435 assertNotNull(pluginManager.getPlugin("second"));
436 }
437
438 public void testPluginWithHostComponentUsingOldPackageImport() throws Exception
439 {
440 final PluginJarBuilder firstBuilder = new PluginJarBuilder("oldpkgfirst");
441 firstBuilder
442 .addFormattedResource("atlassian-plugin.xml",
443 "<atlassian-plugin name='Test' key='first' pluginsVersion='2'>",
444 " <plugin-info>",
445 " <version>1.0</version>",
446 " <bundle-instructions>",
447 " <Export-Package>first</Export-Package>",
448 " </bundle-instructions>",
449 " </plugin-info>",
450 " <servlet key='foo' class='second.MyServlet'>",
451 " <url-pattern>/foo</url-pattern>",
452 " </servlet>",
453 "</atlassian-plugin>")
454 .addFormattedJava("first.MyInterface",
455 "package first;",
456 "public interface MyInterface {}")
457 .build(pluginsDir);
458
459 new PluginJarBuilder("oldpkgsecond", firstBuilder.getClassLoader())
460 .addPluginInformation("second", "Some name", "1.0")
461 .addFormattedJava("second.MyImpl",
462 "package second;",
463 "public class MyImpl implements first.MyInterface {}")
464 .build(pluginsDir);
465
466 initPluginManager();
467
468 assertEquals(2, pluginManager.getEnabledPlugins().size());
469 assertNotNull(pluginManager.getPlugin("first"));
470 assertNotNull(pluginManager.getPlugin("second"));
471 }
472
473 public void testPluginWithServletDependentOnPackageImport() throws Exception
474 {
475 final PluginJarBuilder firstBuilder = new PluginJarBuilder("first");
476 firstBuilder
477 .addPluginInformation("first", "Some name", "1.0")
478 .addFormattedJava("first.MyInterface",
479 "package first;",
480 "public interface MyInterface {}")
481 .addFormattedResource("META-INF/MANIFEST.MF",
482 "Manifest-Version: 1.0",
483 "Bundle-SymbolicName: first",
484 "Bundle-Version: 1.0",
485 "Export-Package: first",
486 "")
487 .build(pluginsDir);
488
489 new PluginJarBuilder("asecond", firstBuilder.getClassLoader())
490 .addFormattedResource("atlassian-plugin.xml",
491 "<atlassian-plugin name='Test' key='asecond' pluginsVersion='2'>",
492 " <plugin-info>",
493 " <version>1.0</version>",
494 " </plugin-info>",
495 " <servlet key='foo' class='second.MyServlet'>",
496 " <url-pattern>/foo</url-pattern>",
497 " </servlet>",
498 "</atlassian-plugin>")
499 .addFormattedJava("second.MyServlet",
500 "package second;",
501 "public class MyServlet extends javax.servlet.http.HttpServlet implements first.MyInterface {}")
502 .build(pluginsDir);
503
504 initPluginManager(null, new SingleModuleDescriptorFactory(new DefaultHostContainer(), "servlet", StubServletModuleDescriptor.class));
505
506 assertEquals(2, pluginManager.getEnabledPlugins().size());
507 assertTrue(pluginManager.getPlugin("first").getPluginState() == PluginState.ENABLED);
508 assertNotNull(pluginManager.getPlugin("asecond").getPluginState() == PluginState.ENABLED);
509 }
510
511 public void testPluginWithServletRefreshedAfterOtherPluginUpgraded() throws Exception
512 {
513 final PluginJarBuilder firstBuilder = new PluginJarBuilder("first");
514 firstBuilder
515 .addPluginInformation("first", "Some name", "1.0")
516 .addFormattedJava("first.MyInterface",
517 "package first;",
518 "public interface MyInterface {}")
519 .addFormattedResource("META-INF/MANIFEST.MF",
520 "Manifest-Version: 1.0",
521 "Bundle-SymbolicName: first",
522 "Bundle-Version: 1.0",
523 "Export-Package: first",
524 "")
525 .build(pluginsDir);
526
527 new PluginJarBuilder("asecond", firstBuilder.getClassLoader())
528 .addFormattedResource("atlassian-plugin.xml",
529 "<atlassian-plugin name='Test' key='asecond' pluginsVersion='2'>",
530 " <plugin-info>",
531 " <version>1.0</version>",
532 " </plugin-info>",
533 " <servlet key='foo' class='second.MyServlet'>",
534 " <url-pattern>/foo</url-pattern>",
535 " </servlet>",
536 "</atlassian-plugin>")
537 .addFormattedJava("second.MyServlet",
538 "package second;",
539 "import com.atlassian.plugin.osgi.Callable2;",
540 "public class MyServlet extends javax.servlet.http.HttpServlet implements first.MyInterface {",
541 " private Callable2 callable;",
542 " public MyServlet(Callable2 cal) { this.callable = cal; }",
543 " public String getServletInfo() {",
544 " try {return callable.call() + ' bob';} catch (Exception ex) { throw new RuntimeException(ex);}",
545 " }",
546 "}")
547 .build(pluginsDir);
548
549 HostComponentProvider prov = new HostComponentProvider()
550 {
551
552 public void provide(ComponentRegistrar registrar)
553 {
554 registrar.register(Callable2.class).forInstance(new Callable2()
555 {
556 public String call()
557 {
558 return "hi";
559 }
560 });
561
562 }
563 };
564
565 ServletContext ctx = mock(ServletContext.class);
566 when(ctx.getInitParameterNames()).thenReturn(Collections.enumeration(Collections.emptyList()));
567 ServletConfig servletConfig = mock(ServletConfig.class);
568 when(servletConfig.getServletContext()).thenReturn(ctx);
569
570 ServletModuleManager mgr = new DefaultServletModuleManager(pluginEventManager);
571 hostContainer = createHostContainer(Collections.<Class<?>, Object>singletonMap(ServletModuleManager.class, mgr));
572 initPluginManager(prov, new SingleModuleDescriptorFactory(
573 hostContainer,
574 "servlet",
575 ServletModuleDescriptor.class));
576
577 assertEquals(2, pluginManager.getEnabledPlugins().size());
578 assertTrue(pluginManager.getPlugin("first").getPluginState() == PluginState.ENABLED);
579 assertNotNull(pluginManager.getPlugin("asecond").getPluginState() == PluginState.ENABLED);
580 assertEquals("hi bob", mgr.getServlet("/foo", servletConfig).getServletInfo());
581
582
583
584 final File updatedJar = new PluginJarBuilder("first-updated")
585 .addPluginInformation("foo", "Some name", "1.0")
586 .addFormattedJava("first.MyInterface",
587 "package first;",
588 "public interface MyInterface {}")
589 .addFormattedResource("META-INF/MANIFEST.MF",
590 "Manifest-Version: 1.0",
591 "Bundle-SymbolicName: foo",
592 "Bundle-Version: 1.0",
593 "Export-Package: first",
594 "")
595 .build();
596 pluginManager.installPlugin(new JarPluginArtifact(updatedJar));
597
598 WaitUntil.invoke(new BasicWaitCondition()
599 {
600 public boolean isFinished()
601 {
602 return pluginManager.isPluginEnabled("asecond");
603 }
604
605 });
606
607 assertEquals("hi bob", mgr.getServlet("/foo", servletConfig).getServletInfo());
608 }
609
610 public void testLotsOfHostComponents() throws Exception
611 {
612 new PluginJarBuilder("first")
613 .addFormattedResource("atlassian-plugin.xml",
614 "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
615 " <plugin-info>",
616 " <version>1.0</version>",
617 " </plugin-info>",
618 " <dummy key='dum1'/>",
619 "</atlassian-plugin>")
620 .build(pluginsDir);
621 new PluginJarBuilder("second")
622 .addFormattedResource("atlassian-plugin.xml",
623 "<atlassian-plugin name='Test 2' key='test.plugin2' pluginsVersion='2'>",
624 " <plugin-info>",
625 " <version>1.0</version>",
626 " </plugin-info>",
627 " <dummy key='dum1'/>",
628 " <dummy key='dum2'/>",
629 "</atlassian-plugin>")
630 .build(pluginsDir);
631
632 final DefaultModuleDescriptorFactory factory = new DefaultModuleDescriptorFactory(new DefaultHostContainer());
633 factory.addModuleDescriptor("dummy", DummyModuleDescriptor.class);
634 initPluginManager(new HostComponentProvider()
635 {
636 public void provide(final ComponentRegistrar registrar)
637 {
638 for (int x = 0; x < 100; x++)
639 {
640 registrar.register(SomeInterface.class).forInstance(new SomeInterface()
641 {}).withName("some" + x);
642 registrar.register(AnotherInterface.class).forInstance(new AnotherInterface()
643 {}).withName("another" + x);
644 }
645 }
646 }, factory);
647
648 assertEquals(2, pluginManager.getEnabledPlugins().size());
649 }
650
651 public void testInstallWithManifestNoSpringContextAndComponents() throws Exception
652 {
653 final BooleanFlag flag = new DefaultBooleanFlag(false);
654 new PluginJarBuilder("first")
655 .addFormattedResource("atlassian-plugin.xml",
656 "<atlassian-plugin name='Test' key='first' pluginsVersion='2'>",
657 " <plugin-info>",
658 " <version>1.0</version>",
659 " </plugin-info>",
660 " <component key='foo' class='first.MyClass' interface='first.MyInterface' public='true'/>",
661 "</atlassian-plugin>")
662 .addFormattedJava("first.MyInterface",
663 "package first;",
664 "public interface MyInterface {}")
665 .addFormattedJava("first.MyClass",
666 "package first;",
667 "public class MyClass implements MyInterface{",
668 " public MyClass(com.atlassian.plugin.osgi.BooleanFlag bool) { bool.set(true); }",
669 "}")
670 .addFormattedResource("META-INF/MANIFEST.MF",
671 "Manifest-Version: 1.0",
672 "Bundle-SymbolicName: foo",
673 "Bundle-Version: 1.0",
674 "Export-Package: first",
675 "")
676 .build(pluginsDir);
677
678 initPluginManager(new HostComponentProvider()
679 {
680 public void provide(ComponentRegistrar registrar)
681 {
682 registrar.register(BooleanFlag.class).forInstance(flag).withName("bob");
683 }
684 });
685
686 assertEquals(1, pluginManager.getEnabledPlugins().size());
687 assertNotNull(pluginManager.getPlugin("first"));
688 assertTrue(flag.get());
689 }
690
691 public void testInstallWithManifestNoDescriptorWithSpringXml() throws Exception
692 {
693 new PluginJarBuilder("nodesc")
694 .manifest(new ImmutableMap.Builder<String, String>()
695 .put(OsgiPlugin.ATLASSIAN_PLUGIN_KEY, "nodesc")
696 .put(Constants.BUNDLE_VERSION, "1.0")
697 .build())
698 .addResource("META-INF/spring/foo.xml", EMPTY_SPRING_CONFIG)
699 .build(pluginsDir);
700
701 initPluginManager();
702
703 assertEquals(1, pluginManager.getEnabledPlugins().size());
704 Plugin plugin = pluginManager.getPlugin("nodesc");
705 assertNotNull(plugin);
706 assertEquals("1.0", plugin.getPluginInformation().getVersion());
707 assertEquals("nodesc", plugin.getKey());
708 assertEquals(0, plugin.getModuleDescriptors().size());
709 }
710
711 public void testInstallWithManifestNoDescriptorWithSpringHeader() throws Exception
712 {
713 new PluginJarBuilder("nodesc")
714 .manifest(new ImmutableMap.Builder<String, String>()
715 .put(OsgiPlugin.ATLASSIAN_PLUGIN_KEY, "nodesc")
716 .put(Constants.BUNDLE_VERSION, "1.0")
717 .put("Spring-Context", "*;timeout:=60")
718 .build())
719 .build(pluginsDir);
720
721 initPluginManager();
722
723 assertEquals(1, pluginManager.getEnabledPlugins().size());
724 Plugin plugin = pluginManager.getPlugin("nodesc");
725 assertNotNull(plugin);
726 assertEquals("1.0", plugin.getPluginInformation().getVersion());
727 assertEquals("nodesc", plugin.getKey());
728 assertEquals(0, plugin.getModuleDescriptors().size());
729 }
730
731
732 public void notTestInstallWithComponentBeanNameConflictedWithHostComponent() throws Exception
733 {
734 new PluginJarBuilder("first")
735 .addFormattedResource("atlassian-plugin.xml",
736 "<atlassian-plugin name='Test' key='first' pluginsVersion='2'>",
737 " <plugin-info>",
738 " <version>1.0</version>",
739 " </plugin-info>",
740 " <component key='host_component1' class='first.MyClass' interface='first.MyInterface'/>",
741 "</atlassian-plugin>")
742 .addFormattedJava("com.atlassian.plugin.osgi.SomeInterface",
743 "package com.atlassian.plugin.osgi;",
744 "public interface SomeInterface {}")
745 .addFormattedJava("first.MyClass",
746 "package first;",
747 "import com.atlassian.plugin.osgi.SomeInterface;",
748 "public class MyClass implements SomeInterface{",
749 "}")
750 .build(pluginsDir);
751
752 initPluginManager(new HostComponentProvider()
753 {
754 public void provide(ComponentRegistrar registrar)
755 {
756 registrar.register(SomeInterface.class).forInstance(new SomeInterface(){}).withName("host_component1");
757 }
758 });
759
760
761 assertEquals(0, pluginManager.getEnabledPlugins().size());
762 assertTrue(pluginManager.getPlugins().toArray()[0] instanceof UnloadablePlugin);
763
764
765 assertTrue(pluginManager.getPlugins().toArray(new UnloadablePlugin[1])[0].getErrorText().contains("host_component1"));
766 }
767
768 public void testInstallWithStrangePath() throws Exception
769 {
770 File strangeDir = new File(tmpDir, "20%time");
771 strangeDir.mkdir();
772 File oldTmp = tmpDir;
773 try
774 {
775 tmpDir = strangeDir;
776 cacheDir = new File(tmpDir, "felix-cache");
777 cacheDir.mkdir();
778 pluginsDir = new File(tmpDir, "plugins");
779 pluginsDir.mkdir();
780
781 new PluginJarBuilder("strangePath")
782 .addFormattedResource("atlassian-plugin.xml",
783 "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
784 " <plugin-info>",
785 " <version>1.0</version>",
786 " </plugin-info>",
787 "</atlassian-plugin>")
788 .build(pluginsDir);
789
790 final DefaultModuleDescriptorFactory factory = new DefaultModuleDescriptorFactory(new DefaultHostContainer());
791 factory.addModuleDescriptor("dummy", DummyModuleDescriptor.class);
792 initPluginManager(new HostComponentProvider()
793 {
794 public void provide(final ComponentRegistrar registrar)
795 {
796 }
797 }, factory);
798
799 assertEquals(1, pluginManager.getEnabledPlugins().size());
800 }
801 finally
802 {
803 tmpDir = oldTmp;
804 }
805 }
806
807 public void testInstallWithUnsatisifedDependency() throws Exception
808 {
809 File plugin = new PluginJarBuilder("unsatisifiedDependency")
810 .addFormattedResource("atlassian-plugin.xml",
811 "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
812 " <plugin-info>",
813 " <version>1.0</version>",
814 " </plugin-info>",
815 " <component-import key='foo' interface='java.util.concurrent.Callable' />",
816 "</atlassian-plugin>")
817 .build(pluginsDir);
818
819 long start = System.currentTimeMillis();
820
821 System.setProperty("atlassian.dev.mode", "true");
822 System.setProperty(PluginUtils.ATLASSIAN_PLUGINS_ENABLE_WAIT, "7");
823 try
824 {
825 initPluginManager();
826
827 assertTrue(start + (60 * 1000) > System.currentTimeMillis());
828 }
829 finally
830 {
831
832 System.setProperty("atlassian.dev.mode", "false");
833 System.clearProperty(PluginUtils.ATLASSIAN_PLUGINS_ENABLE_WAIT);
834 }
835 }
836
837 public void testInstallSimplePluginNoSpring() throws Exception
838 {
839 File jar = new PluginJarBuilder("strangePath")
840 .addPluginInformation("no-spring", "foo", "1.0")
841 .build();
842
843 initPluginManager();
844 pluginManager.installPlugin(new JarPluginArtifact(jar));
845
846 assertEquals(1, pluginManager.getEnabledPlugins().size());
847 }
848
849 public void testInstallSimplePluginWithNoManifest() throws Exception
850 {
851 File jar = new PluginJarBuilder("strangePath")
852 .addPluginInformation("no-spring", "foo", "1.0")
853 .buildWithNoManifest();
854
855 initPluginManager();
856 pluginManager.installPlugin(new JarPluginArtifact(jar));
857
858 assertEquals(1, pluginManager.getEnabledPlugins().size());
859 }
860
861 public void testInstallPluginTakesTooLong() throws Exception
862 {
863 System.setProperty(PluginUtils.ATLASSIAN_PLUGINS_ENABLE_WAIT, "3");
864 try
865 {
866 final PluginJarBuilder builder = new PluginJarBuilder("first")
867 .addFormattedResource("atlassian-plugin.xml",
868 "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
869 " <plugin-info>",
870 " <version>1.0</version>",
871 " </plugin-info>",
872 " <component key='svc' class='my.ServiceImpl' public='true'>",
873 " <interface>my.Service</interface>",
874 " </component>",
875 "</atlassian-plugin>")
876 .addFormattedJava("my.Service",
877 "package my;",
878 "public interface Service {",
879 " public Object call() throws Exception;",
880 "}")
881 .addFormattedJava("my.ServiceImpl",
882 "package my;",
883 "public class ServiceImpl implements Service {",
884 "public ServiceImpl(){",
885 "try{",
886 "Thread.sleep(10000);",
887 "}catch(Exception e){}",
888 "}",
889 " public Object call() throws Exception { ",
890 " return 'hi';}",
891 "}");
892 final File jar = builder.build();
893 initPluginManager();
894
895 pluginManager.installPlugin(new JarPluginArtifact(jar));
896
897 assertEquals(0, pluginManager.getEnabledPlugins().size());
898 }
899 finally
900 {
901 System.clearProperty(PluginUtils.ATLASSIAN_PLUGINS_ENABLE_WAIT);
902 }
903 }
904
905 public void testInstallPluginVersion3() throws Exception
906 {
907 initPluginManager();
908
909 final File v3plugin = new PluginJarBuilder("v3-plugin")
910 .addFormattedResource("atlassian-plugin.xml",
911 "<atlassian-plugin name='V3 Plugin' key='v3-plugin' pluginsVersion='3'>",
912 " <plugin-info>",
913 " <version>1.0</version>",
914 " </plugin-info>",
915 "</atlassian-plugin>")
916 .addFormattedResource("META-INF/MANIFEST.MF",
917 "Bundle-SymbolicName: v3-plugin",
918
919
920 OsgiPlugin.ATLASSIAN_PLUGIN_KEY + ": v3-plugin",
921 "Bundle-Version: 1.0.0",
922 "Manifest-Version: 1.0",
923 "Spring-Context: *;timeout:=60",
924 "")
925 .build();
926
927 pluginManager.installPlugin(new JarPluginArtifact(v3plugin));
928
929 assertEquals(1, pluginManager.getEnabledPlugins().size());
930 assertNotNull(pluginManager.getEnabledPlugin("v3-plugin"));
931 }
932
933 public static class Callable3Aware
934 {
935 private final Callable3 callable;
936
937 public Callable3Aware(Callable3 callable)
938 {
939 this.callable = callable;
940 }
941
942 public String call() throws Exception
943 {
944 return callable.call();
945 }
946 }
947 }