1
2
3
4
5
6
7 package org.mule.module.launcher;
8
9 import org.mule.config.i18n.MessageFactory;
10 import org.mule.module.launcher.application.Application;
11 import org.mule.module.reboot.MuleContainerBootstrapUtils;
12 import org.mule.util.FileUtils;
13 import org.mule.util.FilenameUtils;
14
15 import java.beans.Introspector;
16 import java.io.File;
17 import java.io.IOException;
18 import java.net.URISyntaxException;
19 import java.net.URL;
20 import java.util.concurrent.TimeUnit;
21 import java.util.concurrent.locks.ReentrantLock;
22
23 import org.apache.commons.logging.Log;
24 import org.apache.commons.logging.LogFactory;
25
26 public class DefaultMuleDeployer implements MuleDeployer
27 {
28
29 protected transient final Log logger = LogFactory.getLog(getClass());
30 protected DeploymentService deploymentService;
31
32 public DefaultMuleDeployer(DeploymentService deploymentService)
33 {
34 this.deploymentService = deploymentService;
35 }
36
37 public void deploy(Application app)
38 {
39 final ReentrantLock lock = deploymentService.getLock();
40 try
41 {
42 if (!lock.tryLock(0, TimeUnit.SECONDS))
43 {
44 return;
45 }
46 app.install();
47 app.init();
48 app.start();
49 }
50 catch (InterruptedException e)
51 {
52 Thread.currentThread().interrupt();
53 return;
54 }
55 catch (Throwable t)
56 {
57 app.dispose();
58
59 if (t instanceof DeploymentException)
60 {
61
62 throw ((DeploymentException) t);
63 }
64
65 final String msg = String.format("Failed to deploy application [%s]", app.getAppName());
66 throw new DeploymentException(MessageFactory.createStaticMessage(msg), t);
67 }
68 finally
69 {
70 if (lock.isHeldByCurrentThread())
71 {
72 lock.unlock();
73 }
74 }
75 }
76
77 public void undeploy(Application app)
78 {
79 final ReentrantLock lock = deploymentService.getLock();
80 try
81 {
82 if (!lock.tryLock(0, TimeUnit.SECONDS))
83 {
84 return;
85 }
86 }
87 catch (InterruptedException e)
88 {
89 Thread.currentThread().interrupt();
90 return;
91 }
92
93 try
94 {
95 tryToStopApp(app);
96 tryToDisposeApp(app);
97
98 try
99 {
100 final File appDir = new File(MuleContainerBootstrapUtils.getMuleAppsDir(), app.getAppName());
101 FileUtils.deleteDirectory(appDir);
102
103
104 final File marker = new File(MuleContainerBootstrapUtils.getMuleAppsDir(), String.format("%s-anchor.txt", app.getAppName()));
105 marker.delete();
106
107 Introspector.flushCaches();
108 }
109 catch (IOException e)
110 {
111 throw new DeploymentException(MessageFactory.createStaticMessage("Cannot delete application folder"), e);
112 }
113 }
114 finally
115 {
116 if (lock.isHeldByCurrentThread())
117 {
118 lock.unlock();
119 }
120 }
121 }
122
123 private void tryToDisposeApp(Application app)
124 {
125 try
126 {
127 app.dispose();
128 }
129 catch (Throwable t)
130 {
131 logger.error(String.format("Unable to cleanly dispose application '%s'. Restart Mule if you get errors redeploying this application", app.getAppName()), t);
132 }
133 }
134
135 private void tryToStopApp(Application app)
136 {
137 try
138 {
139 app.stop();
140 }
141 catch (Throwable t)
142 {
143 logger.error(String.format("Unable to cleanly stop application '%s'. Restart Mule if you get errors redeploying this application", app.getAppName()), t);
144 }
145 }
146
147 public Application installFromAppDir(String packedMuleAppFileName) throws IOException
148 {
149 final ReentrantLock lock = deploymentService.getLock();
150 try
151 {
152 if (!lock.tryLock(0, TimeUnit.SECONDS))
153 {
154 throw new IOException("Another deployment operation is in progress");
155 }
156
157 final File appsDir = MuleContainerBootstrapUtils.getMuleAppsDir();
158 File appFile = new File(appsDir, packedMuleAppFileName);
159
160
161 if (!appFile.getParentFile().equals(appsDir))
162 {
163 throw new SecurityException("installFromAppDir() can only deploy from $MULE_HOME/apps. Use installFrom(url) instead.");
164 }
165 return installFrom(appFile.toURL());
166 }
167 catch (InterruptedException e)
168 {
169 Thread.currentThread().interrupt();
170 throw new IOException("Install operation has been interrupted");
171 }
172 finally
173 {
174 if (lock.isHeldByCurrentThread())
175 {
176 lock.unlock();
177 }
178 }
179 }
180
181 public Application installFrom(URL url) throws IOException
182 {
183
184 if (!url.toString().endsWith(".zip"))
185 {
186 throw new IllegalArgumentException("Invalid Mule application archive: " + url);
187 }
188
189 final String baseName = FilenameUtils.getBaseName(url.toString());
190 if (baseName.contains("%20"))
191 {
192 throw new DeploymentInitException(
193 MessageFactory.createStaticMessage("Mule application name may not contain spaces: " + baseName));
194 }
195
196 final ReentrantLock lock = deploymentService.getLock();
197
198 String appName;
199 File appDir = null;
200 boolean errorEncountered = false;
201 try
202 {
203 if (!lock.tryLock(0, TimeUnit.SECONDS))
204 {
205 throw new IOException("Another deployment operation is in progress");
206 }
207
208 final File appsDir = MuleContainerBootstrapUtils.getMuleAppsDir();
209
210 final String fullPath = url.toURI().toString();
211
212 if (logger.isInfoEnabled())
213 {
214 logger.info("Exploding a Mule application archive: " + fullPath);
215 }
216
217 appName = FilenameUtils.getBaseName(fullPath);
218 appDir = new File(appsDir, appName);
219
220 final File source = new File(url.toURI());
221
222 FileUtils.unzip(source, appDir);
223 if ("file".equals(url.getProtocol()))
224 {
225 FileUtils.deleteQuietly(source);
226 }
227 }
228 catch (URISyntaxException e)
229 {
230 errorEncountered = true;
231 final IOException ex = new IOException(e.getMessage());
232 ex.fillInStackTrace();
233 throw ex;
234 }
235 catch (InterruptedException e)
236 {
237 errorEncountered = true;
238 Thread.currentThread().interrupt();
239 throw new IOException("Install operation has been interrupted");
240 }
241 catch (IOException e)
242 {
243 errorEncountered = true;
244
245 throw e;
246 }
247 catch (Throwable t)
248 {
249 errorEncountered = true;
250 final String msg = "Failed to install app from URL: " + url;
251 throw new DeploymentInitException(MessageFactory.createStaticMessage(msg), t);
252 }
253 finally {
254
255 if (errorEncountered && appDir != null && appDir.exists())
256 {
257 final boolean couldNotDelete = FileUtils.deleteTree(appDir);
258
259
260
261
262
263
264
265 }
266 if (lock.isHeldByCurrentThread())
267 {
268 lock.unlock();
269 }
270 }
271
272
273 return deploymentService.getAppFactory().createApp(appName);
274 }
275 }