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