View Javadoc
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       * Similar to Felix's (private) org.apache.felix.framework.BundleImpl
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         // We don't require the helper return our ContainerAccessor, we require that our accessor is used
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         // We don't require our ContainerAccessor come back, but optional and required should return the same thing
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 }