View Javadoc

1   package com.atlassian.plugin.parsers;
2   
3   import com.atlassian.plugin.Application;
4   import com.atlassian.plugin.InstallationMode;
5   import com.atlassian.plugin.ModuleDescriptorFactory;
6   import com.atlassian.plugin.Plugin;
7   import com.atlassian.plugin.PluginArtifact;
8   import com.atlassian.plugin.PluginInformation;
9   import com.atlassian.plugin.PluginParseException;
10  import com.atlassian.plugin.PluginPermission;
11  import com.atlassian.plugin.classloader.PluginClassLoader;
12  import com.atlassian.plugin.impl.DefaultDynamicPlugin;
13  import com.atlassian.plugin.mock.MockAnimalModuleDescriptor;
14  import com.atlassian.plugin.util.ClassLoaderUtils;
15  import com.google.common.collect.Iterables;
16  import com.mockobjects.dynamic.C;
17  import com.mockobjects.dynamic.Mock;
18  import junit.framework.TestCase;
19  
20  import java.io.ByteArrayInputStream;
21  import java.io.File;
22  import java.io.FileInputStream;
23  import java.io.FileNotFoundException;
24  import java.io.InputStream;
25  import java.net.URL;
26  import java.util.Set;
27  
28  @SuppressWarnings({"deprecation"}) //suppress deprecation warnings because we still need to test deprecated methods.
29  public class TestXmlDescriptorParser extends TestCase
30  {
31      private static final String MISSING_INFO_TEST_FILE = "test-missing-plugin-info.xml";
32      private static final String DUMMY_PLUGIN_FILE = "pooh-test-plugin.jar";
33  
34      public TestXmlDescriptorParser(String name)
35      {
36          super(name);
37      }
38  
39      // CONF-12680 Test for missing plugin-info
40      public void testMissingPluginInfo()
41      {
42          // mock up some supporting objects
43          PluginClassLoader classLoader = new PluginClassLoader(new File(getTestFile("ap-plugins") + "/" + DUMMY_PLUGIN_FILE));
44          Mock mockFactory = new Mock(ModuleDescriptorFactory.class);
45          mockFactory.expect("getModuleDescriptorClass", "unknown-plugin");
46  
47          // create a Plugin for testing
48          Plugin testPlugin = new DefaultDynamicPlugin((PluginArtifact) new Mock(PluginArtifact.class).proxy(), classLoader);
49  
50          try
51          {
52              XmlDescriptorParser parser = new XmlDescriptorParser(new FileInputStream(getTestFile(MISSING_INFO_TEST_FILE)));
53              parser.configurePlugin((ModuleDescriptorFactory)mockFactory.proxy(), testPlugin);
54  
55              PluginInformation info = testPlugin.getPluginInformation();
56              assertNotNull("Info should not be null", info);
57          }
58          catch (PluginParseException e)
59          {
60              e.printStackTrace();
61              fail("Plugin information parsing should not fail.");
62          }
63          catch (FileNotFoundException e)
64          {
65              e.printStackTrace();
66              // This shouldn't happen
67              fail("Error setting up test");
68          }
69      }
70  
71      public void testPluginsApplicationVersionMinMax()
72      {
73          XmlDescriptorParser parser = parse(null,
74                  "<atlassian-plugin key='foo'>",
75                  "  <plugin-info>",
76                  "    <application-version min='3' max='4' />",
77                  "  </plugin-info>",
78                  "</atlassian-plugin>");
79          assertEquals(3, (int)parser.getPluginInformation().getMinVersion());
80          assertEquals(4, (int)parser.getPluginInformation().getMaxVersion());
81      }
82  
83      public void testPluginsApplicationVersionMinMaxWithOnlyMin()
84      {
85          XmlDescriptorParser parser = parse(null,
86                  "<atlassian-plugin key='foo'>",
87                  "  <plugin-info>",
88                  "    <application-version min='3' />",
89                  "  </plugin-info>",
90                  "</atlassian-plugin>");
91          assertEquals(3, (int)parser.getPluginInformation().getMinVersion());
92          assertEquals(0, (int)parser.getPluginInformation().getMaxVersion());
93      }
94  
95      public void testPluginsApplicationVersionMinMaxWithOnlyMax()
96      {
97          XmlDescriptorParser parser = parse(null,
98                  "<atlassian-plugin key='foo'>",
99                  "  <plugin-info>",
100                 "    <application-version max='3' />",
101                 "  </plugin-info>",
102                 "</atlassian-plugin>");
103         assertEquals(3, (int)parser.getPluginInformation().getMaxVersion());
104         assertEquals(0, (int)parser.getPluginInformation().getMinVersion());
105     }
106 
107     // Also CONF-12680 test for missing "essential metadata"
108 
109     public void testPluginsVersion()
110     {
111         String xml = "<atlassian-plugin key=\"foo\" pluginsVersion=\"2\" />";
112         XmlDescriptorParser parser = new XmlDescriptorParser(new ByteArrayInputStream(xml.getBytes()));
113         assertEquals(2, parser.getPluginsVersion());
114     }
115 
116     public void testPluginsVersionAfterConfigure()
117     {
118         XmlDescriptorParser parser = new XmlDescriptorParser(new ByteArrayInputStream("<atlassian-plugin key=\"foo\" plugins-version=\"2\" />".getBytes()));
119         // mock up some supporting objects
120         PluginClassLoader classLoader = new PluginClassLoader(new File(getTestFile("ap-plugins") + "/" + DUMMY_PLUGIN_FILE));
121         Mock mockFactory = new Mock(ModuleDescriptorFactory.class);
122         mockFactory.expect("getModuleDescriptorClass", "unknown-plugin");
123 
124         // create a Plugin for testing
125         Plugin testPlugin = new DefaultDynamicPlugin((PluginArtifact) new Mock(PluginArtifact.class).proxy(), classLoader);
126         parser.configurePlugin((ModuleDescriptorFactory)mockFactory.proxy(), testPlugin);
127         assertEquals(2, testPlugin.getPluginsVersion());
128     }
129 
130     public void testPluginWithModules()
131     {
132         XmlDescriptorParser parser = parse(null,
133                 "<atlassian-plugin key='foo'>",
134                 "  <animal key='bear' />",
135                 "</atlassian-plugin>");
136         // mock up some supporting objects
137         PluginClassLoader classLoader = new PluginClassLoader(new File(getTestFile("ap-plugins") + "/" + DUMMY_PLUGIN_FILE));
138         Mock mockFactory = new Mock(ModuleDescriptorFactory.class);
139         mockFactory.expectAndReturn("getModuleDescriptorClass", C.args(C.eq("animal")), MockAnimalModuleDescriptor.class);
140 
141         // create a Plugin for testing
142         Plugin testPlugin = new DefaultDynamicPlugin((PluginArtifact) new Mock(PluginArtifact.class).proxy(), classLoader);
143         parser.configurePlugin((ModuleDescriptorFactory)mockFactory.proxy(), testPlugin);
144         assertNotNull(testPlugin.getModuleDescriptor("bear"));
145     }
146 
147     public void testPluginWithModulesNoApplicationKey()
148     {
149         XmlDescriptorParser parser = parse(null,
150                 "<atlassian-plugin key='foo'>",
151                 "  <animal key='bear' application='foo'/>",
152                 "</atlassian-plugin>");
153         // mock up some supporting objects
154         PluginClassLoader classLoader = new PluginClassLoader(new File(getTestFile("ap-plugins") + "/" + DUMMY_PLUGIN_FILE));
155         Mock mockFactory = new Mock(ModuleDescriptorFactory.class);
156         mockFactory.expectAndReturn("getModuleDescriptorClass", C.args(C.eq("animal")), MockAnimalModuleDescriptor.class);
157 
158         // create a Plugin for testing
159         Plugin testPlugin = new DefaultDynamicPlugin((PluginArtifact) new Mock(PluginArtifact.class).proxy(), classLoader);
160         parser.configurePlugin((ModuleDescriptorFactory)mockFactory.proxy(), testPlugin);
161         assertNull(testPlugin.getModuleDescriptor("bear"));
162     }
163 
164     public void testPluginWithSomeNonApplicationModules()
165     {
166         XmlDescriptorParser parser = parse(newApplication("myapp"),
167                 "<atlassian-plugin key='foo'>",
168                 "  <animal key='bear' application='myapp'/>",
169                 "  <animal key='bear2' application='otherapp'/>",
170                 "</atlassian-plugin>");
171         // mock up some supporting objects
172         PluginClassLoader classLoader = new PluginClassLoader(new File(getTestFile("ap-plugins") + "/" + DUMMY_PLUGIN_FILE));
173         Mock mockFactory = new Mock(ModuleDescriptorFactory.class);
174         mockFactory.expectAndReturn("getModuleDescriptorClass", C.args(C.eq("animal")), MockAnimalModuleDescriptor.class);
175 
176         // create a Plugin for testing
177         Plugin testPlugin = new DefaultDynamicPlugin((PluginArtifact) new Mock(PluginArtifact.class).proxy(), classLoader);
178         parser.configurePlugin((ModuleDescriptorFactory)mockFactory.proxy(), testPlugin);
179         assertNotNull(testPlugin.getModuleDescriptor("bear"));
180         assertNull(testPlugin.getModuleDescriptor("bear2"));
181     }
182 
183     public void testPluginWithSomeRestrictionOnModulesNoVersion()
184     {
185         XmlDescriptorParser parser = parse(newApplication("myapp"),
186                 "<atlassian-plugin key='foo'>",
187                 "  <animal key='bear'>",
188                 "    <restrict application='myapp'/>",
189                 "  </animal>",
190                 "  <animal key='bear2' application='otherapp'/>",
191                 "</atlassian-plugin>");
192         // mock up some supporting objects
193         PluginClassLoader classLoader = new PluginClassLoader(new File(getTestFile("ap-plugins") + "/" + DUMMY_PLUGIN_FILE));
194         Mock mockFactory = new Mock(ModuleDescriptorFactory.class);
195         mockFactory.expectAndReturn("getModuleDescriptorClass", C.args(C.eq("animal")), MockAnimalModuleDescriptor.class);
196 
197         // create a Plugin for testing
198         Plugin testPlugin = new DefaultDynamicPlugin((PluginArtifact) new Mock(PluginArtifact.class).proxy(), classLoader);
199         parser.configurePlugin((ModuleDescriptorFactory)mockFactory.proxy(), testPlugin);
200         assertNotNull(testPlugin.getModuleDescriptor("bear"));
201         assertNull(testPlugin.getModuleDescriptor("bear2"));
202     }
203 
204     public void testPluginWithSomeRestrictionOnModulesVersionAsAttribute()
205     {
206         XmlDescriptorParser parser = parse(newApplication("myapp", "2.0"),
207                 "<atlassian-plugin key='foo'>",
208                 "  <animal key='bear'>",
209                 "    <restrict application='myapp' version='[2.0]' />",
210                 "  </animal>",
211                 "  <animal key='bear2'>",
212                 "    <restrict application='myapp' version='[1.0]' />",
213                 "  </animal>",
214                 "</atlassian-plugin>");
215         // mock up some supporting objects
216         PluginClassLoader classLoader = new PluginClassLoader(new File(getTestFile("ap-plugins") + "/" + DUMMY_PLUGIN_FILE));
217         Mock mockFactory = new Mock(ModuleDescriptorFactory.class);
218         mockFactory.matchAndReturn("getModuleDescriptorClass", C.args(C.eq("animal")), MockAnimalModuleDescriptor.class);
219 
220         // create a Plugin for testing
221         Plugin testPlugin = new DefaultDynamicPlugin((PluginArtifact) new Mock(PluginArtifact.class).proxy(), classLoader);
222         parser.configurePlugin((ModuleDescriptorFactory)mockFactory.proxy(), testPlugin);
223         assertNotNull(testPlugin.getModuleDescriptor("bear"));
224         assertNull(testPlugin.getModuleDescriptor("bear2"));
225     }
226 
227     public void testPluginWithSomeRestrictionOnModulesVersionAsElement()
228     {
229         XmlDescriptorParser parser = parse(newApplication("myapp", "2.0"),
230                 "<atlassian-plugin key='foo'>",
231                 "  <animal key='bear'>",
232                 "    <restrict application='myapp'>",
233                 "      <version>(,3.0)</version>",
234                 "      <version>[5.0,)</version>",
235                 "    </restrict>",
236                 "  </animal>",
237                 "  <animal key='bear2'>",
238                 "    <restrict application='myapp'>",
239                 "      <version>(,2.0)</version>",
240                 "      <version>[5.0,)</version>",
241                 "    </restrict>",
242                 "  </animal>",
243                 "</atlassian-plugin>");
244         // mock up some supporting objects
245         PluginClassLoader classLoader = new PluginClassLoader(new File(getTestFile("ap-plugins") + "/" + DUMMY_PLUGIN_FILE));
246         Mock mockFactory = new Mock(ModuleDescriptorFactory.class);
247         mockFactory.matchAndReturn("getModuleDescriptorClass", C.args(C.eq("animal")), MockAnimalModuleDescriptor.class);
248 
249         // create a Plugin for testing
250         Plugin testPlugin = new DefaultDynamicPlugin((PluginArtifact) new Mock(PluginArtifact.class).proxy(), classLoader);
251         parser.configurePlugin((ModuleDescriptorFactory)mockFactory.proxy(), testPlugin);
252         assertNotNull(testPlugin.getModuleDescriptor("bear"));
253         assertNull(testPlugin.getModuleDescriptor("bear2"));
254     }
255 
256     public void testPluginWithSystemAttribute()
257     {
258         XmlDescriptorParser parser = parse(null,
259                 "<atlassian-plugin key='foo' system='true'>",
260                 "</atlassian-plugin>");
261 
262         // mock up some supporting objects
263         PluginClassLoader classLoader = new PluginClassLoader(new File(getTestFile("ap-plugins") + "/" + DUMMY_PLUGIN_FILE));
264         Mock mockFactory = new Mock(ModuleDescriptorFactory.class);
265         mockFactory.expectAndReturn("getModuleDescriptorClass", C.args(C.eq("animal")), MockAnimalModuleDescriptor.class);
266 
267         // create a Plugin for testing
268         Plugin testPlugin = new DefaultDynamicPlugin((PluginArtifact) new Mock(PluginArtifact.class).proxy(), classLoader);
269         parser.configurePlugin((ModuleDescriptorFactory)mockFactory.proxy(), testPlugin);
270         // PLUG-415 Plugins2 plugins now need to be able to be declared as system.
271         assertEquals("This plugin should be a system plugin - bundled plugins2 plugins are system plugins.", true, testPlugin.isSystemPlugin());
272     }
273 
274     public void testPluginWithoutSystemAttribute()
275     {
276         XmlDescriptorParser parser = parse(null,
277                 "<atlassian-plugin key='foo' >",
278                 "</atlassian-plugin>");
279 
280         // mock up some supporting objects
281         PluginClassLoader classLoader = new PluginClassLoader(new File(getTestFile("ap-plugins") + "/" + DUMMY_PLUGIN_FILE));
282         Mock mockFactory = new Mock(ModuleDescriptorFactory.class);
283         mockFactory.expectAndReturn("getModuleDescriptorClass", C.args(C.eq("animal")), MockAnimalModuleDescriptor.class);
284 
285         // create a Plugin for testing
286         Plugin testPlugin = new DefaultDynamicPlugin((PluginArtifact) new Mock(PluginArtifact.class).proxy(), classLoader);
287         parser.configurePlugin((ModuleDescriptorFactory)mockFactory.proxy(), testPlugin);
288         assertEquals("This plugin should not be a system plugin.", false, testPlugin.isSystemPlugin());
289     }
290 
291     public void testPluginsVersionWithDash()
292     {
293         String xml = "<atlassian-plugin key=\"foo\" plugins-version=\"2\" />";
294         XmlDescriptorParser parser = new XmlDescriptorParser(new ByteArrayInputStream(xml.getBytes()));
295         assertEquals(2, parser.getPluginsVersion());
296     }
297 
298     public void testPluginsVersionMissing()
299     {
300         String xml = "<atlassian-plugin key=\"foo\" />";
301         XmlDescriptorParser parser = new XmlDescriptorParser(new ByteArrayInputStream(xml.getBytes()));
302         assertEquals(1, parser.getPluginsVersion());
303     }
304 
305     public void testPluginsResourcesAvailableToModuleDescriptors()
306     {
307         XmlDescriptorParser parser = parse(null,
308                 "<atlassian-plugin key='foo'>",
309                 "  <resource type='velocity' name='edit'>Show an input box here.</resource>",
310                 "  <animal key='bear' />",
311                 "</atlassian-plugin>");
312         // mock up some supporting objects
313         PluginClassLoader classLoader = new PluginClassLoader(new File(getTestFile("ap-plugins") + "/" + DUMMY_PLUGIN_FILE));
314         Mock mockFactory = new Mock(ModuleDescriptorFactory.class);
315         MockAnimalModuleDescriptor descriptor = new MockAnimalModuleDescriptor("velocity", "edit");
316         mockFactory.expectAndReturn("getModuleDescriptor", C.args(C.eq("animal")), descriptor);
317 
318         // create a Plugin for testing
319         Plugin testPlugin = new DefaultDynamicPlugin((PluginArtifact) new Mock(PluginArtifact.class).proxy(), classLoader);
320         parser.configurePlugin((ModuleDescriptorFactory)mockFactory.proxy(), testPlugin);
321         assertNotNull(testPlugin.getModuleDescriptor("bear"));
322 
323         mockFactory.verify();
324     }
325 
326     public void testPluginPermissionsIsAllPermissionsForPluginsWithNoVersionByDefault()
327     {
328         XmlDescriptorParser parser = parse(null,
329                 "<atlassian-plugin key='foo'>",
330                 "  <plugin-info>",
331                 "  </plugin-info>",
332                 "</atlassian-plugin>");
333 
334         final Set<PluginPermission> parsedPermissions = parser.getPluginInformation().getPermissions();
335         assertEquals(1, parsedPermissions.size());
336         assertSame(PluginPermission.ALL, Iterables.get(parsedPermissions, 0));
337     }
338 
339     public void testPluginPermissionsIsAllPermissionsForPlugins1ByDefault()
340     {
341         XmlDescriptorParser parser = parse(null,
342                 "<atlassian-plugin key='foo' plugins-version='1'>",
343                 "  <plugin-info>",
344                 "  </plugin-info>",
345                 "</atlassian-plugin>");
346 
347         final Set<PluginPermission> parsedPermissions = parser.getPluginInformation().getPermissions();
348         assertEquals(1, parsedPermissions.size());
349         assertSame(PluginPermission.ALL, Iterables.get(parsedPermissions, 0));
350     }
351 
352     public void testPluginPermissionsIsAllPermissionsForPlugins2ByDefault()
353     {
354         XmlDescriptorParser parser = parse(null,
355                 "<atlassian-plugin key='foo' plugins-version='2'>",
356                 "  <plugin-info>",
357                 "  </plugin-info>",
358                 "</atlassian-plugin>");
359 
360         final Set<PluginPermission> parsedPermissions = parser.getPluginInformation().getPermissions();
361         assertEquals(1, parsedPermissions.size());
362         assertSame(PluginPermission.ALL, Iterables.get(parsedPermissions, 0));
363     }
364 
365     public void testPluginPermissionsIsFilteredByApplications()
366     {
367         XmlDescriptorParser parser = parse(newApplication("my-app"),
368                 "<atlassian-plugin key='foo' plugins-version='2'>",
369                 "  <plugin-info>",
370                 "    <permissions>",
371                 "      <permission application='my-other-app'>some_permission</permission>",
372                 "      <permission application='my-app'>some_other_permission</permission>",
373                 "      <permission application='my-other-app' installation-mode='local'>yet_another_permission</permission>",
374                 "    </permissions>",
375                 "  </plugin-info>",
376                 "</atlassian-plugin>");
377 
378         final Set<PluginPermission> parsedPermissions = parser.getPluginInformation().getPermissions();
379         assertEquals(1, parsedPermissions.size());
380         assertEquals("some_other_permission", Iterables.get(parsedPermissions, 0).getName());
381     }
382 
383     public void testPluginPermissions()
384     {
385         XmlDescriptorParser parser = parse(newApplication("my-other-app"),
386                 "<atlassian-plugin key='foo' plugins-version='2'>",
387                 "  <plugin-info>",
388                 "    <permissions>",
389                 "      <permission>some_permission</permission>",
390                 "      <permission application='my-app'>some_other_permission</permission>",
391                 "      <permission installation-mode='local'>yet_another_permission</permission>",
392                 "    </permissions>",
393                 "  </plugin-info>",
394                 "</atlassian-plugin>");
395 
396         final Set<PluginPermission> parsedPermissions = parser.getPluginInformation().getPermissions();
397         assertEquals(2, parsedPermissions.size());
398 
399         final PluginPermission firstPermission = Iterables.get(parsedPermissions, 0);
400         assertEquals("some_permission", firstPermission.getName());
401         assertEquals(null, firstPermission.getInstallationMode());
402 
403         final PluginPermission secondPermission = Iterables.get(parsedPermissions, 1);
404         assertEquals("yet_another_permission", secondPermission.getName());
405         assertEquals(InstallationMode.LOCAL, secondPermission.getInstallationMode());
406     }
407 
408     public void testPluginPermissionsIsEmptyForRemotablePluginByDefault()
409     {
410         XmlDescriptorParser parser = parse(null,
411                 "<atlassian-plugin key='foo' plugins-version='3'>",
412                 "  <plugin-info>",
413                 "  </plugin-info>",
414                 "</atlassian-plugin>");
415 
416         assertTrue(parser.getPluginInformation().getPermissions().isEmpty());
417     }
418 
419     private String getTestFile(String filename)
420     {
421         final URL url = ClassLoaderUtils.getResource(filename, this.getClass());
422         return url.getFile();
423     }
424 
425     private static XmlDescriptorParser parse(Application application, String... lines)
426     {
427         StringBuffer sb = new StringBuffer();
428         for (String line : lines)
429         {
430             sb.append(line.replace('\'', '"')).append('\n');
431         }
432         InputStream in = new ByteArrayInputStream(sb.toString().getBytes());
433         return application != null ? new XmlDescriptorParser(in, application) : new XmlDescriptorParser(in);
434     }
435 
436     private Application newApplication(final String appKey)
437     {
438         return newApplication(appKey, null);
439     }
440 
441     private Application newApplication(final String appKey, final String version)
442     {
443         return new Application()
444         {
445             @Override
446             public String getKey()
447             {
448                 return appKey;
449             }
450 
451             @Override
452             public String getVersion()
453             {
454                 return version;
455             }
456 
457             @Override
458             public String getBuildNumber()
459             {
460                 return null;
461             }
462         };
463     }
464 }