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         moduleDescriptor.checkPermissions();
249     }
250 
251     public void testCheckPermissionsForModuleDescriptorAndPluginWithSamePermission()
252     {
253         final String somePermission = "some_permission";
254         final AbstractModuleDescriptor moduleDescriptor = new StringModuleDescriptor(ModuleFactory.LEGACY_MODULE_FACTORY, this.getClass().getName()) {
255             @Override
256             protected Set<String> getRequiredPermissions()
257             {
258                 return ImmutableSet.of(somePermission);
259             }
260         };
261 
262         final Plugin plugin = mock(Plugin.class);
263         moduleDescriptor.setPlugin(plugin);
264         when(plugin.getPermissions()).thenReturn(ImmutableSet.of(somePermission, ANNOTATION_PERMISSION));
265 
266         moduleDescriptor.checkPermissions();
267     }
268 
269     public void testCheckPermissionsForModuleDescriptorWithPermissionsAndPluginWithAllPermission()
270     {
271         final Set<String> permissions = ImmutableSet.of("some_permission");
272         final AbstractModuleDescriptor moduleDescriptor = new StringModuleDescriptor(ModuleFactory.LEGACY_MODULE_FACTORY, this.getClass().getName()) {
273             @Override
274             protected Set<String> getRequiredPermissions()
275             {
276                 return permissions;
277             }
278         };
279 
280         final Plugin plugin = mock(Plugin.class);
281         moduleDescriptor.setPlugin(plugin);
282         when(plugin.getPermissions()).thenReturn(ImmutableSet.of(Permissions.ALL_PERMISSIONS));
283 
284         moduleDescriptor.checkPermissions();
285     }
286 
287     public void testCheckPermissionsForModuleDescriptorWithPermissionsNotInPluginPermissions()
288     {
289         final Set<String> permissions = ImmutableSet.of("some_module_permission", "one_plugin_permission");
290         final AbstractModuleDescriptor moduleDescriptor = new StringModuleDescriptor(ModuleFactory.LEGACY_MODULE_FACTORY, this.getClass().getName()) {
291             @Override
292             protected Set<String> getRequiredPermissions()
293             {
294                 return permissions;
295             }
296         };
297 
298         final Plugin plugin = mock(Plugin.class);
299         moduleDescriptor.setPlugin(plugin);
300         ImmutableSet<String> pluginPermissions = ImmutableSet.of("one_plugin_permission", "two_plugin_permission", ANNOTATION_PERMISSION);
301         when(plugin.getPermissions()).thenReturn(pluginPermissions);
302 
303         try
304         {
305             moduleDescriptor.checkPermissions();
306             fail("We expected some exception here");
307         }
308         catch (ModulePermissionException e)
309         {
310             assertEquals(ImmutableSet.of("some_module_permission"), e.getPermissions());
311         }
312     }
313 
314     public void testCheckPermissionsForModuleDescriptorWithPermissionsAllInPluginPermissions()
315     {
316         final Set<String> permissions = ImmutableSet.of("two_plugin_permission", "one_plugin_permission");
317         final AbstractModuleDescriptor moduleDescriptor = new StringModuleDescriptor(ModuleFactory.LEGACY_MODULE_FACTORY, this.getClass().getName()) {
318             @Override
319             protected Set<String> getRequiredPermissions()
320             {
321                 return permissions;
322             }
323         };
324 
325         final Plugin plugin = mock(Plugin.class);
326         moduleDescriptor.setPlugin(plugin);
327         ImmutableSet<String> pluginPermissions = ImmutableSet.of("one_plugin_permission", "two_plugin_permission", "three_plugin_permission", ANNOTATION_PERMISSION);
328         when(plugin.getPermissions()).thenReturn(pluginPermissions);
329 
330         moduleDescriptor.checkPermissions();
331     }
332 
333 
334     private AbstractModuleDescriptor makeSingletonDescriptor()
335     {
336         AbstractModuleDescriptor descriptor = new AbstractModuleDescriptor(ModuleFactory.LEGACY_MODULE_FACTORY) {
337             Object module;
338 
339             public void init(Plugin plugin, Element element) throws PluginParseException
340             {
341                 super.init(plugin, element);
342             }
343 
344             public Object getModule()
345             {
346                 try
347                 {
348                     if (!isSingleton())
349                     {
350                         return ClassLoaderUtils.loadClass(getModuleClass().getName(), TestAbstractModuleDescriptor.class).newInstance();
351                     }
352                     else
353                     {
354                         if (module == null)
355                         {
356                             module = ClassLoaderUtils.loadClass(getModuleClass().getName(), TestAbstractModuleDescriptor.class).newInstance();
357                         }
358 
359                         return module;
360                     }
361                 }
362                 catch (Exception e)
363                 {
364                     throw new RuntimeException("What happened Dave?");
365                 }
366             }
367         };
368         return descriptor;
369     }
370 
371     @RequirePermission(ANNOTATION_PERMISSION)
372     private static class StringModuleDescriptor extends AbstractModuleDescriptor<String>
373     {
374         public StringModuleDescriptor(ModuleFactory moduleFactory, String className)
375         {
376             super(moduleFactory);
377             moduleClassName = className;
378         }
379 
380         @Override
381         public String getModule()
382         {
383             return null;
384         }
385 
386     }
387 
388     private static class ExtendsNumberModuleDescriptor<T extends Number> extends AbstractModuleDescriptor<T>
389     {
390         public ExtendsNumberModuleDescriptor(ModuleFactory moduleFactory, String className)
391         {
392             super(moduleFactory);
393             moduleClassName = className;
394         }
395 
396         @Override
397         public T getModule()
398         {
399             return null;
400         }
401     }
402 
403     private static class ExtendsNothingModuleDescriptor<T> extends AbstractModuleDescriptor<T>
404     {
405         public ExtendsNothingModuleDescriptor(ModuleFactory moduleFactory, String className)
406         {
407             super(moduleFactory);
408             moduleClassName = className;
409         }
410 
411         @Override
412         public T getModule()
413         {
414             return null;
415         }
416     }
417 }