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
611 public void testModuleDescriptorWithNamespace() throws Exception
612 {
613 new PluginJarBuilder("asecond")
614 .addFormattedResource("atlassian-plugin.xml",
615 "<atlassian-plugin name='Test' key='asecond' pluginsVersion='2'",
616 " xmlns='http://www.atlassian.com/schema/plugins'",
617 " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'",
618 " xsi:schemaLocation='http://www.atlassian.com/schema/plugins http://schema.atlassian.com/refapp/refapp-2.9.xsd'>",
619 " <plugin-info>",
620 " <version>1.0</version>",
621 " </plugin-info>",
622 " <servlet key='foo' class='second.MyServlet'>",
623 " <url-pattern>/foo</url-pattern>",
624 " </servlet>",
625 "</atlassian-plugin>")
626 .addFormattedJava("second.MyServlet",
627 "package second;",
628 "public class MyServlet extends javax.servlet.http.HttpServlet {}")
629 .build(pluginsDir);
630
631 ServletContext ctx = mock(ServletContext.class);
632 when(ctx.getInitParameterNames()).thenReturn(Collections.enumeration(Collections.emptyList()));
633 ServletConfig servletConfig = mock(ServletConfig.class);
634 when(servletConfig.getServletContext()).thenReturn(ctx);
635
636 ServletModuleManager mgr = new DefaultServletModuleManager(pluginEventManager);
637 hostContainer = createHostContainer(Collections.<Class<?>, Object>singletonMap(ServletModuleManager.class, mgr));
638 initPluginManager(null, new SingleModuleDescriptorFactory(
639 hostContainer,
640 "servlet",
641 ServletModuleDescriptor.class));
642
643 assertEquals(1, pluginManager.getEnabledPlugins().size());
644 assertNotNull(pluginManager.getPlugin("asecond").getPluginState() == PluginState.ENABLED);
645 }
646
647 public void testLotsOfHostComponents() throws Exception
648 {
649 new PluginJarBuilder("first")
650 .addFormattedResource("atlassian-plugin.xml",
651 "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
652 " <plugin-info>",
653 " <version>1.0</version>",
654 " </plugin-info>",
655 " <dummy key='dum1'/>",
656 "</atlassian-plugin>")
657 .build(pluginsDir);
658 new PluginJarBuilder("second")
659 .addFormattedResource("atlassian-plugin.xml",
660 "<atlassian-plugin name='Test 2' key='test.plugin2' pluginsVersion='2'>",
661 " <plugin-info>",
662 " <version>1.0</version>",
663 " </plugin-info>",
664 " <dummy key='dum1'/>",
665 " <dummy key='dum2'/>",
666 "</atlassian-plugin>")
667 .build(pluginsDir);
668
669 final DefaultModuleDescriptorFactory factory = new DefaultModuleDescriptorFactory(new DefaultHostContainer());
670 factory.addModuleDescriptor("dummy", DummyModuleDescriptor.class);
671 initPluginManager(new HostComponentProvider()
672 {
673 public void provide(final ComponentRegistrar registrar)
674 {
675 for (int x = 0; x < 100; x++)
676 {
677 registrar.register(SomeInterface.class).forInstance(new SomeInterface()
678 {}).withName("some" + x);
679 registrar.register(AnotherInterface.class).forInstance(new AnotherInterface()
680 {}).withName("another" + x);
681 }
682 }
683 }, factory);
684
685 assertEquals(2, pluginManager.getEnabledPlugins().size());
686 }
687
688 public void testInstallWithManifestNoSpringContextAndComponents() throws Exception
689 {
690 final BooleanFlag flag = new DefaultBooleanFlag(false);
691 new PluginJarBuilder("first")
692 .addFormattedResource("atlassian-plugin.xml",
693 "<atlassian-plugin name='Test' key='first' pluginsVersion='2'>",
694 " <plugin-info>",
695 " <version>1.0</version>",
696 " </plugin-info>",
697 " <component key='foo' class='first.MyClass' interface='first.MyInterface' public='true'/>",
698 "</atlassian-plugin>")
699 .addFormattedJava("first.MyInterface",
700 "package first;",
701 "public interface MyInterface {}")
702 .addFormattedJava("first.MyClass",
703 "package first;",
704 "public class MyClass implements MyInterface{",
705 " public MyClass(com.atlassian.plugin.osgi.BooleanFlag bool) { bool.set(true); }",
706 "}")
707 .addFormattedResource("META-INF/MANIFEST.MF",
708 "Manifest-Version: 1.0",
709 "Bundle-SymbolicName: foo",
710 "Bundle-Version: 1.0",
711 "Export-Package: first",
712 "")
713 .build(pluginsDir);
714
715 initPluginManager(new HostComponentProvider()
716 {
717 public void provide(ComponentRegistrar registrar)
718 {
719 registrar.register(BooleanFlag.class).forInstance(flag).withName("bob");
720 }
721 });
722
723 assertEquals(1, pluginManager.getEnabledPlugins().size());
724 assertNotNull(pluginManager.getPlugin("first"));
725 assertTrue(flag.get());
726 }
727
728 public void testInstallWithManifestNoDescriptorWithSpringXml() throws Exception
729 {
730 new PluginJarBuilder("nodesc")
731 .manifest(new ImmutableMap.Builder<String, String>()
732 .put(OsgiPlugin.ATLASSIAN_PLUGIN_KEY, "nodesc")
733 .put(Constants.BUNDLE_VERSION, "1.0")
734 .build())
735 .addResource("META-INF/spring/foo.xml", EMPTY_SPRING_CONFIG)
736 .build(pluginsDir);
737
738 initPluginManager();
739
740 assertEquals(1, pluginManager.getEnabledPlugins().size());
741 Plugin plugin = pluginManager.getPlugin("nodesc");
742 assertNotNull(plugin);
743 assertEquals("1.0", plugin.getPluginInformation().getVersion());
744 assertEquals("nodesc", plugin.getKey());
745 assertEquals(0, plugin.getModuleDescriptors().size());
746 }
747
748 public void testInstallWithManifestNoDescriptorWithSpringHeader() throws Exception
749 {
750 new PluginJarBuilder("nodesc")
751 .manifest(new ImmutableMap.Builder<String, String>()
752 .put(OsgiPlugin.ATLASSIAN_PLUGIN_KEY, "nodesc")
753 .put(Constants.BUNDLE_VERSION, "1.0")
754 .put("Spring-Context", "*;timeout:=60")
755 .build())
756 .build(pluginsDir);
757
758 initPluginManager();
759
760 assertEquals(1, pluginManager.getEnabledPlugins().size());
761 Plugin plugin = pluginManager.getPlugin("nodesc");
762 assertNotNull(plugin);
763 assertEquals("1.0", plugin.getPluginInformation().getVersion());
764 assertEquals("nodesc", plugin.getKey());
765 assertEquals(0, plugin.getModuleDescriptors().size());
766 }
767
768
769 public void notTestInstallWithComponentBeanNameConflictedWithHostComponent() throws Exception
770 {
771 new PluginJarBuilder("first")
772 .addFormattedResource("atlassian-plugin.xml",
773 "<atlassian-plugin name='Test' key='first' pluginsVersion='2'>",
774 " <plugin-info>",
775 " <version>1.0</version>",
776 " </plugin-info>",
777 " <component key='host_component1' class='first.MyClass' interface='first.MyInterface'/>",
778 "</atlassian-plugin>")
779 .addFormattedJava("com.atlassian.plugin.osgi.SomeInterface",
780 "package com.atlassian.plugin.osgi;",
781 "public interface SomeInterface {}")
782 .addFormattedJava("first.MyClass",
783 "package first;",
784 "import com.atlassian.plugin.osgi.SomeInterface;",
785 "public class MyClass implements SomeInterface{",
786 "}")
787 .build(pluginsDir);
788
789 initPluginManager(new HostComponentProvider()
790 {
791 public void provide(ComponentRegistrar registrar)
792 {
793 registrar.register(SomeInterface.class).forInstance(new SomeInterface(){}).withName("host_component1");
794 }
795 });
796
797
798 assertEquals(0, pluginManager.getEnabledPlugins().size());
799 assertTrue(pluginManager.getPlugins().toArray()[0] instanceof UnloadablePlugin);
800
801
802 assertTrue(pluginManager.getPlugins().toArray(new UnloadablePlugin[1])[0].getErrorText().contains("host_component1"));
803 }
804
805 public void testInstallWithStrangePath() throws Exception
806 {
807 File strangeDir = new File(tmpDir, "20%time");
808 strangeDir.mkdir();
809 File oldTmp = tmpDir;
810 try
811 {
812 tmpDir = strangeDir;
813 cacheDir = new File(tmpDir, "felix-cache");
814 cacheDir.mkdir();
815 pluginsDir = new File(tmpDir, "plugins");
816 pluginsDir.mkdir();
817
818 new PluginJarBuilder("strangePath")
819 .addFormattedResource("atlassian-plugin.xml",
820 "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
821 " <plugin-info>",
822 " <version>1.0</version>",
823 " </plugin-info>",
824 "</atlassian-plugin>")
825 .build(pluginsDir);
826
827 final DefaultModuleDescriptorFactory factory = new DefaultModuleDescriptorFactory(new DefaultHostContainer());
828 factory.addModuleDescriptor("dummy", DummyModuleDescriptor.class);
829 initPluginManager(new HostComponentProvider()
830 {
831 public void provide(final ComponentRegistrar registrar)
832 {
833 }
834 }, factory);
835
836 assertEquals(1, pluginManager.getEnabledPlugins().size());
837 }
838 finally
839 {
840 tmpDir = oldTmp;
841 }
842 }
843
844 public void testInstallWithUnsatisifedDependency() throws Exception
845 {
846 File plugin = new PluginJarBuilder("unsatisifiedDependency")
847 .addFormattedResource("atlassian-plugin.xml",
848 "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
849 " <plugin-info>",
850 " <version>1.0</version>",
851 " </plugin-info>",
852 " <component-import key='foo' interface='java.util.concurrent.Callable' />",
853 "</atlassian-plugin>")
854 .build(pluginsDir);
855
856 long start = System.currentTimeMillis();
857
858 System.setProperty("atlassian.dev.mode", "true");
859 System.setProperty(PluginUtils.ATLASSIAN_PLUGINS_ENABLE_WAIT, "7");
860 try
861 {
862 initPluginManager();
863
864 assertTrue(start + (60 * 1000) > System.currentTimeMillis());
865 }
866 finally
867 {
868
869 System.setProperty("atlassian.dev.mode", "false");
870 System.clearProperty(PluginUtils.ATLASSIAN_PLUGINS_ENABLE_WAIT);
871 }
872 }
873
874 public void testInstallSimplePluginNoSpring() throws Exception
875 {
876 File jar = new PluginJarBuilder("strangePath")
877 .addPluginInformation("no-spring", "foo", "1.0")
878 .build();
879
880 initPluginManager();
881 pluginManager.installPlugin(new JarPluginArtifact(jar));
882
883 assertEquals(1, pluginManager.getEnabledPlugins().size());
884 }
885
886 public void testInstallSimplePluginWithNoManifest() throws Exception
887 {
888 File jar = new PluginJarBuilder("strangePath")
889 .addPluginInformation("no-spring", "foo", "1.0")
890 .buildWithNoManifest();
891
892 initPluginManager();
893 pluginManager.installPlugin(new JarPluginArtifact(jar));
894
895 assertEquals(1, pluginManager.getEnabledPlugins().size());
896 }
897
898 public void testInstallPluginTakesTooLong() throws Exception
899 {
900 System.setProperty(PluginUtils.ATLASSIAN_PLUGINS_ENABLE_WAIT, "3");
901 try
902 {
903 final PluginJarBuilder builder = new PluginJarBuilder("first")
904 .addFormattedResource("atlassian-plugin.xml",
905 "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
906 " <plugin-info>",
907 " <version>1.0</version>",
908 " </plugin-info>",
909 " <component key='svc' class='my.ServiceImpl' public='true'>",
910 " <interface>my.Service</interface>",
911 " </component>",
912 "</atlassian-plugin>")
913 .addFormattedJava("my.Service",
914 "package my;",
915 "public interface Service {",
916 " public Object call() throws Exception;",
917 "}")
918 .addFormattedJava("my.ServiceImpl",
919 "package my;",
920 "public class ServiceImpl implements Service {",
921 "public ServiceImpl(){",
922 "try{",
923 "Thread.sleep(10000);",
924 "}catch(Exception e){}",
925 "}",
926 " public Object call() throws Exception { ",
927 " return 'hi';}",
928 "}");
929 final File jar = builder.build();
930 initPluginManager();
931
932 pluginManager.installPlugin(new JarPluginArtifact(jar));
933
934 assertEquals(0, pluginManager.getEnabledPlugins().size());
935 }
936 finally
937 {
938 System.clearProperty(PluginUtils.ATLASSIAN_PLUGINS_ENABLE_WAIT);
939 }
940 }
941
942 public void testInstallPluginVersion3() throws Exception
943 {
944 initPluginManager();
945
946 final File v3plugin = new PluginJarBuilder("v3-plugin")
947 .addFormattedResource("atlassian-plugin.xml",
948 "<atlassian-plugin name='V3 Plugin' key='v3-plugin' pluginsVersion='3'>",
949 " <plugin-info>",
950 " <version>1.0</version>",
951 " <permissions>",
952 " <permission>execute_java</permission>",
953 " </permissions>",
954 " </plugin-info>",
955 "</atlassian-plugin>")
956 .addFormattedResource("META-INF/MANIFEST.MF",
957 "Bundle-SymbolicName: v3-plugin",
958
959
960 OsgiPlugin.ATLASSIAN_PLUGIN_KEY + ": v3-plugin",
961 "Bundle-Version: 1.0.0",
962 "Manifest-Version: 1.0",
963 "Spring-Context: *;timeout:=60",
964 "")
965 .build();
966
967 pluginManager.installPlugin(new JarPluginArtifact(v3plugin));
968
969 assertEquals(1, pluginManager.getEnabledPlugins().size());
970 assertNotNull(pluginManager.getEnabledPlugin("v3-plugin"));
971 }
972
973 public static class Callable3Aware
974 {
975 private final Callable3 callable;
976
977 public Callable3Aware(Callable3 callable)
978 {
979 this.callable = callable;
980 }
981
982 public String call() throws Exception
983 {
984 return callable.call();
985 }
986 }
987 }