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