View Javadoc

1   package com.atlassian.plugin.osgi.factory;
2   
3   import com.atlassian.plugin.Application;
4   import com.atlassian.plugin.JarPluginArtifact;
5   import com.atlassian.plugin.ModuleDescriptorFactory;
6   import com.atlassian.plugin.Plugin;
7   import com.atlassian.plugin.PluginAccessor;
8   import com.atlassian.plugin.PluginInformation;
9   import com.atlassian.plugin.PluginParseException;
10  import com.atlassian.plugin.XmlPluginArtifact;
11  import com.atlassian.plugin.event.impl.DefaultPluginEventManager;
12  import com.atlassian.plugin.osgi.container.OsgiContainerManager;
13  import com.atlassian.plugin.osgi.container.impl.DefaultOsgiPersistentCache;
14  import com.atlassian.plugin.osgi.hostcomponents.HostComponentRegistration;
15  import com.atlassian.plugin.test.PluginJarBuilder;
16  import com.atlassian.plugin.test.PluginTestUtils;
17  import com.google.common.collect.ImmutableMap;
18  import com.mockobjects.dynamic.C;
19  import com.mockobjects.dynamic.Mock;
20  import junit.framework.TestCase;
21  import org.apache.commons.io.FileUtils;
22  import org.osgi.framework.Bundle;
23  import org.osgi.framework.BundleContext;
24  import org.osgi.framework.Constants;
25  import org.osgi.service.packageadmin.PackageAdmin;
26  import org.osgi.util.tracker.ServiceTracker;
27  
28  import java.io.File;
29  import java.io.IOException;
30  import java.net.URISyntaxException;
31  import java.util.ArrayList;
32  import java.util.Collections;
33  import java.util.Dictionary;
34  import java.util.Hashtable;
35  
36  import static org.hamcrest.core.IsEqual.equalTo;
37  import static org.junit.Assert.assertThat;
38  import static org.mockito.Mockito.mock;
39  import static org.mockito.Mockito.verify;
40  import static org.mockito.Mockito.when;
41  
42  public class TestOsgiPluginFactory extends TestCase
43  {
44      OsgiPluginFactory factory;
45  
46      private File tmpDir;
47      private File jar;
48      OsgiContainerManager osgiContainerManager;
49      private Mock mockBundle;
50      private Mock mockSystemBundle;
51  
52      @Override
53      public void setUp() throws IOException, URISyntaxException
54      {
55          tmpDir = PluginTestUtils.createTempDirectory(TestOsgiPluginFactory.class);
56          osgiContainerManager = mock(OsgiContainerManager.class);
57          ServiceTracker tracker = mock(ServiceTracker.class);
58          when(tracker.getServices()).thenReturn(new Object[0]);
59          when(osgiContainerManager.getServiceTracker(ModuleDescriptorFactory.class.getName())).thenReturn(tracker);
60  
61          factory = new OsgiPluginFactory(PluginAccessor.Descriptor.FILENAME, Collections.<Application>emptySet(), new DefaultOsgiPersistentCache(tmpDir), osgiContainerManager, new DefaultPluginEventManager());
62          jar = new PluginJarBuilder("someplugin").addPluginInformation("plugin.key", "My Plugin", "1.0").build();
63  
64          mockBundle = new Mock(Bundle.class);
65          final Dictionary<String, String> dict = new Hashtable<String, String>();
66          dict.put(Constants.BUNDLE_DESCRIPTION, "desc");
67          dict.put(Constants.BUNDLE_VERSION, "1.0");
68          mockBundle.matchAndReturn("getHeaders", dict);
69  
70          mockSystemBundle = new Mock(Bundle.class);
71          final Dictionary<String, String> sysDict = new Hashtable<String, String>();
72          sysDict.put(Constants.BUNDLE_DESCRIPTION, "desc");
73          sysDict.put(Constants.BUNDLE_VERSION, "1.0");
74          mockSystemBundle.matchAndReturn("getHeaders", sysDict);
75          mockSystemBundle.matchAndReturn("getLastModified", System.currentTimeMillis());
76          mockSystemBundle.matchAndReturn("getSymbolicName", "system.bundle");
77  
78          Mock mockSysContext = new Mock(BundleContext.class);
79          mockSystemBundle.matchAndReturn("getBundleContext", mockSysContext.proxy());
80  
81          mockSysContext.matchAndReturn("getServiceReference", C.ANY_ARGS, null);
82          mockSysContext.matchAndReturn("getService", C.ANY_ARGS, new Mock(PackageAdmin.class).proxy());
83      }
84  
85      @Override
86      public void tearDown() throws IOException
87      {
88          factory = null;
89          FileUtils.cleanDirectory(tmpDir);
90          jar.delete();
91      }
92  
93      public void testCreateOsgiPlugin() throws PluginParseException
94      {
95          mockBundle.expectAndReturn("getSymbolicName", "plugin.key");
96          when(osgiContainerManager.getHostComponentRegistrations()).thenReturn(new ArrayList());
97          when(osgiContainerManager.getBundles()).thenReturn(new Bundle[] {(Bundle) mockSystemBundle.proxy()});
98          final Plugin plugin = factory.create(new JarPluginArtifact(jar), (ModuleDescriptorFactory) new Mock(ModuleDescriptorFactory.class).proxy());
99          assertNotNull(plugin);
100         assertTrue(plugin instanceof OsgiPlugin);
101     }
102 
103     public void testCreateOsgiPluginWithBadVersion() throws PluginParseException, IOException
104     {
105         jar = new PluginJarBuilder("someplugin").addPluginInformation("plugin.key", "My Plugin", "beta.1.0").build();
106         mockBundle.expectAndReturn("getSymbolicName", "plugin.key");
107         when(osgiContainerManager.getHostComponentRegistrations()).thenReturn(new ArrayList());
108         when(osgiContainerManager.getBundles()).thenReturn(new Bundle[] {(Bundle) mockSystemBundle.proxy()});
109         try
110         {
111             factory.create(new JarPluginArtifact(jar), (ModuleDescriptorFactory) new Mock(ModuleDescriptorFactory.class).proxy());
112             fail("Should have complained about osgi version");
113         }
114         catch (PluginParseException ex)
115         {
116             // expected
117         }
118     }
119 
120     public void testCreateOsgiPluginWithBadVersion2() throws PluginParseException, IOException
121     {
122         jar = new PluginJarBuilder("someplugin").addPluginInformation("plugin.key", "My Plugin", "3.2-rc1").build();
123         mockBundle.expectAndReturn("getSymbolicName", "plugin.key");
124         when(osgiContainerManager.getHostComponentRegistrations()).thenReturn(new ArrayList());
125         when(osgiContainerManager.getBundles()).thenReturn(new Bundle[] {(Bundle) mockSystemBundle.proxy()});
126         Plugin plugin = factory.create(new JarPluginArtifact(jar), (ModuleDescriptorFactory) new Mock(ModuleDescriptorFactory.class).proxy());
127         assertTrue(plugin instanceof OsgiPlugin);
128     }
129 
130     public void testCreateOsgiPluginWithManifestKey() throws PluginParseException, IOException
131     {
132         mockBundle.expectAndReturn("getSymbolicName", "plugin.key");
133         when(osgiContainerManager.getHostComponentRegistrations()).thenReturn(new ArrayList());
134         when(osgiContainerManager.getBundles()).thenReturn(new Bundle[] {(Bundle) mockSystemBundle.proxy()});
135 
136         final File pluginFile = new PluginJarBuilder("loadwithxml")
137                 .manifest(new ImmutableMap.Builder<String, String>()
138                         .put(OsgiPlugin.ATLASSIAN_PLUGIN_KEY, "somekey")
139                         .put(Constants.BUNDLE_VERSION, "1.0")
140                         .put(Constants.BUNDLE_NAME,"My awesome plugin")
141                         .put(Constants.BUNDLE_DESCRIPTION,"Bundle Description")
142                         .put(Constants.BUNDLE_VENDOR,"My vendor Name")
143                         .build())
144                 .build();
145 
146         final Plugin plugin = factory.create(new JarPluginArtifact(pluginFile), (ModuleDescriptorFactory) new Mock(ModuleDescriptorFactory.class).proxy());
147         assertNotNull(plugin);
148         assertTrue(plugin instanceof OsgiPlugin);
149     }
150 
151     public void testCreateOsgiPluginWithManifestKeyAndDescriptorSkippingTransform() throws PluginParseException, IOException
152     {
153         File jar = new PluginJarBuilder("someplugin")
154                 .addPluginInformation("plugin.key", "My Plugin", "1.0")
155                 .manifest(new ImmutableMap.Builder<String, String>()
156                                         .put(OsgiPlugin.ATLASSIAN_PLUGIN_KEY, "somekey")
157                                         .put(Constants.BUNDLE_VERSION, "1.0")
158                                         .build())
159                 .build();
160         mockBundle.expectAndReturn("getSymbolicName", "plugin.key");
161         mockBundle.expectAndReturn("getHeaders", new Hashtable() {{
162             put(OsgiPlugin.ATLASSIAN_PLUGIN_KEY, "plugin.key");
163             put(Constants.BUNDLE_VERSION, "1.0");
164         }});
165         when(osgiContainerManager.getHostComponentRegistrations()).thenReturn(
166                 Collections.<HostComponentRegistration>emptyList());
167         when(osgiContainerManager.getBundles()).thenReturn(new Bundle[] {(Bundle) mockSystemBundle.proxy()});
168         when(osgiContainerManager.installBundle(jar)).thenReturn((Bundle) mockBundle.proxy());
169         final Plugin plugin = factory.create(new JarPluginArtifact(jar), (ModuleDescriptorFactory) new Mock(ModuleDescriptorFactory.class).proxy());
170         assertNotNull(plugin);
171         assertTrue(plugin instanceof OsgiPlugin);
172 
173         plugin.install();
174         verify(osgiContainerManager).installBundle(jar);
175     }
176 
177     public void testPluginInformationAndPluginNameIsExtractedFromManifest() throws IOException
178     {
179         PluginInformation expectedPluginInformation = createPluginInformation("My Description", "My Awesome Vendor Name", "1.0");
180         when(osgiContainerManager.getHostComponentRegistrations()).thenReturn(new ArrayList());
181         when(osgiContainerManager.getBundles()).thenReturn(new Bundle[] {(Bundle) mockSystemBundle.proxy()});
182 
183         String pluginName = "My awesome plugin";
184 
185         final Plugin plugin = createPlugin(pluginName, expectedPluginInformation);
186         assertNotNull(plugin);
187         assertTrue(plugin instanceof OsgiPlugin);
188 
189         assertThat(plugin.getName(),equalTo(pluginName));
190 
191         PluginInformation actualPluginInformation = plugin.getPluginInformation();
192         assertThat(actualPluginInformation.getDescription(), equalTo(expectedPluginInformation.getDescription()));
193         assertThat(actualPluginInformation.getVendorName(),equalTo(expectedPluginInformation.getVendorName()));
194         assertThat(actualPluginInformation.getVersion(), equalTo(expectedPluginInformation.getVersion()));
195     }
196 
197     public void testShouldLoadPluginIfManifestDoesNotHaveOptionalInformation() throws IOException
198     {
199         PluginInformation pluginInformation = createPluginInformation("", "", "1.0");
200         when(osgiContainerManager.getHostComponentRegistrations()).thenReturn(new ArrayList());
201         when(osgiContainerManager.getBundles()).thenReturn(new Bundle[] {(Bundle) mockSystemBundle.proxy()});
202 
203         String pluginName = "My Awesome Plugin";
204         Plugin plugin = createPlugin(pluginName, pluginInformation);
205 
206         assertNotNull(plugin);
207         assertTrue(plugin instanceof OsgiPlugin);
208         assertThat(plugin.getName(), equalTo(pluginName));
209     }
210 
211     private Plugin createPlugin(String pluginName, PluginInformation pluginInformation) throws IOException
212     {
213         final File pluginFile = new PluginJarBuilder("loadwithxml")
214                 .manifest(new ImmutableMap.Builder<String, String>()
215                         .put(OsgiPlugin.ATLASSIAN_PLUGIN_KEY, pluginName)
216                         .put(Constants.BUNDLE_VERSION, pluginInformation.getVersion())
217                         .put(Constants.BUNDLE_NAME, pluginName)
218                         .put(Constants.BUNDLE_DESCRIPTION, pluginInformation.getDescription())
219                         .put(Constants.BUNDLE_VENDOR, pluginInformation.getVendorName())
220                         .build())
221                 .build();
222 
223         return factory.create(new JarPluginArtifact(pluginFile), (ModuleDescriptorFactory) new Mock(ModuleDescriptorFactory.class).proxy());
224     }
225 
226     private PluginInformation createPluginInformation(String description, String vendorName, String version)
227     {
228         PluginInformation pluginInformation = new PluginInformation();
229         pluginInformation.setDescription(description);
230         pluginInformation.setVendorName(vendorName);
231         pluginInformation.setVersion(version);
232         return pluginInformation;
233     }
234 
235     public void testCreateOsgiPluginWithManifestKeyNoVersion() throws PluginParseException, IOException
236     {
237         mockBundle.expectAndReturn("getSymbolicName", "plugin.key");
238         when(osgiContainerManager.getHostComponentRegistrations()).thenReturn(new ArrayList());
239         when(osgiContainerManager.getBundles()).thenReturn(new Bundle[] {(Bundle) mockSystemBundle.proxy()});
240 
241         final File pluginFile = new PluginJarBuilder("loadwithxml")
242                 .manifest(new ImmutableMap.Builder<String, String>()
243                         .put(OsgiPlugin.ATLASSIAN_PLUGIN_KEY, "somekey")
244                         .build())
245                 .build();
246 
247         try
248         {
249             factory.create(new JarPluginArtifact(pluginFile), (ModuleDescriptorFactory) new Mock(ModuleDescriptorFactory.class).proxy());
250             fail("Should have failed due to no version");
251         }
252         catch (NullPointerException ex)
253         {
254             // test passed
255         }
256     }
257 
258     public void testCanLoadWithXml() throws PluginParseException, IOException
259     {
260         final File plugin = new PluginJarBuilder("loadwithxml").addPluginInformation("foo.bar", "", "1.0").build();
261         final String key = factory.canCreate(new JarPluginArtifact(plugin));
262         assertEquals("foo.bar", key);
263     }
264 
265     public void testCanLoadWithXmlArtifact() throws PluginParseException, IOException
266     {
267         File xmlFile = new File(tmpDir, "plugin.xml");
268         FileUtils.writeStringToFile(xmlFile, "<somexml />");
269         final String key = factory.canCreate(new XmlPluginArtifact(xmlFile));
270         assertNull(key);
271     }
272 
273     public void testCanLoadJarWithNoManifest() throws PluginParseException, IOException
274     {
275         final File plugin = new PluginJarBuilder("loadwithxml")
276                 .addResource("foo.xml", "<foo/>")
277                 .buildWithNoManifest();
278         final String key = factory.canCreate(new JarPluginArtifact(plugin));
279         assertNull(key);
280     }
281 
282     public void testCanLoadNoXml() throws PluginParseException, IOException
283     {
284         final File plugin = new PluginJarBuilder("loadwithxml").build();
285         final String key = factory.canCreate(new JarPluginArtifact(plugin));
286         assertNull(key);
287     }
288 
289     public void testCanLoadNoXmlButWithManifestEntry() throws PluginParseException, IOException
290     {
291         final File plugin = new PluginJarBuilder("loadwithxml")
292                 .manifest(new ImmutableMap.Builder<String, String>()
293                         .put(OsgiPlugin.ATLASSIAN_PLUGIN_KEY, "somekey")
294                         .put(Constants.BUNDLE_VERSION, "1.0")
295                         .build())
296                 .build();
297         final String key = factory.canCreate(new JarPluginArtifact(plugin));
298         assertEquals("somekey", key);
299     }
300 
301     public void testCanLoadNoXmlButWithManifestEntryNoVersion() throws PluginParseException, IOException
302     {
303         final File plugin = new PluginJarBuilder("loadwithxml")
304                 .manifest(new ImmutableMap.Builder<String, String>()
305                         .put(OsgiPlugin.ATLASSIAN_PLUGIN_KEY, "somekey")
306                         .build())
307                 .build();
308         final String key = factory.canCreate(new JarPluginArtifact(plugin));
309         assertNull(key);
310     }
311 
312     public void testCanLoadWithXmlVersion3() throws Exception
313     {
314         final File plugin = new PluginJarBuilder("loadwithxml").addPluginInformation("foo.bar", "", "1.0", 3).build();
315         final String key = factory.canCreate(new JarPluginArtifact(plugin));
316         assertNull(key);
317     }
318 }