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 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 }