PageRenderTime 42ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/atlassian-plugins-osgi/src/test/java/it/com/atlassian/plugin/osgi/TestPluginDependencies.java

https://bitbucket.org/atlassian/atlassian-plugins
Java | 693 lines | 631 code | 62 blank | 0 comment | 3 complexity | d99f2ecfbae182feb3cc933e2452258d MD5 | raw file
  1. package it.com.atlassian.plugin.osgi;
  2. import com.atlassian.plugin.DefaultModuleDescriptorFactory;
  3. import com.atlassian.plugin.JarPluginArtifact;
  4. import com.atlassian.plugin.Plugin;
  5. import com.atlassian.plugin.hostcontainer.DefaultHostContainer;
  6. import com.atlassian.plugin.osgi.AbstractWaitCondition;
  7. import com.atlassian.plugin.osgi.AnotherInterface;
  8. import com.atlassian.plugin.osgi.Callable2;
  9. import com.atlassian.plugin.osgi.DummyModuleDescriptor;
  10. import com.atlassian.plugin.osgi.EventTrackingModuleDescriptor;
  11. import com.atlassian.plugin.osgi.PluginInContainerTestBase;
  12. import com.atlassian.plugin.osgi.SomeInterface;
  13. import com.atlassian.plugin.osgi.container.felix.FelixOsgiContainerManager;
  14. import com.atlassian.plugin.osgi.factory.OsgiPlugin;
  15. import com.atlassian.plugin.osgi.hostcomponents.ComponentRegistrar;
  16. import com.atlassian.plugin.osgi.hostcomponents.HostComponentProvider;
  17. import com.atlassian.plugin.test.PluginJarBuilder;
  18. import com.atlassian.plugin.util.WaitUntil;
  19. import org.junit.Test;
  20. import org.osgi.util.tracker.ServiceTracker;
  21. import java.io.File;
  22. import java.util.concurrent.Callable;
  23. import static org.hamcrest.Matchers.contains;
  24. import static org.hamcrest.Matchers.empty;
  25. import static org.junit.Assert.assertEquals;
  26. import static org.junit.Assert.assertThat;
  27. import static org.junit.Assert.assertTrue;
  28. public class TestPluginDependencies extends PluginInContainerTestBase {
  29. @Test
  30. public void testPluginDependentOnPackageImport() throws Exception {
  31. PluginJarBuilder parentBuilder = new PluginJarBuilder("parent")
  32. .addFormattedResource("atlassian-plugin.xml",
  33. "<atlassian-plugin name='Test' key='parent' pluginsVersion='2'>",
  34. " <plugin-info>",
  35. " <version>1.0</version>",
  36. " <bundle-instructions>",
  37. " <Import-Package>foo</Import-Package>",
  38. " <Export-Package>foo</Export-Package>",
  39. " </bundle-instructions>",
  40. " </plugin-info>",
  41. "</atlassian-plugin>")
  42. .addFormattedJava("foo.Bar",
  43. "package foo;",
  44. "public interface Bar {}");
  45. new PluginJarBuilder("child", parentBuilder.getClassLoader())
  46. .addFormattedResource("atlassian-plugin.xml",
  47. "<atlassian-plugin name='Test' key='child' pluginsVersion='2'>",
  48. " <plugin-info>",
  49. " <version>1.0</version>",
  50. " </plugin-info>",
  51. "</atlassian-plugin>")
  52. .addFormattedJava("second.MyImpl",
  53. "package second;",
  54. "public class MyImpl {",
  55. " public MyImpl(foo.Bar config) {",
  56. " }",
  57. "}")
  58. .build(pluginsDir);
  59. parentBuilder.build(pluginsDir);
  60. initPluginManager();
  61. assertEquals(2, pluginAccessor.getEnabledPlugins().size());
  62. assertThat(pluginAccessor.getPlugin("child").getDependencies().getOptional(), contains("parent"));
  63. assertThat(pluginAccessor.getPlugin("child").getDependencies().getMandatory(), empty());
  64. }
  65. @Test
  66. public void testPluginDependentOnDynamicPackageImport() throws Exception {
  67. PluginJarBuilder parentBuilder = new PluginJarBuilder("parent")
  68. .addFormattedResource("atlassian-plugin.xml",
  69. "<atlassian-plugin name='Test' key='parent' pluginsVersion='2'>",
  70. " <plugin-info>",
  71. " <version>1.0</version>",
  72. " <bundle-instructions>",
  73. " <Import-Package>foo</Import-Package>",
  74. " <Export-Package>foo</Export-Package>",
  75. " </bundle-instructions>",
  76. " </plugin-info>",
  77. "</atlassian-plugin>")
  78. .addFormattedJava("foo.Bar",
  79. "package foo;",
  80. "public interface Bar {}");
  81. new PluginJarBuilder("child", parentBuilder.getClassLoader())
  82. .addFormattedResource("atlassian-plugin.xml",
  83. "<atlassian-plugin name='Test' key='child' pluginsVersion='2'>",
  84. " <plugin-info>",
  85. " <version>1.0</version>",
  86. " <bundle-instructions>",
  87. " <Import-Package />",
  88. " <DynamicImport-Package>foo</DynamicImport-Package>",
  89. " </bundle-instructions>",
  90. " </plugin-info>",
  91. "</atlassian-plugin>")
  92. .addFormattedJava("second.MyImpl",
  93. "package second;",
  94. "public class MyImpl {",
  95. " public MyImpl(foo.Bar config) {",
  96. " }",
  97. "}")
  98. .build(pluginsDir);
  99. parentBuilder.build(pluginsDir);
  100. initPluginManager();
  101. assertEquals(2, pluginAccessor.getEnabledPlugins().size());
  102. Plugin childPlugin = pluginAccessor.getPlugin("child");
  103. childPlugin.loadClass("foo.Bar", null);
  104. assertThat(pluginAccessor.getPlugin("child").getDependencies().getOptional(), contains("parent"));
  105. assertThat(pluginAccessor.getPlugin("child").getDependencies().getMandatory(), empty());
  106. }
  107. @Test
  108. public void testUninstallingPluginDependentOnPackageImport() throws Exception {
  109. PluginJarBuilder parentBuilder = new PluginJarBuilder("parent")
  110. .addFormattedResource("atlassian-plugin.xml",
  111. "<atlassian-plugin name='Test' key='parent' pluginsVersion='2'>",
  112. " <plugin-info>",
  113. " <version>1.0</version>",
  114. " <bundle-instructions>",
  115. " <Import-Package>foo</Import-Package>",
  116. " <Export-Package>foo</Export-Package>",
  117. " </bundle-instructions>",
  118. " </plugin-info>",
  119. "</atlassian-plugin>")
  120. .addFormattedJava("foo.Bar",
  121. "package foo;",
  122. "public interface Bar {}");
  123. new PluginJarBuilder("child", parentBuilder.getClassLoader())
  124. .addFormattedResource("atlassian-plugin.xml",
  125. "<atlassian-plugin name='Test' key='child' pluginsVersion='2'>",
  126. " <plugin-info>",
  127. " <version>1.0</version>",
  128. " </plugin-info>",
  129. "</atlassian-plugin>")
  130. .addFormattedJava("second.MyImpl",
  131. "package second;",
  132. "public class MyImpl {",
  133. " public MyImpl(foo.Bar config) {",
  134. " }",
  135. "}")
  136. .build(pluginsDir);
  137. parentBuilder.build(pluginsDir);
  138. initPluginManager();
  139. assertEquals(2, pluginAccessor.getEnabledPlugins().size());
  140. pluginController.uninstall(pluginAccessor.getPlugin("parent"));
  141. assertEquals(1, pluginAccessor.getEnabledPlugins().size());
  142. }
  143. @Test
  144. public void testUpgradeWithNewComponentImplementation() throws Exception {
  145. final DefaultModuleDescriptorFactory factory = new DefaultModuleDescriptorFactory(new DefaultHostContainer());
  146. factory.addModuleDescriptor("dummy", DummyModuleDescriptor.class);
  147. initPluginManager(new HostComponentProvider() {
  148. public void provide(final ComponentRegistrar registrar) {
  149. registrar.register(SomeInterface.class).forInstance(new SomeInterface() {
  150. });
  151. registrar.register(AnotherInterface.class).forInstance(new AnotherInterface() {
  152. });
  153. }
  154. }, factory);
  155. final File pluginJar = new PluginJarBuilder("first")
  156. .addFormattedResource("atlassian-plugin.xml",
  157. "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
  158. " <plugin-info>",
  159. " <version>1.0</version>",
  160. " </plugin-info>",
  161. " <component key='svc' class='my.ServiceImpl' public='true'>",
  162. " <interface>java.util.concurrent.Callable</interface>",
  163. " </component>",
  164. "</atlassian-plugin>")
  165. .addFormattedJava("my.ServiceImpl",
  166. "package my;",
  167. "import java.util.concurrent.Callable;",
  168. "public class ServiceImpl implements Callable {",
  169. " public Object call() throws Exception { return 'hi';}",
  170. "}")
  171. .build();
  172. final File pluginJar2 = new PluginJarBuilder("second")
  173. .addFormattedResource("atlassian-plugin.xml",
  174. "<atlassian-plugin name='Test 2' key='test2.plugin' pluginsVersion='2'>",
  175. " <plugin-info>",
  176. " <version>1.0</version>",
  177. " </plugin-info>",
  178. " <component-import key='svc' interface='java.util.concurrent.Callable' />",
  179. " <component key='del' class='my2.ServiceDelegate' public='true'>",
  180. " <interface>com.atlassian.plugin.osgi.Callable2</interface>",
  181. " </component>",
  182. "</atlassian-plugin>")
  183. .addFormattedJava("my2.ServiceDelegate",
  184. "package my2;",
  185. "import com.atlassian.plugin.osgi.Callable2;",
  186. "import java.util.concurrent.Callable;",
  187. "public class ServiceDelegate implements Callable2 {",
  188. " private final Callable delegate;",
  189. " public ServiceDelegate(Callable foo) { this.delegate = foo;}",
  190. " public String call() throws Exception { return (String)delegate.call();}",
  191. "}")
  192. .build();
  193. pluginController.installPlugins(new JarPluginArtifact(pluginJar));
  194. assertEquals(1, pluginAccessor.getEnabledPlugins().size());
  195. pluginController.installPlugins(new JarPluginArtifact(pluginJar2));
  196. final ServiceTracker tracker = osgiContainerManager.getServiceTracker("com.atlassian.plugin.osgi.Callable2");
  197. for (final Object svc : tracker.getServices()) {
  198. final Callable2 callable = (Callable2) svc;
  199. assertEquals("hi", callable.call());
  200. }
  201. assertEquals(2, pluginAccessor.getEnabledPlugins().size());
  202. final File updatedJar = new PluginJarBuilder("first")
  203. .addFormattedResource("atlassian-plugin.xml",
  204. "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
  205. " <plugin-info>",
  206. " <version>1.0</version>",
  207. " </plugin-info>",
  208. " <component key='svc' class='my.ServiceImpl' public='true'>",
  209. " <interface>java.util.concurrent.Callable</interface>",
  210. " </component>",
  211. "</atlassian-plugin>")
  212. .addFormattedJava("my.ServiceImpl",
  213. "package my;",
  214. "import java.util.concurrent.Callable;",
  215. "public class ServiceImpl implements Callable {",
  216. " public Object call() throws Exception { return 'bob';}",
  217. "}")
  218. .build();
  219. pluginController.installPlugins(new JarPluginArtifact(updatedJar));
  220. WaitUntil.invoke(new AbstractWaitCondition() {
  221. public boolean isFinished() {
  222. return pluginAccessor.getEnabledPlugins().size() == 2;
  223. }
  224. });
  225. assertEquals(2, pluginAccessor.getEnabledPlugins().size());
  226. for (final Object svc : tracker.getServices()) {
  227. final Callable2 callable = (Callable2) svc;
  228. assertEquals("bob", callable.call());
  229. }
  230. }
  231. @Test
  232. public void testUpgradeWithNewComponentImplementationWithInterfaceInPlugin() throws Exception {
  233. final DefaultModuleDescriptorFactory factory = new DefaultModuleDescriptorFactory(new DefaultHostContainer());
  234. factory.addModuleDescriptor("dummy", DummyModuleDescriptor.class);
  235. initPluginManager(new HostComponentProvider() {
  236. public void provide(final ComponentRegistrar registrar) {
  237. registrar.register(SomeInterface.class).forInstance(new SomeInterface() {
  238. });
  239. registrar.register(AnotherInterface.class).forInstance(new AnotherInterface() {
  240. });
  241. }
  242. }, factory);
  243. final PluginJarBuilder builder1 = new PluginJarBuilder("first")
  244. .addFormattedResource("atlassian-plugin.xml",
  245. "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
  246. " <plugin-info>",
  247. " <version>1.0</version>",
  248. " </plugin-info>",
  249. " <component key='svc' class='my.ServiceImpl' public='true'>",
  250. " <interface>my.Service</interface>",
  251. " </component>",
  252. "</atlassian-plugin>")
  253. .addFormattedJava("my.Service",
  254. "package my;",
  255. "public interface Service {",
  256. " public Object call() throws Exception;",
  257. "}")
  258. .addFormattedJava("my.ServiceImpl",
  259. "package my;",
  260. "public class ServiceImpl implements Service {",
  261. " public Object call() throws Exception { return 'hi';}",
  262. "}");
  263. final File pluginJar = builder1.build();
  264. final File pluginJar2 = new PluginJarBuilder("second", builder1.getClassLoader())
  265. .addFormattedResource("atlassian-plugin.xml",
  266. "<atlassian-plugin name='Test 2' key='test2.plugin' pluginsVersion='2'>",
  267. " <plugin-info>",
  268. " <version>1.0</version>",
  269. " </plugin-info>",
  270. " <component-import key='svc' interface='my.Service' />",
  271. " <component key='del' class='my2.ServiceDelegate' public='true'>",
  272. " <interface>java.util.concurrent.Callable</interface>",
  273. " </component>",
  274. "</atlassian-plugin>")
  275. .addFormattedJava("my2.ServiceDelegate",
  276. "package my2;",
  277. "import my.Service;",
  278. "import java.util.concurrent.Callable;",
  279. "public class ServiceDelegate implements Callable {",
  280. " private final Service delegate;",
  281. " public ServiceDelegate(Service foo) { this.delegate = foo;}",
  282. " public Object call() throws Exception { return delegate.call();}",
  283. "}")
  284. .build();
  285. pluginController.installPlugins(new JarPluginArtifact(pluginJar));
  286. assertEquals(1, pluginAccessor.getEnabledPlugins().size());
  287. final ServiceTracker tracker = osgiContainerManager.getServiceTracker(Callable.class.getName());
  288. final ServiceTracker svcTracker = osgiContainerManager.getServiceTracker("my.Service");
  289. pluginController.installPlugins(new JarPluginArtifact(pluginJar2));
  290. assertEquals("hi", svcTracker.getService().getClass().getMethod("call").invoke(svcTracker.getService()));
  291. assertEquals("hi", ((Callable) tracker.getService()).call());
  292. assertEquals(2, pluginAccessor.getEnabledPlugins().size());
  293. final File updatedJar = new PluginJarBuilder("first")
  294. .addFormattedResource("atlassian-plugin.xml",
  295. "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
  296. " <plugin-info>",
  297. " <version>1.0</version>",
  298. " </plugin-info>",
  299. " <component key='svc' class='my.Service2Impl' public='true'>",
  300. " <interface>my.Service</interface>",
  301. " </component>",
  302. "</atlassian-plugin>")
  303. .addFormattedJava("my.Service",
  304. "package my;",
  305. "public interface Service {",
  306. " public Object call() throws Exception;",
  307. "}")
  308. .addFormattedJava("my.Service2Impl",
  309. "package my;",
  310. "public class Service2Impl implements Service {",
  311. " public Object call() throws Exception {return 'bob';}",
  312. "}")
  313. .build();
  314. pluginController.installPlugins(new JarPluginArtifact(updatedJar));
  315. assertEquals("bob", svcTracker.getService().getClass().getMethod("call").invoke(svcTracker.getService()));
  316. tracker.waitForService(5000);
  317. assertEquals("bob", ((Callable) tracker.getService()).call());
  318. }
  319. @Test
  320. public void testUpgradeWithRefreshingAffectingOtherPlugins() throws Exception {
  321. final DefaultModuleDescriptorFactory factory = new DefaultModuleDescriptorFactory(new DefaultHostContainer());
  322. initPluginManager(new HostComponentProvider() {
  323. public void provide(final ComponentRegistrar registrar) {
  324. }
  325. }, factory);
  326. PluginJarBuilder pluginBuilder = new PluginJarBuilder("first")
  327. .addFormattedResource("atlassian-plugin.xml",
  328. "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
  329. " <plugin-info>",
  330. " <version>1.0</version>",
  331. " <bundle-instructions><Export-Package>my</Export-Package></bundle-instructions>",
  332. " </plugin-info>",
  333. " <component key='svc' class='my.ServiceImpl' public='true'>",
  334. " <interface>java.util.concurrent.Callable</interface>",
  335. " </component>",
  336. "</atlassian-plugin>")
  337. .addFormattedJava("my.ServiceImpl",
  338. "package my;",
  339. "import java.util.concurrent.Callable;",
  340. "public class ServiceImpl implements Callable {",
  341. " public Object call() throws Exception { return 'hi';}",
  342. "}");
  343. final File pluginJar = pluginBuilder.build();
  344. final File pluginJar2 = new PluginJarBuilder("second", pluginBuilder.getClassLoader())
  345. .addFormattedResource("atlassian-plugin.xml",
  346. "<atlassian-plugin name='Test 2' key='test2.plugin' pluginsVersion='2'>",
  347. " <plugin-info>",
  348. " <version>1.0</version>",
  349. " <bundle-instructions><Import-Package>my</Import-Package></bundle-instructions>",
  350. " </plugin-info>",
  351. " <component-import key='svc' interface='java.util.concurrent.Callable' />",
  352. " <component-import key='othersvc' interface='com.atlassian.plugin.osgi.Callable3' />",
  353. " <component key='del' class='my2.ServiceDelegate' public='true'>",
  354. " <interface>com.atlassian.plugin.osgi.Callable2</interface>",
  355. " </component>",
  356. "</atlassian-plugin>")
  357. .addFormattedJava("my2.ServiceDelegate",
  358. "package my2;",
  359. "import com.atlassian.plugin.osgi.Callable2;",
  360. "import com.atlassian.plugin.osgi.Callable3;",
  361. "import java.util.concurrent.Callable;",
  362. "public class ServiceDelegate implements Callable2 {",
  363. " private final Callable delegate;",
  364. " private final Callable3 othersvc;",
  365. " public ServiceDelegate(Callable foo,Callable3 othersvc) {",
  366. " this.delegate = foo;",
  367. " this.othersvc = othersvc;",
  368. " }",
  369. " public String call() throws Exception { return othersvc.call() + (String)delegate.call();}",
  370. "}")
  371. .build();
  372. final File otherSvcJar = new PluginJarBuilder("otherSvc")
  373. .addFormattedResource("atlassian-plugin.xml",
  374. "<atlassian-plugin name='Test' key='test.othersvc.plugin' pluginsVersion='2'>",
  375. " <plugin-info>",
  376. " <version>1.0</version>",
  377. " </plugin-info>",
  378. " <component key='othersvc' class='othersvc.ServiceImpl' public='true'>",
  379. " <interface>com.atlassian.plugin.osgi.Callable3</interface>",
  380. " </component>",
  381. "</atlassian-plugin>")
  382. .addFormattedJava("othersvc.ServiceImpl",
  383. "package othersvc;",
  384. "import com.atlassian.plugin.osgi.Callable3;",
  385. "public class ServiceImpl implements Callable3 {",
  386. " public String call() throws Exception { return 'hi';}",
  387. "}")
  388. .build();
  389. pluginController.installPlugins(new JarPluginArtifact(pluginJar));
  390. assertEquals(1, pluginAccessor.getEnabledPlugins().size());
  391. pluginController.installPlugins(new JarPluginArtifact(otherSvcJar));
  392. pluginController.installPlugins(new JarPluginArtifact(pluginJar2));
  393. assertEquals("hi", ((OsgiPlugin) pluginAccessor.getPlugin("test2.plugin")).getContainerAccessor().createBean(TestPluginInstall.Callable3Aware.class).call());
  394. assertEquals(3, pluginAccessor.getEnabledPlugins().size());
  395. final File updatedJar = new PluginJarBuilder("first")
  396. .addFormattedResource("atlassian-plugin.xml",
  397. "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
  398. " <plugin-info>",
  399. " <version>1.0</version>",
  400. " <bundle-instructions><Export-Package>my</Export-Package></bundle-instructions>",
  401. " </plugin-info>",
  402. " <component key='svc' class='my.ServiceImpl' public='true'>",
  403. " <interface>java.util.concurrent.Callable</interface>",
  404. " </component>",
  405. "</atlassian-plugin>")
  406. .addFormattedJava("my.ServiceImpl",
  407. "package my;",
  408. "import java.util.concurrent.Callable;",
  409. "public class ServiceImpl implements Callable {",
  410. " public Object call() throws Exception { return 'bob';}",
  411. "}")
  412. .build();
  413. pluginController.installPlugins(new JarPluginArtifact(updatedJar));
  414. assertEquals(3, pluginAccessor.getEnabledPlugins().size());
  415. assertEquals("hi", ((OsgiPlugin) pluginAccessor.getPlugin("test2.plugin")).getContainerAccessor().createBean(TestPluginInstall.Callable3Aware.class).call());
  416. }
  417. @Test
  418. public void testUpgradeOfBundledPluginWithRefreshingAffectingOtherPluginsCheckingModuleEvents() throws Exception {
  419. DefaultModuleDescriptorFactory factory = new DefaultModuleDescriptorFactory(new DefaultHostContainer());
  420. factory.addModuleDescriptor("dummy", EventTrackingModuleDescriptor.class);
  421. PluginJarBuilder hostBuilder = new PluginJarBuilder("first")
  422. .addFormattedResource("atlassian-plugin.xml",
  423. "<atlassian-plugin name='Test' key='host' pluginsVersion='2'>",
  424. " <plugin-info>",
  425. " <version>1.0</version>",
  426. " <bundle-instructions><Export-Package>my</Export-Package></bundle-instructions>",
  427. " </plugin-info>",
  428. " <dummy key='foo'/>",
  429. "</atlassian-plugin>")
  430. .addFormattedJava("my.Serviceable",
  431. "package my;",
  432. "public interface Serviceable {}");
  433. final File hostJar = hostBuilder.build();
  434. final File clientJar = new PluginJarBuilder("second", hostBuilder.getClassLoader())
  435. .addFormattedResource("atlassian-plugin.xml",
  436. "<atlassian-plugin name='Test 2' key='client' pluginsVersion='2'>",
  437. " <plugin-info>",
  438. " <version>1.0</version>",
  439. " </plugin-info>",
  440. " <dummy key='foo'/>",
  441. "</atlassian-plugin>")
  442. .addFormattedJava("my2.Service",
  443. "package my2;",
  444. "public class Service implements my.Serviceable {}")
  445. .build();
  446. initBundlingPluginManager(factory, hostJar);
  447. assertEquals(1, pluginAccessor.getEnabledPlugins().size());
  448. pluginController.installPlugins(new JarPluginArtifact(clientJar));
  449. EventTrackingModuleDescriptor hostModule = (EventTrackingModuleDescriptor) pluginAccessor.getPlugin("host").getModuleDescriptor("foo");
  450. assertEquals(1, hostModule.getEnabledCount());
  451. assertEquals(0, hostModule.getDisabledCount());
  452. EventTrackingModuleDescriptor clientModule = (EventTrackingModuleDescriptor) pluginAccessor.getPlugin("client").getModuleDescriptor("foo");
  453. assertEquals(1, clientModule.getEnabledCount());
  454. assertEquals(0, clientModule.getDisabledCount());
  455. pluginController.installPlugins(new JarPluginArtifact(hostJar));
  456. hostModule = (EventTrackingModuleDescriptor) pluginAccessor.getPlugin("host").getModuleDescriptor("foo");
  457. assertEquals(1, hostModule.getEnabledCount());
  458. assertEquals(0, hostModule.getDisabledCount());
  459. clientModule = (EventTrackingModuleDescriptor) pluginAccessor.getPlugin("client").getModuleDescriptor("foo");
  460. assertEquals(1, clientModule.getDisabledCount());
  461. assertEquals(2, clientModule.getEnabledCount());
  462. }
  463. @Test
  464. public void testUpgradeWithRefreshingAffectingOtherPluginsWithClassLoadingOnShutdown() throws Exception {
  465. final DefaultModuleDescriptorFactory factory = new DefaultModuleDescriptorFactory(new DefaultHostContainer());
  466. initPluginManager(new HostComponentProvider() {
  467. public void provide(final ComponentRegistrar registrar) {
  468. }
  469. }, factory);
  470. PluginJarBuilder pluginBuilder = new PluginJarBuilder("first")
  471. .addFormattedResource("atlassian-plugin.xml",
  472. "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
  473. " <plugin-info>",
  474. " <version>1.0</version>",
  475. " <bundle-instructions><Export-Package>my</Export-Package></bundle-instructions>",
  476. " </plugin-info>",
  477. " <component key='svc' class='my.ServiceImpl' public='true'>",
  478. " <interface>java.util.concurrent.Callable</interface>",
  479. " </component>",
  480. "</atlassian-plugin>")
  481. .addFormattedJava("my.ServiceImpl",
  482. "package my;",
  483. "import java.util.concurrent.Callable;",
  484. "public class ServiceImpl implements Callable {",
  485. " public Object call() throws Exception { return 'hi';}",
  486. "}");
  487. final File pluginJar = pluginBuilder.build();
  488. final File pluginJar2 = new PluginJarBuilder("second", pluginBuilder.getClassLoader())
  489. .addFormattedResource("atlassian-plugin.xml",
  490. "<atlassian-plugin name='Test 2' key='test2.plugin' pluginsVersion='2'>",
  491. " <plugin-info>",
  492. " <version>1.0</version>",
  493. " <bundle-instructions><Import-Package>my</Import-Package>",
  494. " <DynamicImport-Package>foo</DynamicImport-Package></bundle-instructions>",
  495. " </plugin-info>",
  496. " <component-import key='svc' interface='java.util.concurrent.Callable' />",
  497. " <component-import key='othersvc' interface='com.atlassian.plugin.osgi.Callable3' />",
  498. " <component key='del' class='my2.ServiceDelegate' public='true'>",
  499. " <interface>com.atlassian.plugin.osgi.Callable2</interface>",
  500. " </component>",
  501. "</atlassian-plugin>")
  502. .addFormattedJava("my2.ServiceDelegate",
  503. "package my2;",
  504. "import com.atlassian.plugin.osgi.Callable2;",
  505. "import com.atlassian.plugin.osgi.Callable3;",
  506. "import java.util.concurrent.Callable;",
  507. "public class ServiceDelegate implements Callable2, org.springframework.beans.factory.DisposableBean {",
  508. " private final Callable delegate;",
  509. " private final Callable3 othersvc;",
  510. " public ServiceDelegate(Callable foo,Callable3 othersvc) {",
  511. " this.delegate = foo;",
  512. " this.othersvc = othersvc;",
  513. " }",
  514. " public void destroy() {",
  515. " try {",
  516. " getClass().getClassLoader().loadClass('foo.bar');",
  517. " } catch (ClassNotFoundException ex) {}",
  518. " }",
  519. " public String call() throws Exception { return othersvc.call() + (String)delegate.call();}",
  520. "}")
  521. .build();
  522. final File otherSvcJar = new PluginJarBuilder("otherSvc")
  523. .addFormattedResource("atlassian-plugin.xml",
  524. "<atlassian-plugin name='Test' key='test.othersvc.plugin' pluginsVersion='2'>",
  525. " <plugin-info>",
  526. " <version>1.0</version>",
  527. " </plugin-info>",
  528. " <component key='othersvc' class='othersvc.ServiceImpl' public='true'>",
  529. " <interface>com.atlassian.plugin.osgi.Callable3</interface>",
  530. " </component>",
  531. "</atlassian-plugin>")
  532. .addFormattedJava("othersvc.ServiceImpl",
  533. "package othersvc;",
  534. "import com.atlassian.plugin.osgi.Callable3;",
  535. "public class ServiceImpl implements Callable3 {",
  536. " public String call() throws Exception { return 'hi';}",
  537. "}")
  538. .build();
  539. pluginController.installPlugins(new JarPluginArtifact(pluginJar));
  540. assertEquals(1, pluginAccessor.getEnabledPlugins().size());
  541. pluginController.installPlugins(new JarPluginArtifact(otherSvcJar));
  542. pluginController.installPlugins(new JarPluginArtifact(pluginJar2));
  543. assertEquals("hi", ((OsgiPlugin) pluginAccessor.getPlugin("test2.plugin")).getContainerAccessor().createBean(TestPluginInstall.Callable3Aware.class).call());
  544. assertEquals(3, pluginAccessor.getEnabledPlugins().size());
  545. final File updatedJar = new PluginJarBuilder("first")
  546. .addFormattedResource("atlassian-plugin.xml",
  547. "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
  548. " <plugin-info>",
  549. " <version>1.0</version>",
  550. " <bundle-instructions><Export-Package>my</Export-Package></bundle-instructions>",
  551. " </plugin-info>",
  552. " <component key='svc' class='my.ServiceImpl' public='true'>",
  553. " <interface>java.util.concurrent.Callable</interface>",
  554. " </component>",
  555. "</atlassian-plugin>")
  556. .addFormattedJava("my.ServiceImpl",
  557. "package my;",
  558. "import java.util.concurrent.Callable;",
  559. "public class ServiceImpl implements Callable {",
  560. " public Object call() throws Exception { return 'bob';}",
  561. "}")
  562. .build();
  563. long start = System.currentTimeMillis();
  564. pluginController.installPlugins(new JarPluginArtifact(updatedJar));
  565. long timeWaitingForRefresh = System.currentTimeMillis() - start;
  566. assertTrue("Refresh seemed to have timed out, which is bad", timeWaitingForRefresh < FelixOsgiContainerManager.REFRESH_TIMEOUT * 1000);
  567. assertEquals(3, pluginAccessor.getEnabledPlugins().size());
  568. assertEquals("hi", ((OsgiPlugin) pluginAccessor.getPlugin("test2.plugin")).getContainerAccessor().createBean(TestPluginInstall.Callable3Aware.class).call());
  569. }
  570. @Test
  571. public void testUninstallWithShutdownAffectingOtherPluginsWithClassLoadingOnShutdown() throws Exception {
  572. final DefaultModuleDescriptorFactory factory = new DefaultModuleDescriptorFactory(new DefaultHostContainer());
  573. initPluginManager(new HostComponentProvider() {
  574. public void provide(final ComponentRegistrar registrar) {
  575. }
  576. }, factory);
  577. PluginJarBuilder pluginBuilder = new PluginJarBuilder("first")
  578. .addFormattedResource("atlassian-plugin.xml",
  579. "<atlassian-plugin name='Test' key='test.plugin' pluginsVersion='2'>",
  580. " <plugin-info>",
  581. " <version>1.0</version>",
  582. " <bundle-instructions><Export-Package>my</Export-Package></bundle-instructions>",
  583. " </plugin-info>",
  584. " <component key='svc' class='my.ServiceImpl' public='true'>",
  585. " <interface>java.util.concurrent.Callable</interface>",
  586. " </component>",
  587. "</atlassian-plugin>")
  588. .addFormattedJava("my.ServiceImpl",
  589. "package my;",
  590. "import java.util.concurrent.Callable;",
  591. "public class ServiceImpl implements Callable {",
  592. " public Object call() throws Exception { return 'hi';}",
  593. "}");
  594. final File pluginJar = pluginBuilder.build();
  595. final File pluginJar2 = new PluginJarBuilder("second", pluginBuilder.getClassLoader())
  596. .addFormattedResource("atlassian-plugin.xml",
  597. "<atlassian-plugin name='Test 2' key='test2.plugin' pluginsVersion='2'>",
  598. " <plugin-info>",
  599. " <version>1.0</version>",
  600. " <bundle-instructions><Import-Package>my</Import-Package>",
  601. " <DynamicImport-Package>foo</DynamicImport-Package></bundle-instructions>",
  602. " </plugin-info>",
  603. " <component-import key='svc' interface='java.util.concurrent.Callable' />",
  604. " <component key='del' class='my2.Consumer'/>",
  605. "</atlassian-plugin>")
  606. .addFormattedJava("my2.Consumer",
  607. "package my2;",
  608. "import java.util.concurrent.Callable;",
  609. "public class Consumer implements org.springframework.beans.factory.DisposableBean {",
  610. " private final Callable delegate;",
  611. " public Consumer(Callable foo) {",
  612. " this.delegate = foo;",
  613. " }",
  614. " public void destroy() {",
  615. " try {",
  616. " getClass().getClassLoader().loadClass('foo.bar');",
  617. " } catch (ClassNotFoundException ex) {}",
  618. " }",
  619. "}")
  620. .build();
  621. pluginController.installPlugins(new JarPluginArtifact(pluginJar));
  622. assertEquals(1, pluginAccessor.getEnabledPlugins().size());
  623. pluginController.installPlugins(new JarPluginArtifact(pluginJar2));
  624. assertEquals(2, pluginAccessor.getEnabledPlugins().size());
  625. long start = System.currentTimeMillis();
  626. pluginController.uninstall(pluginAccessor.getPlugin("test.plugin"));
  627. long timeWaitingForRefresh = System.currentTimeMillis() - start;
  628. assertTrue("Refresh seemed to have timed out, which is bad", timeWaitingForRefresh < FelixOsgiContainerManager.REFRESH_TIMEOUT * 1000);
  629. assertEquals(0, pluginAccessor.getEnabledPlugins().size());
  630. }
  631. }