1
2
3
4
5
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
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
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
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
171 }
172 }
173
174 @Test
175 public void testSingletonness() throws DocumentException, PluginParseException
176 {
177 ModuleDescriptor descriptor = makeSingletonDescriptor();
178
179
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
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
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
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
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 }