1 package com.atlassian.plugin.loaders;
2
3 import com.atlassian.plugin.loaders.classloading.DeploymentUnit;
4 import com.atlassian.plugin.loaders.classloading.DirectoryPluginLoaderUtils;
5 import com.atlassian.plugin.loaders.classloading.Scanner;
6 import com.atlassian.plugin.test.PluginTestUtils;
7 import org.apache.commons.io.FileUtils;
8 import org.junit.Before;
9 import org.junit.Test;
10
11 import javax.annotation.Nonnull;
12 import java.io.File;
13 import java.io.IOException;
14 import java.util.Collection;
15 import java.util.Iterator;
16 import java.util.function.Function;
17
18 import static com.atlassian.plugin.loaders.classloading.DirectoryPluginLoaderUtils.PADDINGTON_JAR;
19 import static com.atlassian.plugin.loaders.classloading.DirectoryPluginLoaderUtils.POOH_JAR;
20 import static org.apache.commons.lang.SystemUtils.IS_OS_WINDOWS;
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertFalse;
23 import static org.junit.Assert.assertNotNull;
24 import static org.junit.Assert.assertTrue;
25 import static org.junit.Assume.assumeFalse;
26
27 public class TestDirectoryScanner {
28
29 private File pluginsTestDir;
30
31 @Before
32 public void createFillAndCleanTempPluginDirectory() throws IOException {
33 final DirectoryPluginLoaderUtils.ScannerDirectories directories =
34 DirectoryPluginLoaderUtils.createFillAndCleanTempPluginDirectory();
35 pluginsTestDir = directories.pluginsTestDir;
36 }
37
38 @Test
39 public void testNormalOperation() {
40 File pluginsDirectory = pluginsTestDir;
41 Scanner scanner = new DirectoryScanner(pluginsDirectory);
42 scanner.scan();
43 Collection<DeploymentUnit> deployedUnits = scanner.getDeploymentUnits();
44 assertEquals(2, deployedUnits.size());
45
46
47 Iterator iterator = deployedUnits.iterator();
48 DeploymentUnit unit = (DeploymentUnit) iterator.next();
49 assertEquals(PADDINGTON_JAR, unit.getPath().getName());
50
51 unit = (DeploymentUnit) iterator.next();
52 assertEquals(POOH_JAR, unit.getPath().getName());
53 }
54
55 @Test
56 public void testSkipDot() throws Exception {
57 File pluginsDirectory = pluginsTestDir;
58 assertNotNull(File.createTempFile(".asdf", ".jar", pluginsDirectory));
59 Scanner scanner = new DirectoryScanner(pluginsDirectory);
60 scanner.scan();
61 Collection<DeploymentUnit> deployedUnits = scanner.getDeploymentUnits();
62 assertEquals(2, deployedUnits.size());
63
64
65 Iterator iterator = deployedUnits.iterator();
66 DeploymentUnit unit = (DeploymentUnit) iterator.next();
67 assertEquals(PADDINGTON_JAR, unit.getPath().getName());
68
69 unit = (DeploymentUnit) iterator.next();
70 assertEquals(POOH_JAR, unit.getPath().getName());
71 }
72
73 @Test
74 public void testRemove() {
75 File pluginsDirectory = pluginsTestDir;
76 File paddington = new File(pluginsDirectory, PADDINGTON_JAR);
77
78 assertTrue(paddington.exists());
79
80 DirectoryScanner scanner = new DirectoryScanner(pluginsDirectory);
81 scanner.scan();
82 assertEquals(2, scanner.getDeploymentUnits().size());
83 DeploymentUnit paddingtonUnit = scanner.locateDeploymentUnit(paddington);
84 scanner.remove(paddingtonUnit);
85
86 assertFalse(paddington.exists());
87 assertEquals(1, scanner.getDeploymentUnits().size());
88 }
89
90 @Test
91 public void testRemoveFromReadOnlySource() {
92
93 assumeFalse(IS_OS_WINDOWS);
94
95 final File pluginsDirectory = pluginsTestDir;
96 final File paddington = new File(pluginsDirectory, PADDINGTON_JAR);
97 try {
98
99 setWritable(pluginsDirectory, false);
100
101 assumeFalse("Can write to " + pluginsDirectory +
102 ", even though we made it read-only. Maybe we're running as root?", pluginsDirectory.canWrite());
103 final DirectoryScanner scanner = new DirectoryScanner(pluginsDirectory);
104 scanner.scan();
105 assertEquals(2, scanner.getDeploymentUnits().size());
106 final DeploymentUnit paddingtonUnit = scanner.locateDeploymentUnit(paddington);
107 assertTrue( PADDINGTON_JAR + " should exist before remove() is called", paddington.exists());
108
109 scanner.remove(paddingtonUnit);
110
111 assertTrue(PADDINGTON_JAR + " should exist after remove() is called", paddington.exists());
112 assertEquals(1, scanner.getDeploymentUnits().size());
113 } finally {
114
115 setWritable(pluginsDirectory, true);
116 }
117 }
118
119 @Test
120 public void testRemoveNoErrorWhenNotExist() {
121 File pluginsDirectory = pluginsTestDir;
122 File paddington = new File(pluginsDirectory, PADDINGTON_JAR);
123
124 assertTrue(paddington.exists());
125
126 DirectoryScanner scanner = new DirectoryScanner(pluginsDirectory);
127 scanner.scan();
128 assertEquals(2, scanner.getDeploymentUnits().size());
129 DeploymentUnit paddingtonUnit = scanner.locateDeploymentUnit(paddington);
130 assertTrue(paddington.exists());
131 assertTrue(paddington.delete());
132 scanner.remove(paddingtonUnit);
133
134 assertFalse(paddington.exists());
135 assertEquals(1, scanner.getDeploymentUnits().size());
136 }
137
138 @Test
139 public void testAddAndRemoveJarFromOutsideScanner() throws Exception {
140 File pluginsDirectory = pluginsTestDir;
141 File paddington = new File(pluginsDirectory, PADDINGTON_JAR);
142 File duplicate = new File(pluginsDirectory, "duplicate-test-plugin.jar");
143
144
145 if (duplicate.canRead()) {
146 delete(duplicate);
147 }
148
149
150 Scanner scanner = new DirectoryScanner(pluginsDirectory);
151 scanner.scan();
152 assertEquals(2, scanner.getDeploymentUnits().size());
153
154
155 FileUtils.copyFile(paddington, duplicate);
156 scanner.scan();
157 assertEquals(3, scanner.getDeploymentUnits().size());
158
159
160 delete(duplicate);
161 scanner.scan();
162 assertEquals(2, scanner.getDeploymentUnits().size());
163 }
164
165 @Test
166 public void testModifyJar() throws Exception {
167
168
169 File pluginsDirectory = pluginsTestDir;
170 File paddington = new File(pluginsDirectory, PADDINGTON_JAR);
171
172 File testTempDirectory = PluginTestUtils.createTempDirectory(TestDirectoryScanner.class);
173
174 File newPaddington = new File(testTempDirectory, PADDINGTON_JAR);
175 FileUtils.copyFile(paddington, newPaddington);
176
177
178 long originalModification = System.currentTimeMillis();
179 originalModification = originalModification - (originalModification % 1000) - 3000;
180 setLastModified(newPaddington, originalModification);
181 assertEquals(originalModification, newPaddington.lastModified());
182
183
184 DirectoryScanner scanner = new DirectoryScanner(testTempDirectory);
185 scanner.scan();
186 assertEquals(1, scanner.getDeploymentUnits().size());
187
188 DeploymentUnit newPaddingtonUnit = scanner.locateDeploymentUnit(newPaddington);
189 assertEquals(originalModification, newPaddingtonUnit.lastModified());
190
191
192 long secondModification = originalModification + 2000;
193 setLastModified(newPaddington, secondModification);
194 scanner.scan();
195
196 newPaddingtonUnit = scanner.locateDeploymentUnit(newPaddington);
197 assertEquals(secondModification, newPaddingtonUnit.lastModified());
198 }
199
200 private static void delete(@Nonnull final File file) {
201 confirmModifyFile(file, File::delete);
202 }
203
204 private static void setLastModified(@Nonnull final File file, final long time) {
205 confirmModifyFile(file, f -> f.setLastModified(time));
206 }
207
208 private static void setWritable(@Nonnull final File file, final boolean writable) {
209 confirmModifyFile(file, f -> f.setWritable(writable));
210 }
211
212 private static void confirmModifyFile(@Nonnull final File file, final Function<File, Boolean> operation) {
213 final String message = String.format("Couldn't modify file %s", file);
214 assertTrue(message, operation.apply(file));
215 }
216 }