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