View Javadoc

1   package com.atlassian.plugin.osgi.factory;
2   
3   import java.util.Dictionary;
4   import java.util.Hashtable;
5   import java.util.List;
6   import java.util.Set;
7   
8   import com.atlassian.plugin.module.ContainerAccessor;
9   
10  import com.google.common.collect.ImmutableList;
11  
12  import org.apache.felix.framework.resolver.Module;
13  import org.junit.After;
14  import org.junit.Before;
15  import org.junit.Rule;
16  import org.junit.Test;
17  import org.junit.rules.ExpectedException;
18  import org.osgi.framework.Bundle;
19  import org.osgi.framework.BundleContext;
20  import org.osgi.framework.Constants;
21  import org.osgi.service.packageadmin.PackageAdmin;
22  import org.springframework.beans.factory.config.BeanDefinition;
23  import org.springframework.beans.factory.support.BeanDefinitionBuilder;
24  import org.springframework.beans.factory.support.DefaultListableBeanFactory;
25  import org.springframework.context.support.GenericApplicationContext;
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.Matchers.argThat;
34  import static org.mockito.Mockito.mock;
35  import static org.mockito.Mockito.verify;
36  import static org.mockito.Mockito.when;
37  
38  public class TestOsgiPluginInstalledHelper
39  {
40      @Rule
41      public ExpectedException expectedException = ExpectedException.none();
42  
43      /**
44       * Extend the {@link Bundle} interface to add a method used by reflective code in {@link OsgiPluginInstalledHelper}.
45       */
46      interface ReflectableBundle extends Bundle
47      {
48          List<Module> getModules();
49      }
50  
51      private ReflectableBundle bundle;
52      private BundleContext bundleContext;
53      private Dictionary<String, String> dict;
54      private OsgiPluginHelper helper;
55      private PackageAdmin packageAdmin;
56  
57      @Before
58      public void setUp()
59      {
60          bundle = mock(ReflectableBundle.class);
61          dict = new Hashtable<String, String>();
62          dict.put(Constants.BUNDLE_DESCRIPTION, "desc");
63          dict.put(Constants.BUNDLE_VERSION, "1.0");
64          when(bundle.getHeaders()).thenReturn(dict);
65          bundleContext = mock(BundleContext.class);
66          when(bundle.getBundleContext()).thenReturn(bundleContext);
67  
68          helper = mock(OsgiPluginHelper.class);
69          when(helper.getBundle()).thenReturn(bundle);
70  
71          packageAdmin = mock(PackageAdmin.class);
72  
73          helper = new OsgiPluginInstalledHelper(bundle, packageAdmin);
74      }
75  
76      @After
77      public void tearDown()
78      {
79          bundle = null;
80          packageAdmin = null;
81          helper = null;
82          dict = null;
83          bundleContext = null;
84      }
85  
86      @Test
87      public void canSetContainerAccessorToSpringGenericApplicationContext()
88      {
89          final DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
90          final BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(ChildBean.class).getBeanDefinition();
91          beanFactory.registerBeanDefinition("child", beanDefinition);
92  
93          when(bundle.getSymbolicName()).thenReturn("foo");
94          helper.setPluginContainer(new GenericApplicationContext(beanFactory));
95          final SetterInjectedBean bean = new SetterInjectedBean();
96          helper.getContainerAccessor().injectBean(bean);
97          assertThat(bean.getChild(), notNullValue());
98      }
99  
100     @Test
101     public void canSetContainerAccessorToCustomContainerAccessor()
102     {
103         final ContainerAccessor containerAccessor = mock(ContainerAccessor.class);
104         final String expectedBean = "foo";
105         when(containerAccessor.createBean(String.class)).thenReturn(expectedBean);
106 
107         helper.setPluginContainer(containerAccessor);
108         // We don't require the helper return our ContainerAccessor, we require that our accessor is used
109         final String actualBean = helper.getContainerAccessor().createBean(String.class);
110         assertThat(actualBean, is(expectedBean));
111     }
112 
113     @Test
114     public void getRequiredContainerAccessorReturnsContainerAccessor()
115     {
116         final ContainerAccessor containerAccessor = mock(ContainerAccessor.class);
117         helper.setPluginContainer(containerAccessor);
118         // We don't require our ContainerAccessor come back, but optional and required should return the same thing
119         assertThat(helper.getRequiredContainerAccessor(), is(helper.getContainerAccessor()));
120     }
121 
122     @Test
123     public void beforeSetGetContainerAccessorIsNull()
124     {
125         assertThat(helper.getContainerAccessor(), nullValue());
126     }
127 
128     @Test
129     public void beforeSetGetRequiredContainerAccessorThrows()
130     {
131         final String bundleSymbolicName = "test-bundle-symbolicName";
132         when(bundle.getSymbolicName()).thenReturn(bundleSymbolicName);
133         expectedException.expect(IllegalStateException.class);
134         expectedException.expectMessage(bundleSymbolicName);
135         helper.getRequiredContainerAccessor();
136     }
137 
138     @Test
139     public void disableWithoutEnablingDoesNotThrow()
140     {
141         helper.onDisable();
142     }
143 
144     @Test
145     public void installedBundlesAreResolvedByGetRequiredPlugins()
146     {
147         when(bundle.getState()).thenReturn(Bundle.INSTALLED);
148         when(bundle.getModules()).thenReturn(ImmutableList.<Module>of());
149         when(packageAdmin.resolveBundles(argThat(arrayContaining(bundle)))).thenReturn(true);
150         helper.getRequiredPlugins();
151         verify(packageAdmin).resolveBundles(new Bundle[] { bundle });
152     }
153 
154     @Test
155     public void getRequiredPluginsReturnsEmptySetIfBundleCannotBeResolved()
156     {
157         final String symbolicName = "test-bundle-sybolicName";
158         when(bundle.getSymbolicName()).thenReturn(symbolicName);
159         when(bundle.getState()).thenReturn(Bundle.INSTALLED);
160         when(packageAdmin.resolveBundles(argThat(arrayContaining(bundle)))).thenReturn(false);
161         final Set<String> requiredPlugins = helper.getRequiredPlugins();
162         verify(packageAdmin).resolveBundles(new Bundle[] { bundle });
163         assertThat(requiredPlugins, empty());
164     }
165 
166     public static class ChildBean
167     {
168     }
169 
170     public static class SetterInjectedBean
171     {
172         private ChildBean child;
173 
174         public ChildBean getChild()
175         {
176             return child;
177         }
178 
179         @SuppressWarnings ("UnusedDeclaration")
180         public void setChild(final ChildBean child)
181         {
182             this.child = child;
183         }
184     }
185 }