1 package com.atlassian.plugin.loaders;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.net.URISyntaxException;
6 import java.util.Arrays;
7 import java.util.Collection;
8 import java.util.Collections;
9 import java.util.List;
10
11 import com.atlassian.plugin.ModuleDescriptorFactory;
12 import com.atlassian.plugin.Plugin;
13 import com.atlassian.plugin.PluginArtifact;
14 import com.atlassian.plugin.PluginException;
15 import com.atlassian.plugin.event.PluginEventManager;
16 import com.atlassian.plugin.loaders.classloading.DeploymentUnit;
17 import com.atlassian.plugin.loaders.classloading.Scanner;
18 import com.atlassian.plugin.test.PluginJarBuilder;
19 import com.atlassian.plugin.factories.PluginFactory;
20 import com.atlassian.plugin.test.PluginTestUtils;
21
22 import com.google.common.base.Function;
23 import com.google.common.collect.Iterables;
24 import com.google.common.collect.Lists;
25
26 import org.apache.commons.io.FileUtils;
27 import org.junit.After;
28 import org.junit.Before;
29 import org.junit.Test;
30 import org.mockito.ArgumentCaptor;
31
32
33 import static org.hamcrest.Matchers.containsInAnyOrder;
34 import static org.junit.Assert.assertEquals;
35 import static org.junit.Assert.assertThat;
36 import static org.junit.Assert.assertTrue;
37 import static org.junit.Assert.fail;
38 import static org.mockito.Matchers.isA;
39 import static org.mockito.Matchers.same;
40 import static org.mockito.Mockito.mock;
41 import static org.mockito.Mockito.verify;
42 import static org.mockito.Mockito.when;
43
44
45 public class TestBundledPluginLoader
46 {
47 private File pluginDir;
48
49 private static final String fooXml = "foo.xml";
50
51 @Before
52 public void createTemporaryDirectory() throws IOException, URISyntaxException
53 {
54 pluginDir = PluginTestUtils.createTempDirectory(TestBundledPluginLoader.class);
55 }
56
57 @After
58 public void deleteTemporaryDirectory() throws Exception
59 {
60 FileUtils.deleteDirectory(pluginDir);
61 pluginDir = null;
62 }
63
64 @Test
65 public void loaderFromZipContainsExpectedFiles() throws IOException
66 {
67 File bundledZip = buildBundledZip();
68 final BundledPluginLoader loader = buildBundledPluginLoader(bundledZip, Collections.<PluginFactory>emptyList());
69 assertLoaderContains(loader, fooXml);
70 }
71
72 @Test
73 public void loaderFromDirectoryContainsExpectedFiles() throws IOException
74 {
75 final File dir = PluginTestUtils.createTempDirectory(TestBundledPluginLoader.class);
76 FileUtils.writeStringToFile(new File(dir, "foo.txt"), "hello");
77
78 final BundledPluginLoader loader = buildBundledPluginLoader(dir, Collections.<PluginFactory>emptyList());
79 assertLoaderContains(loader, "foo.txt");
80 }
81
82 @Test
83 public void loaderFromFileListContainsExpectedFiles() throws IOException
84 {
85 final File dir = PluginTestUtils.createTempDirectory(TestBundledPluginLoader.class);
86 FileUtils.writeStringToFile(new File(dir, "foo.txt"), "hello");
87 FileUtils.writeStringToFile(new File(dir, "bar.txt"), "world");
88 File listFile = new File(dir, "bundled-plugins.list");
89 FileUtils.writeStringToFile(listFile, "foo.txt\nbar.txt");
90
91 final BundledPluginLoader loader = buildBundledPluginLoader(listFile, Collections.<PluginFactory>emptyList());
92 assertLoaderContains(loader, "foo.txt", "bar.txt");
93 }
94
95 @Test
96 public void loaderScannerDoesNotRemoveUnderlyingFiles() throws IOException
97 {
98 File bundledZip = buildBundledZip();
99
100 final BundledPluginLoader loader = buildBundledPluginLoader(bundledZip, Collections.<PluginFactory>emptyList());
101 final Scanner scanner = loader.scanner;
102 assertLoaderContains(loader, fooXml);
103 final Collection<DeploymentUnit> units = scanner.getDeploymentUnits();
104 final int countBefore = units.size();
105 int found = 0;
106 for (DeploymentUnit unit : units)
107 {
108 final File file = unit.getPath();
109 if (fooXml.equals(file.getName()))
110 {
111 found += 1;
112 assertTrue(file.exists());
113 scanner.remove(unit);
114
115 assertTrue(file.exists());
116 }
117 }
118
119 assertEquals(1, found);
120
121 assertEquals(countBefore, scanner.getDeploymentUnits().size());
122 }
123
124 @Test
125 public void loaderRemoveDoesUninstallPlugin() throws IOException
126 {
127 File bundledZip = buildBundledZip();
128 Plugin mockPlugin = mock(Plugin.class);
129 PluginFactory pluginFactory = mock(PluginFactory.class);
130 ModuleDescriptorFactory moduleDescriptorFactory = mock(ModuleDescriptorFactory.class);
131
132 final String key = "plugin.key.foo";
133 ArgumentCaptor<PluginArtifact> pluginArtifact = ArgumentCaptor.forClass(PluginArtifact.class);
134
135 when(mockPlugin.getKey()).thenReturn(key);
136 when(mockPlugin.isDeleteable()).thenReturn(true);
137 when(mockPlugin.isUninstallable()).thenReturn(true);
138 when(pluginFactory.canCreate(isA(PluginArtifact.class))).thenReturn(key);
139 when(pluginFactory.create(pluginArtifact.capture(), same(moduleDescriptorFactory))).thenReturn(mockPlugin);
140
141 final BundledPluginLoader loader = buildBundledPluginLoader(bundledZip, Arrays.asList(pluginFactory));
142 Collection<Plugin> plugins = Lists.newArrayList(loader.loadAllPlugins(moduleDescriptorFactory));
143 assertEquals(1, plugins.size());
144
145 Plugin bundledPlugin = Iterables.getOnlyElement(plugins);
146 assertEquals(key, bundledPlugin.getKey());
147 assertTrue(bundledPlugin.isBundledPlugin());
148 assertTrue(bundledPlugin.isDeleteable());
149 verify(mockPlugin).isDeleteable();
150
151
152 loader.removePlugin(bundledPlugin);
153 verify(mockPlugin).isUninstallable();
154 verify(mockPlugin).uninstall();
155
156 assertTrue(pluginArtifact.getValue().toFile().exists());
157
158 try
159 {
160
161
162
163
164
165
166 loader.removePlugin(bundledPlugin);
167 fail();
168 }
169 catch (PluginException pe)
170 {
171
172 }
173 }
174
175 private File buildBundledZip() throws IOException
176 {
177 return new PluginJarBuilder("bundledPlugins")
178 .addResource(fooXml, "<foo/>")
179 .buildWithNoManifest();
180 }
181
182 private BundledPluginLoader buildBundledPluginLoader(File bundle, List<PluginFactory> pluginFactories) throws IOException
183 {
184 return new BundledPluginLoader(bundle.toURI().toURL(), pluginDir, pluginFactories, mock(PluginEventManager.class));
185 }
186
187 private void assertLoaderContains(final BundledPluginLoader loader, String ... expectedEntries)
188 {
189 final Collection<DeploymentUnit> scanned = loader.scanner.scan();
190 final Iterable<String> actualEntries = Iterables.transform(scanned, new Function<DeploymentUnit, String>()
191 {
192 @Override
193 public String apply(DeploymentUnit unit)
194 {
195 return unit.getPath().getName();
196 }
197 });
198 assertThat(actualEntries, containsInAnyOrder(expectedEntries));
199 }
200 }