1
2
3
4
5
6
7
8
9
10
11 package org.mule.module.launcher;
12
13 import org.mule.MuleCoreExtension;
14 import org.mule.api.MuleContext;
15 import org.mule.api.component.JavaComponent;
16 import org.mule.api.config.MuleProperties;
17 import org.mule.api.construct.FlowConstruct;
18 import org.mule.api.registry.MuleRegistry;
19 import org.mule.construct.SimpleService;
20 import org.mule.module.launcher.application.Application;
21 import org.mule.module.launcher.application.ApplicationWrapper;
22 import org.mule.module.launcher.application.PriviledgedMuleApplication;
23 import org.mule.tck.junit4.AbstractMuleContextTestCase;
24 import org.mule.util.CollectionUtils;
25 import org.mule.util.FileUtils;
26 import org.mule.util.StringUtils;
27 import org.mule.util.concurrent.Latch;
28
29 import java.io.File;
30 import java.io.IOException;
31 import java.net.URL;
32 import java.net.URLDecoder;
33 import java.util.Arrays;
34 import java.util.Collection;
35 import java.util.HashMap;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.concurrent.TimeUnit;
39
40 import org.apache.commons.io.filefilter.DirectoryFileFilter;
41 import org.apache.commons.io.filefilter.SuffixFileFilter;
42 import org.junit.Test;
43
44 import static org.junit.Assert.assertArrayEquals;
45 import static org.junit.Assert.assertEquals;
46 import static org.junit.Assert.assertFalse;
47 import static org.junit.Assert.assertNotNull;
48 import static org.junit.Assert.assertNotSame;
49 import static org.junit.Assert.assertNull;
50 import static org.junit.Assert.assertTrue;
51
52 public class DeploymentServiceTestCase extends AbstractMuleContextTestCase
53 {
54 protected static final int LATCH_TIMEOUT = 10000;
55 protected static final String[] NONE = new String[0];
56
57 protected File muleHome;
58 protected File appsDir;
59 protected DeploymentService deploymentService;
60
61 protected volatile Latch deployLatch;
62 protected volatile Latch installLatch;
63 protected volatile Latch undeployLatch;
64
65 @Override
66 protected void doSetUp() throws Exception
67 {
68 super.doSetUp();
69
70 final String tmpDir = System.getProperty("java.io.tmpdir");
71 muleHome = new File(tmpDir, getClass().getSimpleName() + System.currentTimeMillis());
72 appsDir = new File(muleHome, "apps");
73 appsDir.mkdirs();
74 System.setProperty(MuleProperties.MULE_HOME_DIRECTORY_PROPERTY, muleHome.getCanonicalPath());
75
76 new File(muleHome, "lib/shared/default").mkdirs();
77
78 deploymentService = new DeploymentService(new HashMap<Class<? extends MuleCoreExtension>, MuleCoreExtension>());
79 deploymentService.setDeployer(new TestDeployer());
80 installLatch = new Latch();
81 deployLatch = new Latch();
82 undeployLatch = new Latch();
83 }
84
85 @Override
86 protected void doTearDown() throws Exception
87 {
88
89 FileUtils.deleteTree(muleHome);
90 if (deploymentService != null)
91 {
92 deploymentService.stop();
93 }
94 super.doTearDown();
95
96
97
98
99 Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader());
100 }
101
102 @Test
103 public void testPriviledgedApp() throws Exception
104 {
105 final URL url = getClass().getResource("/priviledged-dummy-app.zip");
106 assertNotNull("Test app file not found " + url, url);
107 addAppArchive(url);
108
109 deploymentService.start();
110
111 assertTrue("Deployer never invoked", deployLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
112
113 assertAppsDir(NONE, new String[] {"priviledged-dummy-app"}, true);
114
115 final Application app = findApp("priviledged-dummy-app", 1);
116
117
118 final Object obj = app.getMuleContext().getRegistry().lookupObject(PriviledgedMuleApplication.REGISTRY_KEY_DEPLOYMENT_SERVICE);
119 assertNotNull("Privileged objects have not been registered", obj);
120 assertTrue(((ApplicationWrapper) app).getDelegate() instanceof PriviledgedMuleApplication);
121 }
122
123 @Test
124 public void testPriviledgedCrossAppAccess() throws Exception
125 {
126 URL url = getClass().getResource("/priviledged-dummy-app.zip");
127 assertNotNull("Test app file not found " + url, url);
128 addAppArchive(url);
129
130 url = getClass().getResource("/dummy-app.zip");
131 assertNotNull("Test app file not found " + url, url);
132 addAppArchive(url);
133
134 deploymentService.start();
135
136
137 assertTrue("Deployer never invoked", deployLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
138
139 assertAppsDir(NONE, new String[] {"dummy-app", "priviledged-dummy-app"}, true);
140
141 final Application privApp = findApp("priviledged-dummy-app", 2);
142 final Application dummyApp = findApp("dummy-app", 2);
143 assertTrue(((ApplicationWrapper) privApp).getDelegate() instanceof PriviledgedMuleApplication);
144
145 final MuleContext muleContext1 = privApp.getMuleContext();
146 System.out.println("muleContext1 = " + muleContext1);
147 assertNotSame(muleContext1, muleContext);
148 assertNotSame(privApp.getDeploymentClassLoader(), dummyApp.getDeploymentClassLoader());
149 final Collection<FlowConstruct> flowConstructs = dummyApp.getMuleContext().getRegistry().lookupObjects(FlowConstruct.class);
150 assertFalse("No FlowConstructs found in the sibling app", flowConstructs.isEmpty());
151 FlowConstruct fc = flowConstructs.iterator().next();
152 assertTrue(fc instanceof SimpleService);
153 SimpleService service = (SimpleService) fc;
154
155 Class<?> clazz = ((JavaComponent) service.getComponent()).getObjectType();
156 assertEquals("Wrong component implementation class", "org.mule.module.launcher.EchoTest", clazz.getName());
157 }
158
159 @Test
160 public void testDeployZipOnStartup() throws Exception
161 {
162 final URL url = getClass().getResource("/dummy-app.zip");
163 assertNotNull("Test app file not found " + url, url);
164 addAppArchive(url);
165
166 deploymentService.start();
167
168 assertTrue("Deployer never invoked", deployLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
169
170 assertAppsDir(NONE, new String[] {"dummy-app"}, true);
171
172
173 final Application app = findApp("dummy-app", 1);
174 final MuleRegistry registry = app.getMuleContext().getRegistry();
175 final Object obj = registry.lookupObject(PriviledgedMuleApplication.REGISTRY_KEY_DEPLOYMENT_SERVICE);
176 assertNull(obj);
177 assertFalse(((ApplicationWrapper) app).getDelegate() instanceof PriviledgedMuleApplication);
178
179
180 assertEquals("mule-app.properties should have been loaded.", "someValue", registry.get("myCustomProp"));
181 }
182
183 @Test
184 public void testUpdateAppViaZip() throws Exception
185 {
186 final URL url = getClass().getResource("/dummy-app.zip");
187 assertNotNull("Test app file not found " + url, url);
188 addAppArchive(url);
189
190 deploymentService.start();
191
192 assertTrue("Deployer never invoked", deployLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
193 assertAppsDir(NONE, new String[] {"dummy-app"}, true);
194 assertEquals("Application has not been properly registered with Mule", 1, deploymentService.getApplications().size());
195
196
197 deployLatch = new Latch();
198 addAppArchive(url);
199 assertTrue("Undeploy never invoked", undeployLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
200 assertTrue("Deployer never invoked", deployLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
201 assertEquals("Application has not been properly registered with Mule", 1, deploymentService.getApplications().size());
202 assertAppsDir(NONE, new String[]{"dummy-app"}, true);
203 }
204
205 @Test
206 public void testBrokenAppArchive() throws Exception
207 {
208 final URL url = getClass().getResource("/broken-app.zip");
209 assertNotNull("Test app file not found " + url, url);
210 addAppArchive(url);
211
212 deploymentService.start();
213
214 assertTrue("Install never invoked", installLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
215
216
217 installLatch = new Latch();
218
219
220 Thread.sleep(1000);
221
222
223 assertAppsDir(new String[] {"broken-app.zip"}, NONE, true);
224
225 assertAppsDir(NONE, new String[] {"dummy-app"}, false);
226 assertEquals("No apps should have been registered with Mule.", 0, deploymentService.getApplications().size());
227 final Map<URL, Long> zombieMap = deploymentService.getZombieMap();
228 assertEquals("Wrong number of zombie apps registered.", 1, zombieMap.size());
229 final Map.Entry<URL, Long> zombie = zombieMap.entrySet().iterator().next();
230 assertEquals("Wrong URL tagged as zombie.", "broken-app.zip", new File(zombie.getKey().getFile()).getName());
231 assertTrue("Invalid lastModified value for file URL.", zombie.getValue() != -1);
232
233
234 assertFalse("Install was invoked again for the broken application file", installLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
235 }
236
237 @Test
238 public void testBrokenAppName() throws Exception
239 {
240 final URL url = getClass().getResource("/app with spaces.zip");
241 assertNotNull("Test app file not found " + url, url);
242 addAppArchive(url);
243
244 try
245 {
246 deploymentService.start();
247 }
248 catch (DeploymentInitException e)
249 {
250 assertTrue(e.getMessage().contains("may not contain spaces"));
251 }
252
253
254 assertAppsDir(new String[] {"app with spaces.zip"}, NONE, true);
255 final Map<URL, Long> zombieMap = deploymentService.getZombieMap();
256 assertEquals("Wrong number of zombie apps registered.", 1, zombieMap.size());
257 final Map.Entry<URL, Long> zombie = zombieMap.entrySet().iterator().next();
258 assertEquals("Wrong URL tagged as zombie.", "app%20with%20spaces.zip", new File(zombie.getKey().getFile()).getName());
259 assertTrue("Invalid lastModified value for file URL.", zombie.getValue() != -1);
260 }
261
262
263
264
265 private Application findApp(final String appName, int totalAppsExpected)
266 {
267
268 final List<Application> apps = deploymentService.getApplications();
269 assertNotNull(apps);
270 assertEquals(totalAppsExpected, apps.size());
271 final Application app = deploymentService.findApplication(appName);
272 assertNotNull(app);
273 return app;
274 }
275
276 private void assertAppsDir(String[] expectedZips, String[] expectedApps, boolean performValidation)
277 {
278 final String[] actualZips = appsDir.list(new SuffixFileFilter(".zip"));
279 if (performValidation) {
280 assertArrayEquals("Invalid Mule application archives set", expectedZips, actualZips);
281 }
282 final String[] actualApps = appsDir.list(DirectoryFileFilter.DIRECTORY);
283 if (performValidation) {
284 assertTrue("Invalid Mule exploded applications set",
285 CollectionUtils.isEqualCollection(Arrays.asList(expectedApps), Arrays.asList(actualApps)));
286 }
287 }
288
289
290
291
292 private void addAppArchive(URL url) throws IOException
293 {
294
295 final String tempFileName = new File(URLDecoder.decode(url.getFile()) + ".part").getName();
296 final File tempFile = new File(appsDir, tempFileName);
297 FileUtils.copyURLToFile(url, tempFile);
298 tempFile.renameTo(new File(StringUtils.removeEnd(tempFile.getAbsolutePath(), ".part")));
299 }
300
301
302 private class TestDeployer implements MuleDeployer
303 {
304 MuleDeployer delegate = new DefaultMuleDeployer(deploymentService);
305
306 @Override
307 public void deploy(Application app)
308 {
309 System.out.println("DeploymentServiceTestCase$TestDeployer.deploy");
310 delegate.deploy(app);
311 deployLatch.release();
312 }
313
314 @Override
315 public void undeploy(Application app)
316 {
317 System.out.println("DeploymentServiceTestCase$TestDeployer.undeploy");
318 delegate.undeploy(app);
319 undeployLatch.release();
320 }
321
322 @Override
323 public Application installFromAppDir(String packedMuleAppFileName) throws IOException
324 {
325 installLatch.release();
326 System.out.println("DeploymentServiceTestCase$TestDeployer.installFromAppDir");
327 return delegate.installFromAppDir(packedMuleAppFileName);
328 }
329
330 @Override
331 public Application installFrom(URL url) throws IOException
332 {
333 installLatch.release();
334 System.out.println("DeploymentServiceTestCase$TestDeployer.installFrom");
335 return delegate.installFrom(url);
336 }
337 }
338 }