1 package com.atlassian.plugin.manager;
2
3 import com.atlassian.plugin.DefaultModuleDescriptorFactory;
4 import com.atlassian.plugin.JarPluginArtifact;
5 import com.atlassian.plugin.Plugin;
6 import com.atlassian.plugin.PluginAccessor;
7 import com.atlassian.plugin.PluginInformation;
8 import com.atlassian.plugin.PluginParseException;
9 import com.atlassian.plugin.PluginState;
10 import com.atlassian.plugin.event.PluginEventManager;
11 import com.atlassian.plugin.event.impl.DefaultPluginEventManager;
12 import com.atlassian.plugin.factories.LegacyDynamicPluginFactory;
13 import com.atlassian.plugin.factories.PluginFactory;
14 import com.atlassian.plugin.hostcontainer.DefaultHostContainer;
15 import com.atlassian.plugin.impl.StaticPlugin;
16 import com.atlassian.plugin.loaders.DirectoryPluginLoader;
17 import com.atlassian.plugin.loaders.PluginLoader;
18 import com.atlassian.plugin.loaders.classloading.DirectoryPluginLoaderUtils;
19 import com.atlassian.plugin.manager.store.MemoryPluginPersistentStateStore;
20 import com.atlassian.plugin.mock.MockAnimalModuleDescriptor;
21 import com.atlassian.plugin.repositories.FilePluginInstaller;
22 import com.atlassian.plugin.test.PluginJarBuilder;
23 import com.google.common.collect.ImmutableList;
24 import com.google.common.collect.Iterables;
25 import com.mockobjects.dynamic.C;
26 import com.mockobjects.dynamic.Mock;
27 import org.apache.commons.io.FileUtils;
28 import org.junit.After;
29 import org.junit.Before;
30 import org.junit.Test;
31
32 import java.io.File;
33 import java.io.InputStream;
34 import java.util.Arrays;
35 import java.util.Collections;
36
37 import static com.atlassian.plugin.loaders.classloading.DirectoryPluginLoaderUtils.createFillAndCleanTempPluginDirectory;
38 import static org.junit.Assert.assertEquals;
39 import static org.junit.Assert.assertFalse;
40 import static org.junit.Assert.assertNotNull;
41 import static org.junit.Assert.assertNull;
42 import static org.junit.Assert.assertTrue;
43 import static org.junit.Assert.fail;
44
45 public class TestDefaultPluginManagerLongRunning {
46
47
48
49 private DefaultPluginManager manager;
50
51 private PluginPersistentStateStore pluginStateStore;
52 private DefaultModuleDescriptorFactory moduleDescriptorFactory;
53
54 private DirectoryPluginLoader directoryPluginLoader;
55 private PluginEventManager pluginEventManager;
56
57 @Before
58 public void setUp() throws Exception {
59 pluginEventManager = new DefaultPluginEventManager();
60
61 pluginStateStore = new MemoryPluginPersistentStateStore();
62 moduleDescriptorFactory = new DefaultModuleDescriptorFactory(new DefaultHostContainer());
63 }
64
65 @After
66 public void tearDown() throws Exception {
67 manager = null;
68 moduleDescriptorFactory = null;
69 pluginStateStore = null;
70
71 if (directoryPluginLoader != null) {
72 directoryPluginLoader.onShutdown(null);
73 directoryPluginLoader = null;
74 }
75 }
76
77 private DefaultPluginManager newDefaultPluginManager(PluginLoader... pluginLoaders) {
78 return new DefaultPluginManager(pluginStateStore, ImmutableList.copyOf(pluginLoaders), moduleDescriptorFactory, new DefaultPluginEventManager());
79 }
80
81 @Test
82 public void testEnableFailed() throws PluginParseException {
83 final Mock mockPluginLoader = new Mock(PluginLoader.class);
84 final Plugin plugin = new StaticPlugin() {
85 public PluginState enableInternal() {
86 return PluginState.DISABLED;
87 }
88
89 public void disableInternal() {
90
91 }
92 };
93 plugin.setKey("foo");
94 plugin.setEnabledByDefault(false);
95 plugin.setPluginInformation(new PluginInformation());
96
97 mockPluginLoader.expectAndReturn("loadAllPlugins", C.ANY_ARGS, Collections.singletonList(plugin));
98
99 manager = newDefaultPluginManager((PluginLoader) mockPluginLoader.proxy());
100 manager.init();
101
102 assertEquals(1, manager.getPlugins().size());
103 assertEquals(0, manager.getEnabledPlugins().size());
104 assertFalse(plugin.getPluginState() == PluginState.ENABLED);
105 manager.enablePlugins("foo");
106 assertEquals(1, manager.getPlugins().size());
107 assertEquals(0, manager.getEnabledPlugins().size());
108 assertFalse(plugin.getPluginState() == PluginState.ENABLED);
109 }
110
111 private DefaultPluginManager makeClassLoadingPluginManager(File pluginsTestDir) throws PluginParseException {
112 directoryPluginLoader = new DirectoryPluginLoader(pluginsTestDir, ImmutableList.of(
113 new LegacyDynamicPluginFactory(PluginAccessor.Descriptor.FILENAME)), pluginEventManager);
114
115 manager = newDefaultPluginManager(directoryPluginLoader);
116
117 moduleDescriptorFactory.addModuleDescriptor("animal", MockAnimalModuleDescriptor.class);
118 manager.init();
119 return manager;
120 }
121
122 @Test
123 public void testInstallPluginTwiceWithSameName() throws Exception {
124 final DirectoryPluginLoaderUtils.ScannerDirectories directories = createFillAndCleanTempPluginDirectory();
125 File pluginsTestDir = directories.pluginsTestDir;
126
127 FileUtils.cleanDirectory(pluginsTestDir);
128 final File plugin = File.createTempFile("plugin", ".jar");
129 plugin.delete();
130 File jar = new PluginJarBuilder("plugin")
131 .addPluginInformation("some.key", "My name", "1.0", 1)
132 .addResource("foo.txt", "foo")
133 .addJava("my.MyClass",
134 "package my; public class MyClass {}")
135 .build();
136 FileUtils.moveFile(jar, plugin);
137
138 final DefaultPluginManager manager = makeClassLoadingPluginManager(pluginsTestDir);
139 manager.setPluginInstaller(new FilePluginInstaller(pluginsTestDir));
140
141 final String pluginKey = Iterables.getOnlyElement(manager.installPlugins(new JarPluginArtifact(plugin)));
142
143 assertTrue(new File(pluginsTestDir, plugin.getName()).exists());
144
145 final Plugin installedPlugin = manager.getPlugin(pluginKey);
146 assertNotNull(installedPlugin);
147 InputStream s0 = installedPlugin.getClassLoader().getResourceAsStream("foo.txt");
148 assertNotNull(s0);
149 s0.close();
150 assertNull(installedPlugin.getClassLoader().getResourceAsStream("bar.txt"));
151 assertNotNull(installedPlugin.getClassLoader().loadClass("my.MyClass"));
152 try {
153 installedPlugin.getClassLoader().loadClass("my.MyNewClass");
154 fail("Expected ClassNotFoundException for unknown class");
155 } catch (final ClassNotFoundException e) {
156
157 }
158
159
160 Thread.sleep(1000);
161
162 File jartmp = new PluginJarBuilder("plugin")
163 .addPluginInformation("some.key", "My name", "1.0", 1)
164 .addResource("bar.txt", "bar")
165 .addJava("my.MyNewClass",
166 "package my; public class MyNewClass {}")
167 .build();
168 plugin.delete();
169 FileUtils.moveFile(jartmp, plugin);
170
171
172 final String pluginKey2 = Iterables.getOnlyElement(manager.installPlugins(new JarPluginArtifact(plugin)));
173
174 assertTrue(new File(pluginsTestDir, plugin.getName()).exists());
175
176 final Plugin installedPlugin2 = manager.getPlugin(pluginKey2);
177 assertNotNull(installedPlugin2);
178 assertEquals(1, manager.getEnabledPlugins().size());
179 assertNull(installedPlugin2.getClassLoader().getResourceAsStream("foo.txt"));
180 InputStream s1 = installedPlugin2.getClassLoader().getResourceAsStream("bar.txt");
181 assertNotNull(s1);
182 s1.close();
183 assertNotNull(installedPlugin2.getClassLoader().loadClass("my.MyNewClass"));
184 try {
185 installedPlugin2.getClassLoader().loadClass("my.MyClass");
186 fail("Expected ClassNotFoundException for unknown class");
187 } catch (final ClassNotFoundException e) {
188
189 }
190 }
191
192 @Test
193 public void testInstallPluginTwiceWithDifferentName() throws Exception {
194 final DirectoryPluginLoaderUtils.ScannerDirectories directories = createFillAndCleanTempPluginDirectory();
195 File pluginsTestDir = directories.pluginsTestDir;
196
197 FileUtils.cleanDirectory(pluginsTestDir);
198 final File plugin1 = new PluginJarBuilder("plugin").addPluginInformation("some.key", "My name", "1.0", 1).addResource("foo.txt", "foo").addJava(
199 "my.MyClass", "package my; public class MyClass {}").build();
200
201 final DefaultPluginManager manager = makeClassLoadingPluginManager(pluginsTestDir);
202 manager.setPluginInstaller(new FilePluginInstaller(pluginsTestDir));
203
204 final String pluginKey = Iterables.getOnlyElement(manager.installPlugins(new JarPluginArtifact(plugin1)));
205
206 assertTrue(new File(pluginsTestDir, plugin1.getName()).exists());
207
208 final Plugin installedPlugin = manager.getPlugin(pluginKey);
209 assertNotNull(installedPlugin);
210 InputStream s0 = installedPlugin.getClassLoader().getResourceAsStream("foo.txt");
211 assertNotNull(s0);
212 s0.close();
213 InputStream s1 = installedPlugin.getClassLoader().getResourceAsStream("bar.txt");
214 assertNull(s1);
215 assertNotNull(installedPlugin.getClassLoader().loadClass("my.MyClass"));
216 try {
217 installedPlugin.getClassLoader().loadClass("my.MyNewClass");
218 fail("Expected ClassNotFoundException for unknown class");
219 } catch (final ClassNotFoundException e) {
220
221 }
222
223
224 Thread.sleep(1000);
225
226 final File plugin2 = new PluginJarBuilder("plugin").addPluginInformation("some.key", "My name", "1.0", 1)
227 .addResource("bar.txt", "bar").addJava("my.MyNewClass", "package my; public class MyNewClass {}")
228 .build();
229
230
231 final String pluginKey2 = Iterables.getOnlyElement(manager.installPlugins(new JarPluginArtifact(plugin2)));
232
233 assertFalse(new File(pluginsTestDir, plugin1.getName()).exists());
234 assertTrue(new File(pluginsTestDir, plugin2.getName()).exists());
235
236 final Plugin installedPlugin2 = manager.getPlugin(pluginKey2);
237 assertNotNull(installedPlugin2);
238 assertEquals(1, manager.getEnabledPlugins().size());
239 InputStream s2 = installedPlugin2.getClassLoader().getResourceAsStream("foo.txt");
240 assertNull(s2);
241 InputStream s3 = installedPlugin2.getClassLoader().getResourceAsStream("bar.txt");
242 assertNotNull(s3);
243 s3.close();
244 assertNotNull(installedPlugin2.getClassLoader().loadClass("my.MyNewClass"));
245 try {
246 installedPlugin2.getClassLoader().loadClass("my.MyClass");
247 fail("Expected ClassNotFoundException for unknown class");
248 } catch (final ClassNotFoundException e) {
249
250 }
251 }
252
253 @Test
254 public void testAddPluginsWithDependencyIssuesNoResolution() throws Exception {
255 final Plugin servicePlugin = new EnableInPassPlugin("service.plugin", 4);
256 final Plugin clientPlugin = new EnableInPassPlugin("client.plugin", 1);
257
258 manager = newDefaultPluginManager();
259 manager.addPlugins(null, Arrays.asList(servicePlugin, clientPlugin));
260
261 assertTrue(clientPlugin.getPluginState() == PluginState.ENABLED);
262 assertFalse(servicePlugin.getPluginState() == PluginState.ENABLED);
263 }
264
265 private static class EnableInPassPlugin extends StaticPlugin {
266 private int pass;
267
268 public EnableInPassPlugin(final String key, final int pass) {
269 this.pass = pass;
270 setKey(key);
271 }
272
273 @Override
274 public void enable() {
275 if (--pass <= 0) {
276 super.enable();
277 }
278 }
279 }
280 }