1
2
3
4
5
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
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
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
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
157 }
158 }
159
160 public void testSingletonness() throws DocumentException, PluginParseException
161 {
162 ModuleDescriptor descriptor = makeSingletonDescriptor();
163
164
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
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
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
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
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 }