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
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
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 }