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