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