View Javadoc

1   /*
2    * Created by IntelliJ IDEA.
3    * User: Mike
4    * Date: Jul 29, 2004
5    * Time: 4:28:18 PM
6    */
7   package com.atlassian.plugin.descriptors;
8   
9   import java.util.List;
10  import java.util.Set;
11  import java.util.concurrent.atomic.AtomicBoolean;
12  
13  import com.atlassian.plugin.ModuleDescriptor;
14  import com.atlassian.plugin.ModulePermissionException;
15  import com.atlassian.plugin.Permissions;
16  import com.atlassian.plugin.Plugin;
17  import com.atlassian.plugin.PluginParseException;
18  import com.atlassian.plugin.RequirePermission;
19  import com.atlassian.plugin.StateAware;
20  import com.atlassian.plugin.elements.ResourceDescriptor;
21  import com.atlassian.plugin.impl.StaticPlugin;
22  import com.atlassian.plugin.mock.MockAnimal;
23  import com.atlassian.plugin.mock.MockAnimalModuleDescriptor;
24  import com.atlassian.plugin.mock.MockMineral;
25  import com.atlassian.plugin.module.ModuleFactory;
26  import com.atlassian.plugin.util.ClassLoaderUtils;
27  
28  import com.google.common.collect.ImmutableSet;
29  
30  import org.dom4j.DocumentException;
31  import org.dom4j.DocumentHelper;
32  import org.dom4j.Element;
33  import org.junit.Test;
34  
35  import static org.junit.Assert.assertEquals;
36  import static org.junit.Assert.assertNotNull;
37  import static org.junit.Assert.assertNull;
38  import static org.junit.Assert.assertSame;
39  import static org.junit.Assert.assertTrue;
40  import static org.junit.Assert.fail;
41  import static org.mockito.Mockito.mock;
42  import static org.mockito.Mockito.never;
43  import static org.mockito.Mockito.spy;
44  import static org.mockito.Mockito.verify;
45  import static org.mockito.Mockito.when;
46  
47  public class TestAbstractModuleDescriptor
48  {
49      public static final String ANNOTATION_PERMISSION = "annotation_permission";
50  
51      @Test
52      public void testAssertModuleClassImplements() throws DocumentException, PluginParseException
53      {
54          ModuleDescriptor descriptor = new AbstractModuleDescriptor(ModuleFactory.LEGACY_MODULE_FACTORY) {
55              public void init(Plugin plugin, Element element) throws PluginParseException
56              {
57                  super.init(plugin, element);
58                  enabled();
59                  assertModuleClassImplements(MockMineral.class);
60              }
61  
62              public Object getModule()
63              {
64                  return null;
65              }
66          };
67  
68          try
69          {
70              descriptor.init(new StaticPlugin(), DocumentHelper.parseText("<animal key=\"key\" name=\"bear\" class=\"com.atlassian.plugin.mock.MockBear\" />").getRootElement());
71              ((StateAware)descriptor).enabled();
72              fail("Should have blown up.");
73          }
74          catch (PluginParseException e)
75          {
76              assertEquals("Given module class: com.atlassian.plugin.mock.MockBear does not implement com.atlassian.plugin.mock.MockMineral", e.getMessage());
77          }
78  
79          // now succeed
80          descriptor.init(new StaticPlugin(), DocumentHelper.parseText("<animal key=\"key\" name=\"bear\" class=\"com.atlassian.plugin.mock.MockGold\" />").getRootElement());
81      }
82  
83      @Test
84      public void testLoadClassFromNewModuleFactory()
85      {
86          ModuleFactory moduleFactory = mock(ModuleFactory.class);
87          AbstractModuleDescriptor moduleDescriptor = new StringModuleDescriptor(moduleFactory, "foo");
88          Plugin plugin = mock(Plugin.class);
89          moduleDescriptor.loadClass(plugin, "foo");
90          assertEquals(String.class, moduleDescriptor.getModuleClass());
91      }
92  
93      @Test
94      public void testLoadClassFromNewModuleFactoryWithExtendsNumberType()
95      {
96          ModuleFactory moduleFactory = mock(ModuleFactory.class);
97          AbstractModuleDescriptor moduleDescriptor = new ExtendsNumberModuleDescriptor(moduleFactory, "foo");
98          Plugin plugin = mock(Plugin.class);
99  
100         try
101         {
102             moduleDescriptor.loadClass(plugin, "foo");
103             fail("Should have complained about extends type");
104         }
105         catch (IllegalStateException ex)
106         {
107             // success
108         }
109     }
110 
111     @Test
112     public void testLoadClassFromNewModuleFactoryWithExtendsNothingType()
113     {
114         ModuleFactory moduleFactory = mock(ModuleFactory.class);
115         AbstractModuleDescriptor moduleDescriptor = new ExtendsNothingModuleDescriptor(moduleFactory, "foo");
116         Plugin plugin = mock(Plugin.class);
117 
118         try
119         {
120             moduleDescriptor.loadClass(plugin, "foo");
121             fail("Should have complained about extends type");
122         }
123         catch (IllegalStateException ex)
124         {
125             // success
126         }
127     }
128 
129     @Test
130     public void testGetModuleReturnClass()
131     {
132         AbstractModuleDescriptor desc = new MockAnimalModuleDescriptor();
133         assertEquals(MockAnimal.class, desc.getModuleReturnClass());
134     }
135 
136     @Test
137     public void testGetModuleReturnClassWithExtendsNumber()
138     {
139         ModuleFactory moduleFactory = mock(ModuleFactory.class);
140         AbstractModuleDescriptor moduleDescriptor = new ExtendsNothingModuleDescriptor(moduleFactory, "foo");
141         assertEquals(Object.class, moduleDescriptor.getModuleReturnClass());
142     }
143 
144     @Test
145     public void testLoadClassFromNewModuleFactoryButUnknownType()
146     {
147         ModuleFactory moduleFactory = mock(ModuleFactory.class);
148         AbstractModuleDescriptor moduleDescriptor = new AbstractModuleDescriptor(moduleFactory)
149         {
150             public AbstractModuleDescriptor init()
151             {
152                 moduleClassName = "foo";
153                 return this;
154             }
155 
156             @Override
157             public Object getModule()
158             {
159                 return null;
160             }
161         }.init();
162         try
163         {
164             Plugin plugin = mock(Plugin.class);
165             moduleDescriptor.loadClass(plugin, "foo");
166             fail("Should have complained about unknown type");
167         }
168         catch (IllegalStateException ex)
169         {
170             // success
171         }
172     }
173 
174     @Test
175     public void testSingletonness() throws DocumentException, PluginParseException
176     {
177         ModuleDescriptor descriptor = makeSingletonDescriptor();
178 
179         // try a default descriptor with no singleton="" element. Should _be_ a singleton
180         descriptor.init(new StaticPlugin(), DocumentHelper.parseText("<animal key=\"key\" name=\"bear\" class=\"com.atlassian.plugin.mock.MockBear\" />").getRootElement());
181         ((StateAware)descriptor).enabled();
182         Object module = descriptor.getModule();
183         assertTrue(module == descriptor.getModule());
184 
185         // now try a default descriptor with singleton="true" element. Should still be a singleton
186         descriptor = makeSingletonDescriptor();
187         descriptor.init(new StaticPlugin(), DocumentHelper.parseText("<animal key=\"key\" name=\"bear\" class=\"com.atlassian.plugin.mock.MockBear\" singleton=\"true\" />").getRootElement());
188         ((StateAware)descriptor).enabled();
189         module = descriptor.getModule();
190         assertTrue(module == descriptor.getModule());
191 
192         // now try reiniting as a non-singleton
193         descriptor = makeSingletonDescriptor();
194         descriptor.init(new StaticPlugin(), DocumentHelper.parseText("<animal key=\"key\" name=\"bear\" class=\"com.atlassian.plugin.mock.MockBear\" singleton=\"false\" />").getRootElement());
195         ((StateAware)descriptor).enabled();
196         module = descriptor.getModule();
197         assertTrue(module != descriptor.getModule());
198     }
199 
200     @Test
201     public void testGetResourceDescriptor() throws DocumentException, PluginParseException
202     {
203         ModuleDescriptor descriptor = makeSingletonDescriptor();
204         descriptor.init(new StaticPlugin(), DocumentHelper.parseText("<animal key=\"key\" name=\"bear\" class=\"com.atlassian.plugin.mock.MockBear\">" +
205                 "<resource type='velocity' name='view' location='foo' />" +
206                 "</animal>").getRootElement());
207 
208         assertNull(descriptor.getResourceLocation("foo", "bar"));
209         assertNull(descriptor.getResourceLocation("velocity", "bar"));
210         assertNull(descriptor.getResourceLocation("foo", "view"));
211         assertEquals(new ResourceDescriptor(DocumentHelper.parseText("<resource type='velocity' name='view' location='foo' />").getRootElement()).getResourceLocationForName("view").getLocation(), descriptor.getResourceLocation("velocity", "view").getLocation());
212     }
213 
214     @Test
215     public void testGetResourceDescriptorByType() throws DocumentException, PluginParseException
216     {
217         ModuleDescriptor descriptor = makeSingletonDescriptor();
218         descriptor.init(new StaticPlugin(), DocumentHelper.parseText("<animal key=\"key\" name=\"bear\" class=\"com.atlassian.plugin.mock.MockBear\">" +
219                 "<resource type='velocity' name='view' location='foo' />" +
220                 "<resource type='velocity' name='input-params' location='bar' />" +
221                 "</animal>").getRootElement());
222 
223         final List resourceDescriptors = descriptor.getResourceDescriptors("velocity");
224         assertNotNull(resourceDescriptors);
225         assertEquals(2, resourceDescriptors.size());
226 
227         ResourceDescriptor resourceDescriptor = (ResourceDescriptor) resourceDescriptors.get(0);
228         assertEquals(new ResourceDescriptor(DocumentHelper.parseText("<resource type='velocity' name='view' location='foo' />").getRootElement()), resourceDescriptor);
229 
230         resourceDescriptor = (ResourceDescriptor) resourceDescriptors.get(1);
231         assertEquals(new ResourceDescriptor(DocumentHelper.parseText("<resource type='velocity' name='input-params' location='bar' />").getRootElement()), resourceDescriptor);
232     }
233 
234     @Test
235     public void testDestroy()
236     {
237         AbstractModuleDescriptor descriptor = spy(new StringModuleDescriptor(ModuleFactory.LEGACY_MODULE_FACTORY, null));
238         Plugin plugin = mock(Plugin.class);
239         descriptor.setPlugin(plugin);
240         // enable the module descriptor first; otherwise, disabled() won't be called from destroy()
241         descriptor.enabled();
242 
243         descriptor.destroy();
244 
245         verify(descriptor).disabled();
246         assertSame(plugin, descriptor.getPlugin());
247     }
248 
249     @Test
250     public void testDestroyWhenDisabled()
251     {
252         AbstractModuleDescriptor descriptor = spy(new StringModuleDescriptor(ModuleFactory.LEGACY_MODULE_FACTORY, null));
253         Plugin plugin = mock(Plugin.class);
254         descriptor.setPlugin(plugin);
255 
256         descriptor.destroy();
257 
258         // it's never enabled, so disabled() won't be called
259         verify(descriptor, never()).disabled();
260         assertSame(plugin, descriptor.getPlugin());
261     }
262 
263     @Test
264     public void testDestroyDelegatesToDeprecatedOverride()
265     {
266         final AtomicBoolean called = new AtomicBoolean();
267 
268         AbstractModuleDescriptor descriptor = new StringModuleDescriptor(ModuleFactory.LEGACY_MODULE_FACTORY, null) {
269             @Override
270             @Deprecated
271             public void destroy(Plugin plugin)
272             {
273                 called.set(true);
274             }
275         };
276 
277         Plugin plugin = mock(Plugin.class);
278         descriptor.setPlugin(plugin);
279 
280         descriptor.destroy();
281 
282         assertTrue(called.get());
283     }
284 
285     @Test
286     public void testCheckPermissionsForModuleDescriptorAndPluginDefinedWithNoPermission()
287     {
288         final AbstractModuleDescriptor moduleDescriptor = makeSingletonDescriptor();
289         moduleDescriptor.setPlugin(mock(Plugin.class));
290 
291         try
292         {
293             moduleDescriptor.checkPermissions();
294         }
295         catch (ModulePermissionException e)
296         {
297             fail("Didn't expected the exception here" + e);
298         }
299     }
300 
301     @Test
302     public void testCheckPermissionsForModuleDescriptorAndPluginWithSamePermission()
303     {
304         final String somePermission = "some_permission";
305         final AbstractModuleDescriptor moduleDescriptor = new StringModuleDescriptor(ModuleFactory.LEGACY_MODULE_FACTORY, this.getClass().getName()) {
306             @Override
307             protected Set<String> getRequiredPermissions()
308             {
309                 return ImmutableSet.of(somePermission);
310             }
311         };
312 
313         final Plugin plugin = mock(Plugin.class);
314         moduleDescriptor.setPlugin(plugin);
315         when(plugin.getActivePermissions()).thenReturn(ImmutableSet.of(somePermission, ANNOTATION_PERMISSION));
316 
317         try
318         {
319             moduleDescriptor.checkPermissions();
320         }
321         catch (ModulePermissionException e)
322         {
323             fail("Didn't expected the exception here" + e);
324         }
325     }
326 
327     @Test
328     public void testCheckPermissionsForModuleDescriptorWithPermissionsAndPluginWithAllPermission()
329     {
330         final Set<String> permissions = ImmutableSet.of("some_permission");
331         final AbstractModuleDescriptor moduleDescriptor = new StringModuleDescriptor(ModuleFactory.LEGACY_MODULE_FACTORY, this.getClass().getName()) {
332             @Override
333             protected Set<String> getRequiredPermissions()
334             {
335                 return permissions;
336             }
337         };
338 
339         final Plugin plugin = mock(Plugin.class);
340         moduleDescriptor.setPlugin(plugin);
341         when(plugin.hasAllPermissions()).thenReturn(true);
342         when(plugin.getActivePermissions()).thenReturn(ImmutableSet.of(Permissions.ALL_PERMISSIONS));
343 
344         try
345         {
346             moduleDescriptor.checkPermissions();
347         }
348         catch (ModulePermissionException e)
349         {
350             fail("Didn't expected the exception here" + e);
351         }
352     }
353 
354     @Test
355     public void testCheckPermissionsForModuleDescriptorWithPermissionsNotInPluginPermissions()
356     {
357         final Set<String> permissions = ImmutableSet.of("some_module_permission", "one_plugin_permission");
358         final AbstractModuleDescriptor moduleDescriptor = new StringModuleDescriptor(ModuleFactory.LEGACY_MODULE_FACTORY, this.getClass().getName()) {
359             @Override
360             protected Set<String> getRequiredPermissions()
361             {
362                 return permissions;
363             }
364         };
365 
366         final Plugin plugin = mock(Plugin.class);
367         moduleDescriptor.setPlugin(plugin);
368         ImmutableSet<String> pluginPermissions = ImmutableSet.of("one_plugin_permission", "two_plugin_permission", ANNOTATION_PERMISSION);
369         when(plugin.getActivePermissions()).thenReturn(pluginPermissions);
370 
371         try
372         {
373             moduleDescriptor.checkPermissions();
374             fail("We expected some exception here");
375         }
376         catch (ModulePermissionException e)
377         {
378             assertEquals(ImmutableSet.of("some_module_permission"), e.getPermissions());
379         }
380     }
381 
382     @Test
383     public void testCheckPermissionsForModuleDescriptorWithPermissionsAllInPluginPermissions()
384     {
385         final Set<String> permissions = ImmutableSet.of("two_plugin_permission", "one_plugin_permission");
386         final AbstractModuleDescriptor moduleDescriptor = new StringModuleDescriptor(ModuleFactory.LEGACY_MODULE_FACTORY, this.getClass().getName()) {
387             @Override
388             protected Set<String> getRequiredPermissions()
389             {
390                 return permissions;
391             }
392         };
393 
394         final Plugin plugin = mock(Plugin.class);
395         moduleDescriptor.setPlugin(plugin);
396         ImmutableSet<String> pluginPermissions = ImmutableSet.of("one_plugin_permission", "two_plugin_permission", "three_plugin_permission", ANNOTATION_PERMISSION);
397         when(plugin.getActivePermissions()).thenReturn(pluginPermissions);
398 
399         moduleDescriptor.checkPermissions();
400     }
401 
402     private AbstractModuleDescriptor makeSingletonDescriptor()
403     {
404         AbstractModuleDescriptor descriptor = new AbstractModuleDescriptor(ModuleFactory.LEGACY_MODULE_FACTORY) {
405             Object module;
406 
407             public void init(Plugin plugin, Element element) throws PluginParseException
408             {
409                 super.init(plugin, element);
410             }
411 
412             public Object getModule()
413             {
414                 try
415                 {
416                     if (!isSingleton())
417                     {
418                         return ClassLoaderUtils.loadClass(getModuleClass().getName(), TestAbstractModuleDescriptor.class).newInstance();
419                     }
420                     else
421                     {
422                         if (module == null)
423                         {
424                             module = ClassLoaderUtils.loadClass(getModuleClass().getName(), TestAbstractModuleDescriptor.class).newInstance();
425                         }
426 
427                         return module;
428                     }
429                 }
430                 catch (Exception e)
431                 {
432                     throw new RuntimeException("What happened Dave?");
433                 }
434             }
435         };
436         return descriptor;
437     }
438 
439     @RequirePermission(ANNOTATION_PERMISSION)
440     private static class StringModuleDescriptor extends AbstractModuleDescriptor<String>
441     {
442         public StringModuleDescriptor(ModuleFactory moduleFactory, String className)
443         {
444             super(moduleFactory);
445             moduleClassName = className;
446         }
447 
448         @Override
449         public String getModule()
450         {
451             return null;
452         }
453 
454     }
455 
456     private static class ExtendsNumberModuleDescriptor<T extends Number> extends AbstractModuleDescriptor<T>
457     {
458         public ExtendsNumberModuleDescriptor(ModuleFactory moduleFactory, String className)
459         {
460             super(moduleFactory);
461             moduleClassName = className;
462         }
463 
464         @Override
465         public T getModule()
466         {
467             return null;
468         }
469     }
470 
471     private static class ExtendsNothingModuleDescriptor<T> extends AbstractModuleDescriptor<T>
472     {
473         public ExtendsNothingModuleDescriptor(ModuleFactory moduleFactory, String className)
474         {
475             super(moduleFactory);
476             moduleClassName = className;
477         }
478 
479         @Override
480         public T getModule()
481         {
482             return null;
483         }
484     }
485 }