Coverage Report - org.mule.module.launcher.DefaultMuleDeployer
 
Classes in this File Line Coverage Branch Coverage Complexity
DefaultMuleDeployer
0%
0/104
0%
0/34
7.286
 
 1  
 /*
 2  
  * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 3  
  * The software in this package is published under the terms of the CPAL v1.0
 4  
  * license, a copy of which has been included with this distribution in the
 5  
  * LICENSE.txt file.
 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  0
     protected transient final Log logger = LogFactory.getLog(getClass());
 30  
     protected DeploymentService deploymentService;
 31  
 
 32  
     public DefaultMuleDeployer(DeploymentService deploymentService)
 33  0
     {
 34  0
         this.deploymentService = deploymentService;
 35  0
     }
 36  
 
 37  
     public void deploy(Application app)
 38  
     {
 39  0
         final ReentrantLock lock = deploymentService.getLock();
 40  
         try
 41  
         {
 42  0
             if (!lock.tryLock(0, TimeUnit.SECONDS))
 43  
             {
 44  
                 return;
 45  
             }
 46  0
             app.install();
 47  0
             app.init();
 48  0
             app.start();
 49  
         }
 50  0
         catch (InterruptedException e)
 51  
         {
 52  0
             Thread.currentThread().interrupt();
 53  
             return;
 54  
         }
 55  0
         catch (Throwable t)
 56  
         {
 57  0
             app.dispose();
 58  
 
 59  0
             if (t instanceof DeploymentException)
 60  
             {
 61  
                 // re-throw as is
 62  0
                 throw ((DeploymentException) t);
 63  
             }
 64  
 
 65  0
             final String msg = String.format("Failed to deploy application [%s]", app.getAppName());
 66  0
             throw new DeploymentException(MessageFactory.createStaticMessage(msg), t);
 67  
         }
 68  
         finally
 69  
         {
 70  0
             if (lock.isHeldByCurrentThread())
 71  
             {
 72  0
                 lock.unlock();
 73  
             }
 74  
         }
 75  0
     }
 76  
 
 77  
     public void undeploy(Application app)
 78  
     {
 79  0
         final ReentrantLock lock = deploymentService.getLock();
 80  
         try
 81  
         {
 82  0
             if (!lock.tryLock(0, TimeUnit.SECONDS))
 83  
             {
 84  0
                 return;
 85  
             }
 86  
         }
 87  0
         catch (InterruptedException e)
 88  
         {
 89  0
             Thread.currentThread().interrupt();
 90  0
             return;
 91  0
         }
 92  
 
 93  
         try
 94  
         {
 95  0
             tryToStopApp(app);
 96  0
             tryToDisposeApp(app);
 97  
 
 98  
             try
 99  
             {
 100  0
                 final File appDir = new File(MuleContainerBootstrapUtils.getMuleAppsDir(), app.getAppName());
 101  0
                 FileUtils.deleteDirectory(appDir);
 102  
 
 103  
                 // remove a marker, harmless, but a tidy app dir is always better :)
 104  0
                 final File marker = new File(MuleContainerBootstrapUtils.getMuleAppsDir(), String.format("%s-anchor.txt", app.getAppName()));
 105  0
                 marker.delete();
 106  
 
 107  0
                 Introspector.flushCaches();
 108  
             }
 109  0
             catch (IOException e)
 110  
             {
 111  0
                 throw new DeploymentException(MessageFactory.createStaticMessage("Cannot delete application folder"), e);
 112  0
             }
 113  
         }
 114  
         finally
 115  
         {
 116  0
             if (lock.isHeldByCurrentThread())
 117  
             {
 118  0
                 lock.unlock();
 119  
             }
 120  
         }
 121  0
     }
 122  
 
 123  
     private void tryToDisposeApp(Application app)
 124  
     {
 125  
         try
 126  
         {
 127  0
             app.dispose();
 128  
         }
 129  0
         catch (Throwable t)
 130  
         {
 131  0
             logger.error(String.format("Unable to cleanly dispose application '%s'. Restart Mule if you get errors redeploying this application", app.getAppName()), t);
 132  0
         }
 133  0
     }
 134  
 
 135  
     private void tryToStopApp(Application app)
 136  
     {
 137  
         try
 138  
         {
 139  0
             app.stop();
 140  
         }
 141  0
         catch (Throwable t)
 142  
         {
 143  0
             logger.error(String.format("Unable to cleanly stop application '%s'. Restart Mule if you get errors redeploying this application", app.getAppName()), t);
 144  0
         }
 145  0
     }
 146  
 
 147  
     public Application installFromAppDir(String packedMuleAppFileName) throws IOException
 148  
     {
 149  0
         final ReentrantLock lock = deploymentService.getLock();
 150  
         try
 151  
         {
 152  0
             if (!lock.tryLock(0, TimeUnit.SECONDS))
 153  
             {
 154  0
                 throw new IOException("Another deployment operation is in progress");
 155  
             }
 156  
 
 157  0
             final File appsDir = MuleContainerBootstrapUtils.getMuleAppsDir();
 158  0
             File appFile = new File(appsDir, packedMuleAppFileName);
 159  
             // basic security measure: outside apps dir use installFrom(url) and go through any
 160  
             // restrictions applied to it
 161  0
             if (!appFile.getParentFile().equals(appsDir))
 162  
             {
 163  0
                 throw new SecurityException("installFromAppDir() can only deploy from $MULE_HOME/apps. Use installFrom(url) instead.");
 164  
             }
 165  0
             return installFrom(appFile.toURL());
 166  
         }
 167  0
         catch (InterruptedException e)
 168  
         {
 169  0
             Thread.currentThread().interrupt();
 170  0
             throw new IOException("Install operation has been interrupted");
 171  
         }
 172  
         finally
 173  
         {
 174  0
             if (lock.isHeldByCurrentThread())
 175  
             {
 176  0
                 lock.unlock();
 177  
             }
 178  
         }
 179  
     }
 180  
 
 181  
     public Application installFrom(URL url) throws IOException
 182  
     {
 183  
         // TODO plug in app-bloodhound/validator here?
 184  0
         if (!url.toString().endsWith(".zip"))
 185  
         {
 186  0
             throw new IllegalArgumentException("Invalid Mule application archive: " + url);
 187  
         }
 188  
 
 189  0
         final String baseName = FilenameUtils.getBaseName(url.toString());
 190  0
         if (baseName.contains("%20"))
 191  
         {
 192  0
             throw new DeploymentInitException(
 193  
                     MessageFactory.createStaticMessage("Mule application name may not contain spaces: " + baseName));
 194  
         }
 195  
 
 196  0
         final ReentrantLock lock = deploymentService.getLock();
 197  
 
 198  
         String appName;
 199  0
         File appDir = null;
 200  0
         boolean errorEncountered = false;
 201  
         try
 202  
         {
 203  0
             if (!lock.tryLock(0, TimeUnit.SECONDS))
 204  
             {
 205  0
                 throw new IOException("Another deployment operation is in progress");
 206  
             }
 207  
 
 208  0
             final File appsDir = MuleContainerBootstrapUtils.getMuleAppsDir();
 209  
 
 210  0
             final String fullPath = url.toURI().toString();
 211  
 
 212  0
             if (logger.isInfoEnabled())
 213  
             {
 214  0
                 logger.info("Exploding a Mule application archive: " + fullPath);
 215  
             }
 216  
 
 217  0
             appName = FilenameUtils.getBaseName(fullPath);
 218  0
             appDir = new File(appsDir, appName);
 219  
             // normalize the full path + protocol to make unzip happy
 220  0
             final File source = new File(url.toURI());
 221  
             
 222  0
             FileUtils.unzip(source, appDir);
 223  0
             if ("file".equals(url.getProtocol()))
 224  
             {
 225  0
                 FileUtils.deleteQuietly(source);
 226  
             }
 227  
         }
 228  0
         catch (URISyntaxException e)
 229  
         {
 230  0
             errorEncountered = true;
 231  0
             final IOException ex = new IOException(e.getMessage());
 232  0
             ex.fillInStackTrace();
 233  0
             throw ex;
 234  
         }
 235  0
         catch (InterruptedException e)
 236  
         {
 237  0
             errorEncountered = true;
 238  0
             Thread.currentThread().interrupt();
 239  0
             throw new IOException("Install operation has been interrupted");
 240  
         }
 241  0
         catch (IOException e)
 242  
         {
 243  0
             errorEncountered = true;
 244  
             // re-throw
 245  0
             throw e;
 246  
         }
 247  0
         catch (Throwable t)
 248  
         {
 249  0
             errorEncountered = true;
 250  0
             final String msg = "Failed to install app from URL: " + url;
 251  0
             throw new DeploymentInitException(MessageFactory.createStaticMessage(msg), t);
 252  
         }
 253  
         finally {
 254  
             // delete an app dir, as it's broken
 255  0
             if (errorEncountered && appDir != null && appDir.exists())
 256  
             {
 257  0
                 final boolean couldNotDelete = FileUtils.deleteTree(appDir);
 258  
                 /*
 259  
                 if (couldNotDelete)
 260  
                 {
 261  
                     final String msg = String.format("Couldn't delete app directory '%s' after it failed to install", appDir);
 262  
                     logger.error(msg);
 263  
                 }
 264  
                 */
 265  
             }
 266  0
             if (lock.isHeldByCurrentThread())
 267  
             {
 268  0
                 lock.unlock();
 269  
             }
 270  
         }
 271  
 
 272  
         // appname is never null by now
 273  0
         return deploymentService.getAppFactory().createApp(appName);
 274  
     }
 275  
 }