View Javadoc
1   package com.atlassian.plugin.osgi.util;
2   
3   import com.atlassian.plugin.JarPluginArtifact;
4   import com.atlassian.plugin.PluginArtifact;
5   import com.atlassian.plugin.PluginParseException;
6   import com.atlassian.plugin.osgi.factory.OsgiPlugin;
7   import com.atlassian.plugin.osgi.factory.transform.StubHostComponentRegistration;
8   import com.atlassian.plugin.osgi.hostcomponents.HostComponentRegistration;
9   import com.atlassian.plugin.osgi.hostcomponents.impl.MockRegistration;
10  import com.atlassian.plugin.test.CapturedLogging;
11  import com.atlassian.plugin.test.PluginJarBuilder;
12  import com.google.common.collect.Sets;
13  import org.junit.Assert;
14  import org.junit.Rule;
15  import org.junit.Test;
16  import org.mockito.Mockito;
17  import org.osgi.framework.Bundle;
18  import org.osgi.framework.Constants;
19  import org.osgi.framework.Version;
20  
21  import java.io.ByteArrayInputStream;
22  import java.io.File;
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.util.ArrayList;
26  import java.util.Arrays;
27  import java.util.Collections;
28  import java.util.Dictionary;
29  import java.util.HashMap;
30  import java.util.Hashtable;
31  import java.util.List;
32  import java.util.Map;
33  import java.util.Set;
34  import java.util.jar.JarFile;
35  import java.util.jar.Manifest;
36  
37  import static com.atlassian.plugin.test.CapturedLogging.didLogWarn;
38  import static junit.framework.Assert.assertEquals;
39  import static junit.framework.Assert.assertFalse;
40  import static junit.framework.Assert.assertTrue;
41  import static org.hamcrest.Matchers.notNullValue;
42  import static org.hamcrest.Matchers.nullValue;
43  import static org.hamcrest.core.Is.is;
44  import static org.hamcrest.core.IsEqual.equalTo;
45  import static org.junit.Assert.assertThat;
46  import static org.mockito.Mockito.mock;
47  import static org.mockito.Mockito.when;
48  
49  public class TestOsgiHeaderUtil {
50  
51      @Rule
52      public CapturedLogging capturedLogging = new CapturedLogging(OsgiHeaderUtil.class);
53  
54      @Test(expected = NullPointerException.class)
55      public void shouldAssertValueShouldNotBeNull() {
56          Manifest manifest = new Manifest();
57          OsgiHeaderUtil.getValidatedAttribute(manifest, "some-random-key");
58      }
59  
60      @Test(expected = IllegalArgumentException.class)
61      public void shouldAssertValueShouldNotBeEmpty() throws IOException {
62          Manifest manifest = generateManifest();
63          OsgiHeaderUtil.getValidatedAttribute(manifest, "Some-other");
64      }
65  
66      @Test(expected = IllegalArgumentException.class)
67      public void shouldRaiseAnExceptionWhenValueIsMissing() throws IOException {
68          Manifest manifest = generateManifest();
69          OsgiHeaderUtil.getNonEmptyAttribute(manifest, "Some-other");
70      }
71  
72      @Test
73      public void shouldGetValidatedAttribute() throws IOException {
74          Manifest manifestFile = generateManifest();
75          assertThat(OsgiHeaderUtil.getValidatedAttribute(manifestFile, "Import-Package"), equalTo("javax.swing"));
76      }
77  
78      @Test
79      public void shouldGetEmptyAttributeWithoutValidation() throws IOException {
80          Manifest manifest = generateManifest();
81          assertThat(OsgiHeaderUtil.getAttributeWithoutValidation(manifest, "Some-other"), is(""));
82      }
83  
84      @Test
85      public void shouldGetNullAttributeWithoutValidation() throws IOException {
86          Manifest manifest = generateManifest();
87          Assert.assertNull(OsgiHeaderUtil.getAttributeWithoutValidation(manifest, "some-random"));
88      }
89  
90      private Manifest generateManifest() throws IOException {
91          File bundle = new PluginJarBuilder("someplugin")
92                  .addResource("META-INF/MANIFEST.MF", "Manifest-Version: 1.0\n" +
93                          "Import-Package: javax.swing\n" +
94                          "Bundle-SymbolicName: my.foo.symbolicName\n" +
95                          "Some-other: \n" +
96                          "Bundle-Version: 1.0\n")
97                  .build();
98          JarPluginArtifact jarPluginArtifact = new JarPluginArtifact(bundle);
99          InputStream descriptorClassStream = jarPluginArtifact.getResourceAsStream("META-INF/MANIFEST.MF");
100         return new Manifest(descriptorClassStream);
101     }
102 
103     @Test
104     public void testFindReferredPackages() throws IOException {
105         Set<String> foundPackages = OsgiHeaderUtil.findReferredPackageNames(new ArrayList<HostComponentRegistration>() {{
106             add(new StubHostComponentRegistration(OsgiHeaderUtil.class));
107         }});
108 
109         assertTrue(foundPackages.contains(HostComponentRegistration.class.getPackage().getName()));
110     }
111 
112     @Test
113     public void testFindReferredPackagesMustNotReturnJavaPackages() throws IOException {
114         List<HostComponentRegistration> regs = Arrays.<HostComponentRegistration>asList(new MockRegistration(Mockito.mock(DummyClass.class), DummyClass.class));
115 
116         Set<String> foundPackages = OsgiHeaderUtil.findReferredPackageNames(regs);
117 
118         assertFalse(foundPackages.contains("java.lang"));
119     }
120 
121     @Test
122     public void testFindReferredPackagesWithVersion() throws IOException {
123         Map<String, String> foundPackages = OsgiHeaderUtil.findReferredPackageVersions(new ArrayList<HostComponentRegistration>() {{
124             add(new StubHostComponentRegistration(OsgiHeaderUtil.class));
125         }}, Collections.singletonMap(HostComponentRegistration.class.getPackage().getName(), "1.0.45"));
126 
127         assertTrue(foundPackages.containsKey(HostComponentRegistration.class.getPackage().getName()));
128         assertEquals(foundPackages.get(HostComponentRegistration.class.getPackage().getName()), "1.0.45");
129     }
130 
131     @Test
132     public void testGetPluginKeyBundle() {
133         Dictionary headers = new Hashtable();
134         headers.put(Constants.BUNDLE_VERSION, "1.0");
135         headers.put(Constants.BUNDLE_SYMBOLICNAME, "foo");
136 
137         Bundle bundle = mock(Bundle.class);
138         when(bundle.getSymbolicName()).thenReturn("foo");
139         when(bundle.getHeaders()).thenReturn(headers);
140 
141         assertEquals("foo-1.0", OsgiHeaderUtil.getPluginKey(bundle));
142 
143         headers.put(OsgiPlugin.ATLASSIAN_PLUGIN_KEY, "bar");
144         assertEquals("bar", OsgiHeaderUtil.getPluginKey(bundle));
145     }
146 
147     @Test
148     public void testGetPluginKeyBundleWithDirectives() {
149         Dictionary headers = new Hashtable();
150         headers.put(Constants.BUNDLE_VERSION, "1.0");
151         headers.put(Constants.BUNDLE_SYMBOLICNAME, "foo;singleton:=true");
152 
153         Bundle bundle = mock(Bundle.class);
154         when(bundle.getSymbolicName()).thenReturn("foo;singleton:=true");
155         when(bundle.getHeaders()).thenReturn(headers);
156 
157         assertThat("foo-1.0", equalTo(OsgiHeaderUtil.getPluginKey(bundle)));
158 
159         headers.put(OsgiPlugin.ATLASSIAN_PLUGIN_KEY, "bar");
160         assertThat("bar", equalTo(OsgiHeaderUtil.getPluginKey(bundle)));
161     }
162 
163     @Test
164     public void testGetPluginKeyManifest() {
165         Manifest mf = new Manifest();
166         mf.getMainAttributes().putValue(Constants.BUNDLE_VERSION, "1.0");
167         mf.getMainAttributes().putValue(Constants.BUNDLE_SYMBOLICNAME, "foo");
168 
169         assertEquals("foo-1.0", OsgiHeaderUtil.getPluginKey(mf));
170 
171         mf.getMainAttributes().putValue(OsgiPlugin.ATLASSIAN_PLUGIN_KEY, "bar");
172         assertEquals("bar", OsgiHeaderUtil.getPluginKey(mf));
173     }
174 
175     @Test
176     public void testGetPluginKeyManifestWithDirectives() {
177         Manifest mf = new Manifest();
178         mf.getMainAttributes().putValue(Constants.BUNDLE_VERSION, "1.0");
179         mf.getMainAttributes().putValue(Constants.BUNDLE_SYMBOLICNAME, "foo;singleton:=true");
180 
181         assertThat("foo-1.0", equalTo(OsgiHeaderUtil.getPluginKey(mf)));
182 
183         mf.getMainAttributes().putValue(OsgiPlugin.ATLASSIAN_PLUGIN_KEY, "bar");
184         assertThat("bar", equalTo(OsgiHeaderUtil.getPluginKey(mf)));
185     }
186 
187     @Test
188     public void testGeneratePackageVersionString() {
189         Map<String, String> input = new HashMap<String, String>();
190         input.put("foo.bar", "1.2");
191         input.put("foo.baz", Version.emptyVersion.toString());
192 
193         String output = OsgiHeaderUtil.generatePackageVersionString(input);
194 
195         Set<String> set = Sets.newHashSet(output.split("[,]"));
196 
197         assertTrue(set.contains("foo.bar;version=1.2"));
198         assertTrue(set.contains("foo.baz"));
199         assertEquals(2, set.size());
200     }
201 
202     @Test
203     public void getManifestGetsManifest() {
204         final String manifestString = "Manifest-Version: 1.0\r\nSome-Header: some value\r\n";
205         final PluginArtifact pluginArtifact = getPluginArtifactWithManifest(manifestString);
206         final Manifest manifest = OsgiHeaderUtil.getManifest(pluginArtifact);
207         assertThat(manifest, notNullValue());
208         assertThat(manifest.getMainAttributes().getValue("Some-Header"), is("some value"));
209     }
210 
211     @Test
212     public void getManifestReturnsNullIfManifestIsMissing() {
213         final PluginArtifact pluginArtifact = mock(PluginArtifact.class);
214         // Mockito defaults return null, which is correct for missing resource
215         final Manifest manifest = OsgiHeaderUtil.getManifest(pluginArtifact);
216         assertThat(manifest, nullValue());
217     }
218 
219     @Test
220     public void getManifestReturnsNullIfGetResourceAsStreamFails() {
221         final PluginArtifact pluginArtifact = mock(PluginArtifact.class);
222         when(pluginArtifact.getResourceAsStream(JarFile.MANIFEST_NAME))
223                 .thenThrow(new PluginParseException("Intentional test fail"));
224         final Manifest manifest = OsgiHeaderUtil.getManifest(pluginArtifact);
225         assertThat(manifest, nullValue());
226     }
227 
228     @Test
229     public void getManifestReturnsNullIfResourceStreamThrowsWhenRead() throws Exception {
230         final InputStream inputStream = new InputStream() {
231             @Override
232             public int read() throws IOException {
233                 throw new IOException("Intentional test fail");
234             }
235         };
236         final PluginArtifact pluginArtifact = mock(PluginArtifact.class);
237         when(pluginArtifact.getResourceAsStream(JarFile.MANIFEST_NAME)).thenReturn(inputStream);
238         final Manifest manifest = OsgiHeaderUtil.getManifest(pluginArtifact);
239         assertThat(manifest, nullValue());
240     }
241 
242     @Test
243     public void getManifestReturnsNullIfManifestIsCorrupt() {
244         // Malformed, because you need a ' ' after the header ':'
245         final String manifestString = "Manifest-Version: 1.0\r\nSome-Header:some value\r\n";
246         final PluginArtifact pluginArtifact = getPluginArtifactWithManifest(manifestString);
247         final Manifest manifest = OsgiHeaderUtil.getManifest(pluginArtifact);
248         assertThat(manifest, nullValue());
249     }
250 
251     @Test
252     public void moveStarPackagesToEndComplex() {
253 
254         final Map<String, Map<String, String>> input = new HashMap<String, Map<String, String>>();
255         input.put("javax.servlet*", new HashMap<String, String>());
256         input.put("javax.servlet*~", new HashMap<String, String>());
257         input.put("*", new HashMap<String, String>());
258         input.put("*~", new HashMap<String, String>());
259         input.put("javax.servlet", new HashMap<String, String>());
260         input.put("javax.servlet~", new HashMap<String, String>());
261         input.put("org.apache.lucene.search", new HashMap<String, String>());
262 
263         final Map<String, Map<String, String>> output = new HashMap<String, Map<String, String>>();
264         output.put("javax.servlet", new HashMap<String, String>());
265         output.put("javax.servlet~", new HashMap<String, String>());
266         output.put("org.apache.lucene.search", new HashMap<String, String>());
267         output.put("javax.servlet*", new HashMap<String, String>());
268         output.put("javax.servlet*~", new HashMap<String, String>());
269         output.put("*", new HashMap<String, String>());
270         output.put("*~", new HashMap<String, String>());
271 
272         assertThat(OsgiHeaderUtil.moveStarPackageToEnd(input, "myplugin"), is(output));
273     }
274 
275     @Test
276     public void moveStarPackagesToEndEmpty() {
277         final Map<String, Map<String, String>> input = new HashMap<String, Map<String, String>>();
278         final Map<String, Map<String, String>> output = new HashMap<String, Map<String, String>>();
279         assertThat(OsgiHeaderUtil.moveStarPackageToEnd(input, "myplugin"), is(output));
280     }
281 
282     @Test
283     public void stripDuplicatePackagesWithDuplicates() {
284 
285         final Map<String, Map<String, String>> input = new HashMap<String, Map<String, String>>();
286         input.put("some.package", new HashMap<String, String>());
287         input.put("some.package~", new HashMap<String, String>());
288         input.put("some.other.package~", new HashMap<String, String>());
289 
290         final Map<String, Map<String, String>> output = new HashMap<String, Map<String, String>>();
291         output.put("some.package", new HashMap<String, String>());
292 
293         assertThat(OsgiHeaderUtil.stripDuplicatePackages(input, "myplugin", "myaction"), is(output));
294 
295         assertThat(capturedLogging, didLogWarn("removing duplicate", "myplugin", "myaction", "some.package~"));
296     }
297 
298     @Test
299     public void stripDuplicatePackagesEmpty() {
300         final Map<String, Map<String, String>> input = new HashMap<String, Map<String, String>>();
301         final Map<String, Map<String, String>> output = new HashMap<String, Map<String, String>>();
302         assertThat(OsgiHeaderUtil.stripDuplicatePackages(input, "myplugin", "myaction"), is(output));
303     }
304 
305     private PluginArtifact getPluginArtifactWithManifest(final String manifestString) {
306         final PluginArtifact pluginArtifact = mock(PluginArtifact.class);
307         final ByteArrayInputStream manifestStream = new ByteArrayInputStream(manifestString.getBytes());
308         when(pluginArtifact.getResourceAsStream(JarFile.MANIFEST_NAME)).thenReturn(manifestStream);
309         return pluginArtifact;
310     }
311 
312     private static interface DummyClass {
313         void doSomething(Object obj);
314     }
315 
316 }