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