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