1   package com.atlassian.plugin.webresource;
2   
3   import java.util.Arrays;
4   import java.util.Collections;
5   import java.util.List;
6   import java.util.Map;
7   import java.util.TreeMap;
8   
9   import com.atlassian.plugin.util.PluginUtils;
10  import com.atlassian.plugin.webresource.transformer.WebResourceTransformer;
11  import com.atlassian.plugin.webresource.transformer.WebResourceTransformerModuleDescriptor;
12  import junit.framework.TestCase;
13  
14  import org.dom4j.DocumentHelper;
15  
16  import com.atlassian.plugin.ModuleDescriptor;
17  import com.atlassian.plugin.Plugin;
18  import com.atlassian.plugin.PluginAccessor;
19  import com.atlassian.plugin.elements.ResourceDescriptor;
20  import com.atlassian.plugin.elements.ResourceLocation;
21  import com.atlassian.plugin.servlet.DownloadableClasspathResource;
22  import com.atlassian.plugin.servlet.DownloadableResource;
23  import com.atlassian.plugin.servlet.ForwardableResource;
24  import com.atlassian.plugin.servlet.ServletContextFactory;
25  import com.mockobjects.dynamic.C;
26  import com.mockobjects.dynamic.Mock;
27  import org.dom4j.Element;
28  
29  import static org.mockito.Mockito.mock;
30  import static org.mockito.Mockito.when;
31  
32  public class TestPluginResourceLocatorImpl extends TestCase
33  {
34      private PluginResourceLocatorImpl pluginResourceLocator;
35      private Mock mockWebResourceIntegration;
36      private Mock mockPluginAccessor;
37      private Mock mockServletContextFactory;
38      private Mock mockBatchingConfiguration;
39  
40      private static final String TEST_PLUGIN_KEY = "test.plugin";
41      private static final String TEST_MODULE_KEY = "web-resources";
42      private static final String TEST_MODULE_COMPLETE_KEY = TEST_PLUGIN_KEY + ":" + TEST_MODULE_KEY;
43  
44      @Override
45      protected void setUp() throws Exception
46      {
47          super.setUp();
48  
49          mockPluginAccessor = new Mock(PluginAccessor.class);
50  
51          mockWebResourceIntegration = new Mock(WebResourceIntegration.class);
52          mockWebResourceIntegration.matchAndReturn("getPluginAccessor", mockPluginAccessor.proxy());
53          mockServletContextFactory = new Mock(ServletContextFactory.class);
54          mockBatchingConfiguration = new Mock(ResourceBatchingConfiguration.class);
55  
56          pluginResourceLocator = new PluginResourceLocatorImpl((WebResourceIntegration) mockWebResourceIntegration.proxy(), (ServletContextFactory) mockServletContextFactory
57              .proxy(), (ResourceBatchingConfiguration) mockBatchingConfiguration.proxy());
58      }
59  
60      @Override
61      protected void tearDown() throws Exception
62      {
63          pluginResourceLocator = null;
64          mockWebResourceIntegration = null;
65          mockPluginAccessor = null;
66          mockServletContextFactory = null;
67  
68          super.tearDown();
69      }
70  
71      public void testIsBatchingOff()
72      {
73          try
74          {
75              System.clearProperty(PluginResourceLocatorImpl.PLUGIN_WEBRESOURCE_BATCHING_OFF);
76              System.setProperty(PluginUtils.ATLASSIAN_DEV_MODE, "true");
77              assertTrue(pluginResourceLocator.isBatchingOff());
78  
79              System.setProperty(PluginResourceLocatorImpl.PLUGIN_WEBRESOURCE_BATCHING_OFF, "true");
80              System.clearProperty(PluginUtils.ATLASSIAN_DEV_MODE);
81              assertTrue(pluginResourceLocator.isBatchingOff());
82  
83              System.clearProperty(PluginResourceLocatorImpl.PLUGIN_WEBRESOURCE_BATCHING_OFF);
84              System.clearProperty(PluginUtils.ATLASSIAN_DEV_MODE);
85              assertFalse(pluginResourceLocator.isBatchingOff());
86  
87              System.clearProperty(PluginResourceLocatorImpl.PLUGIN_WEBRESOURCE_BATCHING_OFF);
88              System.setProperty(PluginUtils.ATLASSIAN_DEV_MODE, "false");
89              assertFalse(pluginResourceLocator.isBatchingOff());
90  
91              System.setProperty(PluginResourceLocatorImpl.PLUGIN_WEBRESOURCE_BATCHING_OFF, "false");
92              System.setProperty(PluginUtils.ATLASSIAN_DEV_MODE, "true");
93              assertFalse(pluginResourceLocator.isBatchingOff());
94          }
95          finally
96          {
97              System.clearProperty(PluginResourceLocatorImpl.PLUGIN_WEBRESOURCE_BATCHING_OFF);
98              System.clearProperty(PluginUtils.ATLASSIAN_DEV_MODE);
99          }
100     }
101 
102     public void testMatches()
103     {
104         assertTrue(pluginResourceLocator.matches("/download/superbatch/css/batch.css"));
105         assertTrue(pluginResourceLocator.matches("/download/superbatch/css/images/background/blah.gif"));
106         assertTrue(pluginResourceLocator.matches("/download/batch/plugin.key:module-key/plugin.key.js"));
107         assertTrue(pluginResourceLocator.matches("/download/resources/plugin.key:module-key/foo.png"));
108     }
109 
110     public void testNotMatches()
111     {
112         assertFalse(pluginResourceLocator.matches("/superbatch/batch.css"));
113         assertFalse(pluginResourceLocator.matches("/download/blah.css"));
114     }
115 
116     public void testGetAndParseUrl()
117     {
118         final String url = pluginResourceLocator.getResourceUrl("plugin.key:my-resources", "foo.css");
119         assertTrue(pluginResourceLocator.matches(url));
120     }
121 
122     public void testGetPluginResourcesWithoutBatching() throws Exception
123     {
124         final Mock mockPlugin = new Mock(Plugin.class);
125         mockPlugin.matchAndReturn("getPluginsVersion", 1);
126 
127         final List<ResourceDescriptor> resourceDescriptors = TestUtils.createResourceDescriptors("master-ie.css", "master.css", "comments.css");
128 
129         mockPluginAccessor.expectAndReturn("getEnabledPluginModule", C.args(C.eq(TEST_MODULE_COMPLETE_KEY)), TestUtils.createWebResourceModuleDescriptor(TEST_MODULE_COMPLETE_KEY,
130             (Plugin) mockPlugin.proxy(), resourceDescriptors));
131 
132         System.setProperty(PluginResourceLocatorImpl.PLUGIN_WEBRESOURCE_BATCHING_OFF, "true");
133         try
134         {
135             final List<PluginResource> resources = pluginResourceLocator.getPluginResources(TEST_MODULE_COMPLETE_KEY);
136             assertEquals(3, resources.size());
137             // ensure the resources still have their parameters
138             for (final PluginResource resource : resources)
139             {
140                 if (resource.getResourceName().contains("ie"))
141                 {
142                     assertEquals("true", resource.getParams().get("ieonly"));
143                 }
144                 else
145                 {
146                     assertNull(resource.getParams().get("ieonly"));
147                 }
148             }
149         }
150         finally
151         {
152             System.setProperty(PluginResourceLocatorImpl.PLUGIN_WEBRESOURCE_BATCHING_OFF, "false");
153         }
154     }
155 
156     public void testGetPluginResourcesWithBatching() throws Exception
157     {
158         final Mock mockPlugin = new Mock(Plugin.class);
159         mockPlugin.matchAndReturn("getPluginsVersion", 1);
160 
161         final List<ResourceDescriptor> resourceDescriptors = TestUtils.createResourceDescriptors("master-ie.css", "master.css", "comments.css");
162 
163         mockPluginAccessor.expectAndReturn("getEnabledPluginModule", C.args(C.eq(TEST_MODULE_COMPLETE_KEY)), TestUtils.createWebResourceModuleDescriptor(TEST_MODULE_COMPLETE_KEY,
164             (Plugin) mockPlugin.proxy(), resourceDescriptors));
165 
166         final List<PluginResource> resources = pluginResourceLocator.getPluginResources(TEST_MODULE_COMPLETE_KEY);
167         assertEquals(2, resources.size());
168 
169         final BatchPluginResource ieBatch = (BatchPluginResource) resources.get(0);
170         assertEquals(TEST_MODULE_COMPLETE_KEY, ieBatch.getModuleCompleteKey());
171         assertEquals("css", ieBatch.getType());
172         assertEquals(1, ieBatch.getParams().size());
173         assertEquals("true", ieBatch.getParams().get("ieonly"));
174 
175         final BatchPluginResource batch = (BatchPluginResource) resources.get(1);
176         assertEquals(TEST_MODULE_COMPLETE_KEY, batch.getModuleCompleteKey());
177         assertEquals("css", batch.getType());
178         assertEquals(0, batch.getParams().size());
179     }
180 
181     public void testGetPluginResourcesWithBatchParameter() throws Exception
182     {
183         final Mock mockPlugin = new Mock(Plugin.class);
184         mockPlugin.matchAndReturn("getPluginsVersion", 1);
185 
186         final List<ResourceDescriptor> resourceDescriptors = TestUtils.createResourceDescriptors("master.css", "comments.css");
187         final Map<String, String> nonBatchParams = new TreeMap<String, String>();
188         nonBatchParams.put("batch", "false");
189         resourceDescriptors.add(TestUtils.createResourceDescriptor("nonbatch.css", nonBatchParams));
190 
191         mockPluginAccessor.expectAndReturn("getEnabledPluginModule", C.args(C.eq(TEST_MODULE_COMPLETE_KEY)), TestUtils.createWebResourceModuleDescriptor(TEST_MODULE_COMPLETE_KEY,
192             (Plugin) mockPlugin.proxy(), resourceDescriptors));
193 
194         final List<PluginResource> resources = pluginResourceLocator.getPluginResources(TEST_MODULE_COMPLETE_KEY);
195         assertEquals(2, resources.size());
196 
197         final BatchPluginResource batch = (BatchPluginResource) resources.get(0);
198         assertEquals(TEST_MODULE_COMPLETE_KEY, batch.getModuleCompleteKey());
199         assertEquals("css", batch.getType());
200         assertEquals(0, batch.getParams().size());
201 
202         final SinglePluginResource single = (SinglePluginResource) resources.get(1);
203         assertEquals(TEST_MODULE_COMPLETE_KEY, single.getModuleCompleteKey());
204     }
205 
206     public void testGetPluginResourcesWithForwarding() throws Exception
207     {
208         final Mock mockPlugin = new Mock(Plugin.class);
209         mockPlugin.matchAndReturn("getPluginsVersion", 1);
210 
211         final List<ResourceDescriptor> resourceDescriptors = TestUtils.createResourceDescriptors("master.css", "comments.css");
212         final Map<String, String> params = new TreeMap<String, String>();
213         params.put("source", "webContext");
214         resourceDescriptors.add(TestUtils.createResourceDescriptor("forward.css", params));
215 
216         mockPluginAccessor.expectAndReturn("getEnabledPluginModule", C.args(C.eq(TEST_MODULE_COMPLETE_KEY)), TestUtils.createWebResourceModuleDescriptor(TEST_MODULE_COMPLETE_KEY,
217             (Plugin) mockPlugin.proxy(), resourceDescriptors));
218 
219         final List<PluginResource> resources = pluginResourceLocator.getPluginResources(TEST_MODULE_COMPLETE_KEY);
220         assertEquals(2, resources.size());
221 
222         final BatchPluginResource batch = (BatchPluginResource) resources.get(0);
223         assertEquals(TEST_MODULE_COMPLETE_KEY, batch.getModuleCompleteKey());
224         assertEquals("css", batch.getType());
225         assertEquals(0, batch.getParams().size());
226 
227         final SinglePluginResource single = (SinglePluginResource) resources.get(1);
228         assertEquals(TEST_MODULE_COMPLETE_KEY, single.getModuleCompleteKey());
229     }
230 
231     public void testGetForwardableResource() throws Exception
232     {
233         final String resourceName = "test.css";
234         final String url = "/download/resources/" + TEST_MODULE_COMPLETE_KEY + "/" + resourceName;
235         final Map<String, String> params = new TreeMap<String, String>();
236         params.put("source", "webContext");
237 
238         final Mock mockPlugin = new Mock(Plugin.class);
239         final Mock mockModuleDescriptor = new Mock(ModuleDescriptor.class);
240         mockModuleDescriptor.expectAndReturn("getPluginKey", TEST_PLUGIN_KEY);
241         mockModuleDescriptor.expectAndReturn("getResourceLocation", C.args(C.eq("download"), C.eq(resourceName)), new ResourceLocation("", resourceName, "download", "text/css",
242             "", params));
243 
244         mockPluginAccessor.expectAndReturn("getEnabledPluginModule", C.args(C.eq(TEST_MODULE_COMPLETE_KEY)), mockModuleDescriptor.proxy());
245         mockPluginAccessor.expectAndReturn("getPlugin", C.args(C.eq(TEST_PLUGIN_KEY)), mockPlugin.proxy());
246 
247         final DownloadableResource resource = pluginResourceLocator.getDownloadableResource(url, Collections.EMPTY_MAP);
248 
249         assertTrue(resource instanceof ForwardableResource);
250     }
251 
252     public void testGetDownloadableClasspathResource() throws Exception
253     {
254         final String resourceName = "test.css";
255         final String url = "/download/resources/" + TEST_MODULE_COMPLETE_KEY + "/" + resourceName;
256 
257         final Mock mockPlugin = new Mock(Plugin.class);
258         final Mock mockModuleDescriptor = new Mock(ModuleDescriptor.class);
259         mockModuleDescriptor.expectAndReturn("getPluginKey", TEST_PLUGIN_KEY);
260         mockModuleDescriptor.expectAndReturn("getResourceLocation", C.args(C.eq("download"), C.eq(resourceName)), new ResourceLocation("", resourceName, "download", "text/css",
261             "", Collections.EMPTY_MAP));
262 
263         mockPluginAccessor.expectAndReturn("getEnabledPluginModule", C.args(C.eq(TEST_MODULE_COMPLETE_KEY)), mockModuleDescriptor.proxy());
264         mockPluginAccessor.expectAndReturn("getPlugin", C.args(C.eq(TEST_PLUGIN_KEY)), mockPlugin.proxy());
265 
266         final DownloadableResource resource = pluginResourceLocator.getDownloadableResource(url, Collections.EMPTY_MAP);
267 
268         assertTrue(resource instanceof DownloadableClasspathResource);
269     }
270 
271     public void testGetTransformedDownloadableClasspathResource() throws Exception
272     {
273         final String resourceName = "test.js";
274         final String url = "/download/resources/" + TEST_MODULE_COMPLETE_KEY + "/" + resourceName;
275 
276         final DownloadableResource transformedResource = mock(DownloadableResource.class);
277         WebResourceTransformation trans = new WebResourceTransformation(DocumentHelper.parseText(
278                 "<transformation extension=\"js\">\n" +
279                     "<transformer key=\"foo\" />\n" +
280                 "</transformation>").getRootElement());
281         WebResourceTransformer transformer = new WebResourceTransformer()
282         {
283             public DownloadableResource transform(Element configElement, ResourceLocation location, String filePath, DownloadableResource nextResource) {
284                 return transformedResource;
285             }
286         };
287 
288         WebResourceTransformerModuleDescriptor transDescriptor = mock(WebResourceTransformerModuleDescriptor.class);
289         when(transDescriptor.getKey()).thenReturn("foo");
290         when(transDescriptor.getModule()).thenReturn(transformer);
291 
292         final Mock mockPlugin = new Mock(Plugin.class);
293         WebResourceModuleDescriptor descriptor = mock(WebResourceModuleDescriptor.class);
294         when(descriptor.getPluginKey()).thenReturn(TEST_PLUGIN_KEY);
295         when(descriptor.getResourceLocation("download", resourceName)).thenReturn(new ResourceLocation("", resourceName, "download", "text/css",
296             "", Collections.EMPTY_MAP));
297         when(descriptor.getTransformations()).thenReturn(Arrays.asList(trans));
298 
299         mockPluginAccessor.expectAndReturn("getEnabledModuleDescriptorsByClass", C.args(C.eq(WebResourceTransformerModuleDescriptor.class)), Arrays.asList(transDescriptor));
300         mockPluginAccessor.expectAndReturn("getEnabledPluginModule", C.args(C.eq(TEST_MODULE_COMPLETE_KEY)), descriptor);
301         mockPluginAccessor.expectAndReturn("getPlugin", C.args(C.eq(TEST_PLUGIN_KEY)), mockPlugin.proxy());
302 
303         final DownloadableResource resource = pluginResourceLocator.getDownloadableResource(url, Collections.EMPTY_MAP);
304 
305         assertTrue(resource == transformedResource);
306     }
307 
308     public void testGetUnmatchedTransformDownloadableClasspathResource() throws Exception
309     {
310         final String resourceName = "test.css";
311         final String url = "/download/resources/" + TEST_MODULE_COMPLETE_KEY + "/" + resourceName;
312 
313         final DownloadableResource transformedResource = mock(DownloadableResource.class);
314         WebResourceTransformation trans = new WebResourceTransformation(DocumentHelper.parseText(
315                 "<transformation extension=\"js\">\n" +
316                     "<transformer key=\"foo\" />\n" +
317                 "</transformation>").getRootElement());
318         WebResourceTransformer transformer = new WebResourceTransformer()
319         {
320             public DownloadableResource transform(Element configElement, ResourceLocation location, String extraPath, DownloadableResource nextResource) {
321                 return transformedResource;
322             }
323         };
324 
325         WebResourceTransformerModuleDescriptor transDescriptor = mock(WebResourceTransformerModuleDescriptor.class);
326         when(transDescriptor.getKey()).thenReturn("foo");
327         when(transDescriptor.getModule()).thenReturn(transformer);
328 
329         final Mock mockPlugin = new Mock(Plugin.class);
330         WebResourceModuleDescriptor descriptor = mock(WebResourceModuleDescriptor.class);
331         when(descriptor.getPluginKey()).thenReturn(TEST_PLUGIN_KEY);
332         when(descriptor.getResourceLocation("download", resourceName)).thenReturn(new ResourceLocation("", resourceName, "download", "text/css",
333             "", Collections.EMPTY_MAP));
334         when(descriptor.getTransformations()).thenReturn(Arrays.asList(trans));
335 
336         mockPluginAccessor.expectAndReturn("getEnabledModuleDescriptorsByClass", C.args(C.eq(WebResourceTransformerModuleDescriptor.class)), Arrays.asList(transDescriptor));
337         mockPluginAccessor.expectAndReturn("getEnabledPluginModule", C.args(C.eq(TEST_MODULE_COMPLETE_KEY)), descriptor);
338         mockPluginAccessor.expectAndReturn("getPlugin", C.args(C.eq(TEST_PLUGIN_KEY)), mockPlugin.proxy());
339 
340         final DownloadableResource resource = pluginResourceLocator.getDownloadableResource(url, Collections.EMPTY_MAP);
341 
342         assertTrue(resource instanceof DownloadableClasspathResource);
343     }
344 
345     public void testGetMissingTransformerDownloadableClasspathResource() throws Exception
346     {
347         final String resourceName = "test.css";
348         final String url = "/download/resources/" + TEST_MODULE_COMPLETE_KEY + "/" + resourceName;
349 
350         final DownloadableResource transformedResource = mock(DownloadableResource.class);
351         WebResourceTransformation trans = new WebResourceTransformation(DocumentHelper.parseText(
352                 "<transformation extension=\"js\">\n" +
353                     "<transformer key=\"foo\" />\n" +
354                 "</transformation>").getRootElement());
355         WebResourceTransformer transformer = new WebResourceTransformer()
356         {
357             public DownloadableResource transform(Element configElement, ResourceLocation location, String extraPath, DownloadableResource nextResource) {
358                 return transformedResource;
359             }
360         };
361 
362         WebResourceTransformerModuleDescriptor transDescriptor = mock(WebResourceTransformerModuleDescriptor.class);
363         when(transDescriptor.getKey()).thenReturn("bar");
364         when(transDescriptor.getModule()).thenReturn(transformer);
365 
366         final Mock mockPlugin = new Mock(Plugin.class);
367         WebResourceModuleDescriptor descriptor = mock(WebResourceModuleDescriptor.class);
368         when(descriptor.getPluginKey()).thenReturn(TEST_PLUGIN_KEY);
369         when(descriptor.getResourceLocation("download", resourceName)).thenReturn(new ResourceLocation("", resourceName, "download", "text/css",
370             "", Collections.EMPTY_MAP));
371         when(descriptor.getTransformations()).thenReturn(Arrays.asList(trans));
372 
373         mockPluginAccessor.expectAndReturn("getEnabledModuleDescriptorsByClass", C.args(C.eq(WebResourceTransformerModuleDescriptor.class)), Arrays.asList(transDescriptor));
374         mockPluginAccessor.expectAndReturn("getEnabledPluginModule", C.args(C.eq(TEST_MODULE_COMPLETE_KEY)), descriptor);
375         mockPluginAccessor.expectAndReturn("getPlugin", C.args(C.eq(TEST_PLUGIN_KEY)), mockPlugin.proxy());
376 
377         final DownloadableResource resource = pluginResourceLocator.getDownloadableResource(url, Collections.EMPTY_MAP);
378 
379         assertTrue(resource instanceof DownloadableClasspathResource);
380     }
381 
382     public void testGetDownloadableBatchResource() throws Exception
383     {
384         final String url = "/download/batch/" + TEST_MODULE_COMPLETE_KEY + "/all.css";
385         final String ieResourceName = "master-ie.css";
386         final Map<String, String> params = new TreeMap<String, String>();
387         params.put("ieonly", "true");
388 
389         final List<ResourceDescriptor> resourceDescriptors = TestUtils.createResourceDescriptors(ieResourceName, "master.css");
390 
391         final Mock mockPlugin = new Mock(Plugin.class);
392         final Mock mockModuleDescriptor = new Mock(ModuleDescriptor.class);
393         mockModuleDescriptor.expectAndReturn("getPluginKey", TEST_PLUGIN_KEY);
394         mockModuleDescriptor.expectAndReturn("getCompleteKey", TEST_MODULE_COMPLETE_KEY);
395         mockModuleDescriptor.expectAndReturn("getResourceDescriptors", resourceDescriptors);
396         mockModuleDescriptor.expectAndReturn("getResourceLocation", C.args(C.eq("download"), C.eq(ieResourceName)), new ResourceLocation("", ieResourceName, "download",
397             "text/css", "", Collections.EMPTY_MAP));
398 
399         mockPluginAccessor.matchAndReturn("isPluginModuleEnabled", C.args(C.eq(TEST_MODULE_COMPLETE_KEY)), Boolean.TRUE);
400         mockPluginAccessor.matchAndReturn("getEnabledPluginModule", C.args(C.eq(TEST_MODULE_COMPLETE_KEY)), mockModuleDescriptor.proxy());
401         mockPluginAccessor.matchAndReturn("getPluginModule", C.args(C.eq(TEST_MODULE_COMPLETE_KEY)), mockModuleDescriptor.proxy());
402         mockPluginAccessor.matchAndReturn("getPlugin", C.args(C.eq(TEST_PLUGIN_KEY)), mockPlugin.proxy());
403 
404         final DownloadableResource resource = pluginResourceLocator.getDownloadableResource(url, params);
405 
406         assertTrue(resource instanceof BatchPluginResource);
407     }
408 
409     public void testGetDownloadableBatchResourceFallbacksToSingle() throws Exception
410     {
411         final String resourceName = "images/foo.png";
412         final String url = "/download/batch/" + TEST_MODULE_COMPLETE_KEY + "/" + resourceName;
413 
414         final Mock mockPlugin = new Mock(Plugin.class);
415         final Mock mockModuleDescriptor = new Mock(ModuleDescriptor.class);
416         mockModuleDescriptor.expectAndReturn("getPluginKey", TEST_PLUGIN_KEY);
417         mockModuleDescriptor.expectAndReturn("getCompleteKey", TEST_MODULE_COMPLETE_KEY);
418         mockModuleDescriptor.expectAndReturn("getResourceDescriptors", Collections.EMPTY_LIST);
419         mockModuleDescriptor.expectAndReturn("getResourceLocation", C.args(C.eq("download"), C.eq(resourceName)), new ResourceLocation("", resourceName, "download", "text/css",
420             "", Collections.EMPTY_MAP));
421 
422         mockPluginAccessor.matchAndReturn("isPluginModuleEnabled", C.args(C.eq(TEST_MODULE_COMPLETE_KEY)), Boolean.TRUE);
423         mockPluginAccessor.matchAndReturn("getEnabledPluginModule", C.args(C.eq(TEST_MODULE_COMPLETE_KEY)), mockModuleDescriptor.proxy());
424         mockPluginAccessor.matchAndReturn("getPluginModule", C.args(C.eq(TEST_MODULE_COMPLETE_KEY)), mockModuleDescriptor.proxy());
425         mockPluginAccessor.matchAndReturn("getPlugin", C.args(C.eq(TEST_PLUGIN_KEY)), mockPlugin.proxy());
426 
427         final DownloadableResource resource = pluginResourceLocator.getDownloadableResource(url, Collections.EMPTY_MAP);
428 
429         assertTrue(resource instanceof DownloadableClasspathResource);
430     }
431 
432     public void testGetDownloadableSuperBatchResource() throws Exception
433     {
434         final String url = "/download/superbatch/css/batch.css";
435 
436         final Plugin testPlugin = TestUtils.createTestPlugin(TEST_PLUGIN_KEY, "1");
437         final List<ResourceDescriptor> resourceDescriptors = TestUtils.createResourceDescriptors("atlassian.css", "master.css");
438 
439         final WebResourceModuleDescriptor webModuleDescriptor = TestUtils.createWebResourceModuleDescriptor(TEST_MODULE_COMPLETE_KEY, testPlugin, resourceDescriptors);
440 
441         mockWebResourceIntegration.expectAndReturn("getSuperBatchVersion", "1.0");
442         mockBatchingConfiguration.expectAndReturn("isSuperBatchingEnabled", true);
443         mockBatchingConfiguration.matchAndReturn("getSuperBatchModuleCompleteKeys", Arrays.asList(TEST_MODULE_COMPLETE_KEY));
444 
445         mockPluginAccessor.matchAndReturn("getEnabledPluginModule", C.args(C.eq(TEST_MODULE_COMPLETE_KEY)), webModuleDescriptor);
446         mockPluginAccessor.matchAndReturn("getPlugin", C.args(C.eq(TEST_PLUGIN_KEY)), testPlugin);
447 
448         final DownloadableResource resource = pluginResourceLocator.getDownloadableResource(url, Collections.<String, String> emptyMap());
449         assertTrue(resource instanceof SuperBatchPluginResource);
450 
451         final SuperBatchPluginResource superBatchPluginResource = (SuperBatchPluginResource) resource;
452         assertFalse(superBatchPluginResource.isEmpty());
453     }
454 
455     public void testGetDownloadableSuperBatchSubResource() throws Exception
456     {
457         final String url = "/download/superbatch/css/images/foo.png";
458         final String cssResourcesXml = "<resource name=\"css/\" type=\"download\" location=\"css/images/\" />";
459 
460         final List<ResourceDescriptor> resourceDescriptors = TestUtils.createResourceDescriptors("atlassian.css", "master.css");
461         resourceDescriptors.add(new ResourceDescriptor(DocumentHelper.parseText(cssResourcesXml).getRootElement()));
462 
463         final Plugin testPlugin = TestUtils.createTestPlugin(TEST_PLUGIN_KEY, "1");
464         final WebResourceModuleDescriptor webModuleDescriptor = TestUtils.createWebResourceModuleDescriptor(TEST_MODULE_COMPLETE_KEY, testPlugin, resourceDescriptors);
465 
466         mockWebResourceIntegration.expectAndReturn("getSuperBatchVersion", "1.0");
467         mockBatchingConfiguration.expectAndReturn("isSuperBatchingEnabled", true);
468         mockBatchingConfiguration.matchAndReturn("getSuperBatchModuleCompleteKeys", Arrays.asList(TEST_MODULE_COMPLETE_KEY));
469 
470         mockPluginAccessor.matchAndReturn("getEnabledPluginModule", C.args(C.eq(TEST_MODULE_COMPLETE_KEY)), webModuleDescriptor);
471         mockPluginAccessor.matchAndReturn("getPlugin", C.args(C.eq(TEST_PLUGIN_KEY)), testPlugin);
472 
473         final DownloadableResource resource = pluginResourceLocator.getDownloadableResource(url, Collections.<String, String> emptyMap());
474         assertTrue(resource instanceof DownloadableClasspathResource);
475     }
476 
477     public void testSplitLastPathPart()
478     {
479         final String[] parts = pluginResourceLocator.splitLastPathPart("http://localhost:8080/confluence/download/foo/bar/baz");
480         assertEquals(2, parts.length);
481         assertEquals("http://localhost:8080/confluence/download/foo/bar/", parts[0]);
482         assertEquals("baz", parts[1]);
483 
484         final String[] anotherParts = pluginResourceLocator.splitLastPathPart(parts[0]);
485         assertEquals(2, anotherParts.length);
486         assertEquals("http://localhost:8080/confluence/download/foo/", anotherParts[0]);
487         assertEquals("bar/", anotherParts[1]);
488 
489         assertNull(pluginResourceLocator.splitLastPathPart("noslashes"));
490     }
491 }