1 package com.atlassian.plugin.osgi.factory;
2
3 import com.atlassian.plugin.PluginDependencies;
4 import com.atlassian.plugin.module.ContainerAccessor;
5 import com.google.common.collect.ImmutableList;
6 import org.junit.After;
7 import org.junit.Before;
8 import org.junit.Rule;
9 import org.junit.Test;
10 import org.junit.rules.ExpectedException;
11 import org.mockito.Mockito;
12 import org.osgi.framework.Bundle;
13 import org.osgi.framework.BundleContext;
14 import org.osgi.framework.Constants;
15 import org.osgi.framework.wiring.BundleRevisions;
16 import org.osgi.service.packageadmin.PackageAdmin;
17 import org.springframework.beans.factory.annotation.Autowired;
18 import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
19 import org.springframework.beans.factory.config.BeanDefinition;
20 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
21 import org.springframework.beans.factory.support.DefaultListableBeanFactory;
22 import org.springframework.context.support.GenericApplicationContext;
23
24 import java.util.Dictionary;
25 import java.util.Hashtable;
26
27 import static org.hamcrest.MatcherAssert.assertThat;
28 import static org.hamcrest.Matchers.arrayContaining;
29 import static org.hamcrest.Matchers.empty;
30 import static org.hamcrest.Matchers.is;
31 import static org.hamcrest.Matchers.notNullValue;
32 import static org.hamcrest.Matchers.nullValue;
33 import static org.mockito.Mockito.mock;
34 import static org.mockito.Mockito.verify;
35 import static org.mockito.Mockito.when;
36 import static org.mockito.hamcrest.MockitoHamcrest.argThat;
37
38 public class TestOsgiPluginInstalledHelper {
39 @Rule
40 public final ExpectedException expectedException = ExpectedException.none();
41
42
43
44
45 interface BundleImpl extends Bundle, BundleRevisions {
46 }
47
48 private BundleImpl bundle;
49 private BundleContext bundleContext;
50 private Dictionary<String, String> dict;
51 private PackageAdmin packageAdmin;
52
53 private OsgiPluginInstalledHelper helper;
54
55 @Before
56 public void setUp() {
57 bundle = mock(BundleImpl.class);
58 dict = new Hashtable<>();
59 dict.put(Constants.BUNDLE_DESCRIPTION, "desc");
60 dict.put(Constants.BUNDLE_VERSION, "1.0");
61 when(bundle.getHeaders()).thenReturn(dict);
62 bundleContext = mock(BundleContext.class);
63 when(bundle.getBundleContext()).thenReturn(bundleContext);
64
65 packageAdmin = mock(PackageAdmin.class);
66
67 helper = new OsgiPluginInstalledHelper(bundle, packageAdmin);
68 }
69
70 @After
71 public void tearDown() {
72 bundle = null;
73 packageAdmin = null;
74 helper = null;
75 dict = null;
76 bundleContext = null;
77 }
78
79 @Test
80 public void canSetContainerAccessorToSpringGenericApplicationContext() {
81 final DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
82 final BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(ChildBean.class).getBeanDefinition();
83 beanFactory.registerBeanDefinition("child", beanDefinition);
84 final AutowiredAnnotationBeanPostProcessor postProcessor = new AutowiredAnnotationBeanPostProcessor();
85 postProcessor.setBeanFactory(beanFactory);
86
87 when(bundle.getSymbolicName()).thenReturn("foo");
88 GenericApplicationContext applicationContext = new GenericApplicationContext(beanFactory);
89 applicationContext.getBeanFactory().addBeanPostProcessor(postProcessor);
90 applicationContext.refresh();
91 helper.setPluginContainer(applicationContext);
92 final SetterInjectedBean bean = new SetterInjectedBean();
93 helper.getContainerAccessor().injectBean(bean);
94 assertThat(bean.getChild(), notNullValue());
95 }
96
97 @Test
98 public void canSetContainerAccessorToCustomContainerAccessor() {
99 final ContainerAccessor containerAccessor = mock(ContainerAccessor.class);
100 final String expectedBean = "foo";
101 when(containerAccessor.createBean(String.class)).thenReturn(expectedBean);
102
103 helper.setPluginContainer(containerAccessor);
104
105 final String actualBean = helper.getContainerAccessor().createBean(String.class);
106 assertThat(actualBean, is(expectedBean));
107 }
108
109 @Test
110 public void getRequiredContainerAccessorReturnsContainerAccessor() {
111 final ContainerAccessor containerAccessor = mock(ContainerAccessor.class);
112 helper.setPluginContainer(containerAccessor);
113
114 assertThat(helper.getRequiredContainerAccessor(), is(helper.getContainerAccessor()));
115 }
116
117 @Test
118 public void beforeSetGetContainerAccessorIsNull() {
119 assertThat(helper.getContainerAccessor(), nullValue());
120 }
121
122 @Test
123 public void beforeSetGetRequiredContainerAccessorThrows() {
124 final String bundleSymbolicName = "test-bundle-symbolicName";
125 when(bundle.getSymbolicName()).thenReturn(bundleSymbolicName);
126 expectedException.expect(IllegalStateException.class);
127 expectedException.expectMessage(bundleSymbolicName);
128 helper.getRequiredContainerAccessor();
129 }
130
131 @Test
132 public void disableWithoutEnablingDoesNotThrow() {
133 helper.onDisable();
134 }
135
136 @Test
137 public void installedBundlesAreResolvedByGetDependencies() {
138 Mockito.when(bundle.getState()).thenReturn(Bundle.INSTALLED);
139 Mockito.when(bundle.getRevisions()).thenReturn(ImmutableList.of());
140 when(packageAdmin.resolveBundles(argThat(arrayContaining(bundle)))).thenReturn(true);
141 helper.getDependencies();
142 verify(packageAdmin).resolveBundles(new Bundle[]{bundle});
143 }
144
145 @Test
146 public void getDependenciesReturnsEmptySetIfBundleCannotBeResolved() {
147 final String symbolicName = "test-bundle-sybolicName";
148 when(bundle.getSymbolicName()).thenReturn(symbolicName);
149 when(bundle.getState()).thenReturn(Bundle.INSTALLED);
150 when(packageAdmin.resolveBundles(argThat(arrayContaining(bundle)))).thenReturn(false);
151 final PluginDependencies requiredPlugins = helper.getDependencies();
152 verify(packageAdmin).resolveBundles(new Bundle[]{bundle});
153 assertThat(requiredPlugins.getAll(), empty());
154 }
155
156 public static class ChildBean {
157 }
158
159 public static class SetterInjectedBean {
160 private ChildBean child;
161
162 public ChildBean getChild() {
163 return child;
164 }
165
166 @Autowired
167 public void setChild(final ChildBean child) {
168 this.child = child;
169 }
170 }
171 }