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