View Javadoc
1   package com.atlassian.plugin.osgi.factory.transform.stage;
2   
3   import com.atlassian.plugin.JarPluginArtifact;
4   import com.atlassian.plugin.PluginAccessor;
5   import com.atlassian.plugin.osgi.SomeInterface;
6   import com.atlassian.plugin.osgi.container.OsgiContainerManager;
7   import com.atlassian.plugin.osgi.factory.transform.Barable;
8   import com.atlassian.plugin.osgi.factory.transform.FooChild;
9   import com.atlassian.plugin.osgi.factory.transform.Fooable;
10  import com.atlassian.plugin.osgi.factory.transform.StubHostComponentRegistration;
11  import com.atlassian.plugin.osgi.factory.transform.TransformContext;
12  import com.atlassian.plugin.osgi.factory.transform.model.SystemExports;
13  import com.atlassian.plugin.osgi.factory.transform.test.SomeClass;
14  import com.atlassian.plugin.osgi.hostcomponents.HostComponentRegistration;
15  import com.atlassian.plugin.osgi.hostcomponents.impl.MockRegistration;
16  import com.atlassian.plugin.test.PluginJarBuilder;
17  import org.dom4j.DocumentException;
18  import org.junit.Before;
19  import org.junit.Test;
20  import org.osgi.framework.ServiceReference;
21  
22  import javax.servlet.Servlet;
23  import javax.swing.table.TableModel;
24  import java.io.File;
25  import java.io.FileOutputStream;
26  import java.io.IOException;
27  import java.util.ArrayList;
28  import java.util.List;
29  import java.util.zip.ZipEntry;
30  import java.util.zip.ZipOutputStream;
31  
32  import static org.junit.Assert.assertEquals;
33  import static org.junit.Assert.assertNotNull;
34  import static org.junit.Assert.assertNull;
35  import static org.junit.Assert.assertTrue;
36  import static org.mockito.Mockito.mock;
37  import static org.mockito.Mockito.when;
38  
39  public class TestHostComponentSpringStage {
40  
41      private HostComponentSpringStage transformer = new HostComponentSpringStage();
42      private File jar;
43      private SystemExports systemExports;
44      private OsgiContainerManager osgiContainerManager;
45  
46      @Before
47      public void setUp() throws Exception {
48          osgiContainerManager = mock(OsgiContainerManager.class);
49          when(osgiContainerManager.getRegisteredServices()).thenReturn(new ServiceReference[0]);
50          jar = new PluginJarBuilder()
51                  .addFormattedJava("my.Foo",
52                          "package my;",
53                          "public class Foo {",
54                          "  public Foo(com.atlassian.plugin.osgi.SomeInterface bar) {}",
55                          "}")
56                  .addPluginInformation("my.plugin", "my.plugin", "1.0")
57                  .addFormattedResource("META-INF/MANIFEST.MF",
58                          "Manifest-Version: 1.0",
59                          "Bundle-Version: 1.0",
60                          "Bundle-SymbolicName: my.server",
61                          "Bundle-ManifestVersion: 2",
62                          "Bundle-ClassPath: .\n")
63                  .build();
64          systemExports = new SystemExports("javax.servlet;version=\"2.3\",javax.servlet.http;version=\"2.3\"");
65      }
66  
67      @Test
68      public void testTransformWithInnerJar() throws Exception {
69          File outerjar = new PluginJarBuilder()
70                  .addPluginInformation("my.plugin", "my.plugin", "1.0")
71                  .addFormattedResource("META-INF/MANIFEST.MF",
72                          "Manifest-Version: 1.0",
73                          "Bundle-Version: 1.0",
74                          "Bundle-SymbolicName: my.server",
75                          "Bundle-ManifestVersion: 2",
76                          "Bundle-ClassPath: .,foo.jar\n")
77                  .addFile("foo.jar", jar)
78                  .build();
79  
80          SpringTransformerTestHelper.transform(
81                  transformer,
82                  outerjar,
83                  new ArrayList<HostComponentRegistration>() {
84                      {
85                          add(new StubHostComponentRegistration("foo", new SomeInterface() {
86                          }, SomeInterface.class));
87                      }
88                  },
89                  null,
90                  "beans:bean[@id='foo']/beans:property[@name='filter']/@value='(&(bean-name=foo)(plugins-host=true))'");
91      }
92  
93      @Test
94      public void testTransformWithInnerJarContainingInnerJar() throws Exception {
95          // creates the jar file that is to be embedded in the inner jar
96          final File embeddedJar = File.createTempFile("temp", ".jar", new File(System.getProperty("java.io.tmpdir")));
97          final ZipOutputStream zout = new ZipOutputStream(new FileOutputStream(embeddedJar));
98          zout.putNextEntry(new ZipEntry("somefile"));
99          zout.write("somefile".getBytes());
100         zout.close();
101 
102         // create the inner jar embedding the jar file created in the previous step
103         // this should be exactly the same as in the setUp() method, except for the temp.jar file entry.
104         jar = new PluginJarBuilder()
105                 .addFormattedJava("my.Foo",
106                         "package my;",
107                         "public class Foo {",
108                         "  public Foo(com.atlassian.plugin.osgi.SomeInterface bar) {}",
109                         "}")
110                 .addPluginInformation("my.plugin", "my.plugin", "1.0")
111                 .addFormattedResource("META-INF/MANIFEST.MF",
112                         "Manifest-Version: 1.0",
113                         "Bundle-Version: 1.0",
114                         "Bundle-SymbolicName: my.server",
115                         "Bundle-ManifestVersion: 2",
116                         "Bundle-ClassPath: .\n")
117                 .addFile("temp.jar", embeddedJar)
118                 .build();
119 
120         // delegates to the test method that tests transformation with inner jar, the assertions should be the same
121         testTransformWithInnerJar();
122     }
123 
124     @Test
125     public void testTransform() throws IOException, DocumentException {
126         SpringTransformerTestHelper.transform(
127                 transformer,
128                 jar,
129                 new ArrayList<HostComponentRegistration>() {
130                     {
131                         add(new StubHostComponentRegistration("foo", new SomeInterface() {
132                         }, SomeInterface.class));
133                     }
134                 },
135                 null,
136                 "beans:bean[@id='foo']/beans:property[@name='interfaces']/beans:list/beans:value='" + SomeInterface.class.getName() + "'",
137                 "beans:bean[@id='foo']/beans:property[@name='filter']/@value='(&(bean-name=foo)(plugins-host=true))'");
138     }
139 
140     @Test
141     public void testTransformWithProperNestedInferredImports() throws Exception {
142         jar = new PluginJarBuilder().addFormattedJava("my.Foo", "package my;", "public class Foo {",
143                 "  public Foo(javax.swing.table.TableModel bar) {}", "}").addPluginInformation("my.plugin", "my.plugin", "1.0").build();
144 
145         final List<HostComponentRegistration> regs = new ArrayList<HostComponentRegistration>() {
146             {
147                 add(new MockRegistration("foo", TableModel.class));
148             }
149         };
150 
151         final TransformContext context = new TransformContext(regs, systemExports, new JarPluginArtifact(jar), null, PluginAccessor.Descriptor.FILENAME, osgiContainerManager);
152         transformer.execute(context);
153         assertTrue(context.getExtraImports().contains("javax.swing.event"));
154     }
155 
156     @Test
157     public void testTransformWithProperNestedVersionedInferredImports() throws Exception {
158         jar = new PluginJarBuilder()
159                 .addFormattedJava("my.Foo",
160                         "package my;",
161                         "public class Foo {",
162                         "  public Foo(javax.servlet.Servlet servlet) {}",
163                         "}")
164                 .addPluginInformation("my.plugin", "my.plugin", "1.0")
165                 .build();
166 
167         final List<HostComponentRegistration> regs = new ArrayList<HostComponentRegistration>() {
168             {
169                 add(new MockRegistration("foo", Servlet.class));
170             }
171         };
172 
173         final TransformContext context = new TransformContext(regs, systemExports, new JarPluginArtifact(jar), null, PluginAccessor.Descriptor.FILENAME, osgiContainerManager);
174         transformer.execute(context);
175         assertTrue(context.getExtraImports().contains("javax.servlet;version=\"[2.3,2.3]\""));
176 
177     }
178 
179     @Test
180     public void testTransformWithInferredImportsOfSuperInterfaces() throws Exception {
181         jar = new PluginJarBuilder()
182                 .addFormattedJava("my.Foo",
183                         "package my;",
184                         "public class Foo {",
185                         "  public Foo(com.atlassian.plugin.osgi.factory.transform.FooChild bar) {}",
186                         "}")
187                 .addPluginInformation("my.plugin", "my.plugin", "1.0")
188                 .build();
189 
190         final List<HostComponentRegistration> regs = new ArrayList<HostComponentRegistration>() {
191             {
192                 add(new MockRegistration("foo", FooChild.class));
193             }
194         };
195 
196         final TransformContext context = new TransformContext(regs, systemExports, new JarPluginArtifact(jar), null, PluginAccessor.Descriptor.FILENAME, osgiContainerManager);
197         transformer.execute(context);
198         assertTrue(context.getExtraImports().contains(SomeClass.class.getPackage().getName()));
199 
200     }
201 
202     @Test
203     public void testTransformWithSuperClassThatUsesHostComponent() throws Exception {
204         jar = new PluginJarBuilder()
205                 .addFormattedJava("my.Foo",
206                         "package my;",
207                         "public class Foo extends " + AbstractFoo.class.getName() + " {",
208                         "}")
209                 .addPluginInformation("my.plugin", "my.plugin", "1.0")
210                 .build();
211 
212         final List<HostComponentRegistration> regs = new ArrayList<HostComponentRegistration>() {
213             {
214                 add(new MockRegistration("foo", FooChild.class));
215             }
216         };
217 
218         final TransformContext context = new TransformContext(regs, systemExports, new JarPluginArtifact(jar), null, PluginAccessor.Descriptor.FILENAME, osgiContainerManager);
219         transformer.execute(context);
220         assertTrue(context.getExtraImports().contains(FooChild.class.getPackage().getName()));
221     }
222 
223     @Test
224     public void testTransformWithSuperClassInJar() throws Exception {
225         jar = new PluginJarBuilder()
226                 .addFormattedJava("my.Foo",
227                         "package my;",
228                         "public class Foo {",
229                         "}")
230                 .addFormattedJava("my2.Bar",
231                         "package my2;",
232                         "public class Bar extends my.Foo {",
233                         "}")
234                 .addPluginInformation("my.plugin", "my.plugin", "1.0")
235                 .build();
236 
237         final List<HostComponentRegistration> regs = new ArrayList<HostComponentRegistration>() {
238             {
239                 add(new MockRegistration("foo", FooChild.class));
240             }
241         };
242 
243         final TransformContext context = new TransformContext(regs, systemExports, new JarPluginArtifact(jar), null, PluginAccessor.Descriptor.FILENAME, osgiContainerManager);
244         transformer.execute(context);
245         assertEquals(0, context.getExtraImports().size());
246     }
247 
248     @Test
249     public void testTransformWithSuperClassInOtherJar() throws Exception {
250         PluginJarBuilder parent = new PluginJarBuilder()
251                 .addFormattedJava("my.Foo",
252                         "package my;",
253                         "public class Foo {",
254                         "}");
255 
256         jar = new PluginJarBuilder("child", parent.getClassLoader())
257                 .addFormattedJava("my2.Bar",
258                         "package my2;",
259                         "public class Bar extends my.Foo {",
260                         "}")
261                 .addPluginInformation("my.plugin", "my.plugin", "1.0")
262                 .build();
263 
264         final List<HostComponentRegistration> regs = new ArrayList<HostComponentRegistration>() {
265             {
266                 add(new MockRegistration("foo", FooChild.class));
267             }
268         };
269 
270         final TransformContext context = new TransformContext(regs, systemExports, new JarPluginArtifact(jar), null, PluginAccessor.Descriptor.FILENAME, osgiContainerManager);
271         transformer.execute(context);
272         assertEquals(0, context.getExtraImports().size());
273     }
274 
275     @Test
276     public void testTransformWithPoundSign() throws IOException, DocumentException {
277         SpringTransformerTestHelper.transform(
278                 transformer,
279                 jar,
280                 new ArrayList<HostComponentRegistration>() {
281                     {
282                         add(new StubHostComponentRegistration("foo#1", new SomeInterface() {
283                         }, SomeInterface.class));
284                     }
285                 },
286                 null,
287                 "beans:bean[@id='fooLB1']/beans:property[@name='filter']/@value='(&(bean-name=foo#1)(plugins-host=true))'");
288     }
289 
290     @Test
291     public void testTransformNoMatches() throws Exception {
292         final File jar = new PluginJarBuilder().addFormattedJava("my.Foo", "package my;", "public class Foo {", "  public Foo(String bar) {}", "}").addPluginInformation(
293                 "my.plugin", "my.plugin", "1.0").addResource("META-INF/MANIFEST.MF",
294                 "Manifest-Version: 1.0\n" + "Bundle-Version: 1.0\n" + "Bundle-SymbolicName: my.server\n" + "Bundle-ManifestVersion: 2\n").build();
295 
296         // host component with name
297         assertNull(SpringTransformerTestHelper.transform(transformer, jar, new ArrayList<HostComponentRegistration>() {
298             {
299                 add(new StubHostComponentRegistration("foo", SomeInterface.class));
300             }
301         }, null, "not(beans:bean[@id='foo'])"));
302     }
303 
304     @Test
305     public void testTransformMatchInInnerJar() throws Exception {
306         final File innerJar = new PluginJarBuilder().addFormattedJava("my.Foo", "package my;", "public class Foo {",
307                 "  public Foo(com.atlassian.plugin.osgi.SomeInterface bar) {}", "}").build();
308         final File jar = new PluginJarBuilder().addFile("META-INF/lib/inner.jar", innerJar).addResource(
309                 "META-INF/MANIFEST.MF",
310                 "Manifest-Version: 1.0\n" + "Bundle-Version: 1.0\n" + "Bundle-SymbolicName: my.server\n" + "Bundle-ManifestVersion: 2\n" + "Bundle-ClassPath: .,\n" + "     META-INF/lib/inner.jar\n").addPluginInformation(
311                 "my.plugin", "my.plugin", "1.0").build();
312 
313         // host component with name
314         SpringTransformerTestHelper.transform(transformer, jar, new ArrayList<HostComponentRegistration>() {
315             {
316                 add(new StubHostComponentRegistration("foo", SomeInterface.class));
317             }
318         }, null, "beans:bean[@id='foo']");
319     }
320 
321     @Test
322     public void testTransformWithExistingComponentImportName() throws Exception {
323         jar = new PluginJarBuilder()
324                 .addFormattedJava("my.Foo",
325                         "package my;",
326                         "public class Foo {",
327                         "  public Foo(com.atlassian.plugin.osgi.SomeInterface bar) {}",
328                         "}")
329                 .addFormattedResource("atlassian-plugin.xml",
330                         "<atlassian-plugin>",
331                         "  <component-import key='foo' class='Foo' interface='Foo'/>",
332                         "</atlassian-plugin>")
333                 .addResource("META-INF/MANIFEST.MF",
334                         "Manifest-Version: 1.0\n" +
335                                 "Bundle-Version: 1.0\n" +
336                                 "Bundle-SymbolicName: my.server\n" +
337                                 "Bundle-ManifestVersion: 2\n")
338                 .build();
339 
340         SpringTransformerTestHelper.transform(
341                 transformer,
342                 jar,
343                 new ArrayList<HostComponentRegistration>() {
344                     {
345                         assertTrue(add(new StubHostComponentRegistration("foo", new SomeInterface() {
346                         }, SomeInterface.class)));
347                     }
348                 },
349                 null,
350                 "beans:bean[@id='foo0']/beans:property[@name='filter']/@value='(&(bean-name=foo)(plugins-host=true))'");
351     }
352 
353     @Test
354     public void testTransformWithExistingComponentImportInterface() throws Exception {
355         jar = new PluginJarBuilder()
356                 .addFormattedJava("my.Foo",
357                         "package my;",
358                         "public class Foo {",
359                         "  public Foo(com.atlassian.plugin.osgi.SomeInterface bar) {}",
360                         "}")
361                 .addFormattedResource("atlassian-plugin.xml",
362                         "<atlassian-plugin>",
363                         "  <component-import key='foobar'>",
364                         "    <interface>com.atlassian.plugin.osgi.SomeInterface</interface>",
365                         "  </component-import>",
366                         "</atlassian-plugin>")
367                 .addResource("META-INF/MANIFEST.MF",
368                         "Manifest-Version: 1.0\n" +
369                                 "Bundle-Version: 1.0\n" +
370                                 "Bundle-SymbolicName: my.server\n" +
371                                 "Bundle-ManifestVersion: 2\n")
372                 .build();
373 
374         SpringTransformerTestHelper.transform(
375                 transformer,
376                 jar,
377                 new ArrayList<HostComponentRegistration>() {
378                     {
379                         assertTrue(add(new StubHostComponentRegistration("foo", new SomeInterface() {
380                         }, SomeInterface.class)));
381                     }
382                 },
383                 null,
384                 "not(beans:bean[@id='foo']/beans:property[@name='filter']/@value='(&(bean-name=foo)(plugins-host=true))']");
385     }
386 
387     @Test
388     public void testTransformWithExistingComponentImportInterfaceScopedToDifferentApplication() throws Exception {
389         jar = new PluginJarBuilder()
390                 .addFormattedJava("my.Foo",
391                         "package my;",
392                         "public class Foo {",
393                         "  public Foo(com.atlassian.plugin.osgi.SomeInterface bar) {}",
394                         "}")
395                 .addFormattedResource("atlassian-plugin.xml",
396                         "<atlassian-plugin>",
397                         "  <component-import key='foobar' application='notfoo'>",
398                         "    <interface>com.atlassian.plugin.osgi.SomeInterface</interface>",
399                         "  </component-import>",
400                         "</atlassian-plugin>")
401                 .addResource("META-INF/MANIFEST.MF",
402                         "Manifest-Version: 1.0\n" +
403                                 "Bundle-Version: 1.0\n" +
404                                 "Bundle-SymbolicName: my.server\n" +
405                                 "Bundle-ManifestVersion: 2\n")
406                 .build();
407 
408         assertNotNull("No file overrides!", SpringTransformerTestHelper.transform(
409                 transformer,
410                 jar,
411                 new ArrayList<HostComponentRegistration>() {
412                     {
413                         assertTrue(add(new StubHostComponentRegistration("foo", new SomeInterface() {
414                         }, SomeInterface.class)));
415                     }
416                 },
417                 null,
418                 "beans:bean[@id='foo']/beans:property[@name='filter']/@value='(&(bean-name=foo)(plugins-host=true))'"));
419     }
420 
421     @Test
422     public void testTransformWithExistingComponentImportInterfacePartialMatch() throws Exception {
423         jar = new PluginJarBuilder()
424                 .addFormattedJava("my.Foo",
425                         "package my;",
426                         "public class Foo {",
427                         "  public Foo(com.atlassian.plugin.osgi.factory.transform.Barable bar) {}",
428                         "}")
429                 .addFormattedResource("atlassian-plugin.xml",
430                         "<atlassian-plugin>",
431                         "  <component-import key='foobar'>",
432                         "    <interface>com.atlassian.plugin.osgi.factory.transform.Barable</interface>",
433                         "  </component-import>",
434                         "</atlassian-plugin>")
435                 .addResource("META-INF/MANIFEST.MF",
436                         "Manifest-Version: 1.0\n" +
437                                 "Bundle-Version: 1.0\n" +
438                                 "Bundle-SymbolicName: my.server\n" +
439                                 "Bundle-ManifestVersion: 2\n")
440                 .build();
441 
442         SpringTransformerTestHelper.transform(
443                 transformer,
444                 jar,
445                 new ArrayList<HostComponentRegistration>() {
446                     {
447                         assertTrue(add(new StubHostComponentRegistration("foo", new Fooable() {
448                             public SomeClass getSomeClass(Integer blah) {
449                                 return null;
450                             }
451                         }, Barable.class, Fooable.class)));
452                     }
453                 },
454                 null,
455                 "not(beans:bean[@id='foo']/beans:property[@name='filter']/@value='(&(bean-name=foo)(plugins-host=true))']");
456     }
457 
458     @Test
459     public void testTransformBeanTracking() throws Exception {
460         jar = new PluginJarBuilder().addFormattedJava("my.Foo", "package my;", "public class Foo {",
461                 "  public Foo(javax.swing.table.TableModel bar) {}", "}").addPluginInformation("my.plugin", "my.plugin", "1.0").build();
462 
463         final List<HostComponentRegistration> regs = new ArrayList<HostComponentRegistration>() {
464             {
465                 add(new MockRegistration("foo", TableModel.class));
466             }
467         };
468 
469         final TransformContext context = new TransformContext(regs, systemExports, new JarPluginArtifact(jar), null, PluginAccessor.Descriptor.FILENAME, osgiContainerManager);
470         transformer.execute(context);
471 
472         // the bean should exist. With no name explicitly given to the host component name, the bean name is auto-generated.
473         assertTrue(context.beanExists("bean0"));
474     }
475 }