View Javadoc
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.boot;
8   
9   import java.io.File;
10  import java.io.FileInputStream;
11  import java.io.FileOutputStream;
12  import java.io.IOException;
13  import java.io.InputStream;
14  import java.io.OutputStream;
15  import java.lang.reflect.InvocationTargetException;
16  import java.lang.reflect.Method;
17  import java.net.URL;
18  import java.net.URLClassLoader;
19  import java.security.AccessController;
20  import java.security.PrivilegedAction;
21  import java.util.Iterator;
22  import java.util.List;
23  
24  public final class MuleBootstrapUtils
25  {
26      private static final String MULE_LIB_FILENAME = "lib" + File.separator + "mule";
27      private static final String MULE_HOME = System.getProperty("mule.home");
28      
29      public static final String MULE_LOCAL_JAR_FILENAME = "mule-local-install.jar";
30  
31      private MuleBootstrapUtils()
32      {
33          // utility class only
34      }
35  
36      /**
37       * Whether Mule is running embedded or standalone.
38       * @return true if running standalone
39       */
40      public static boolean isStandalone()
41      {
42          // when embedded, mule.home var is not set
43          return MULE_HOME != null;
44      }
45  
46      /**
47       * @return null if running embedded
48       */
49      public static File getMuleHomeFile()
50      {
51          return isStandalone() ? new File(MULE_HOME) : null;
52      }
53  
54      /**
55       * @return null if running embedded
56       */
57      public static File getMuleLibDir()
58      {   
59          return isStandalone() ? new File(MULE_HOME + File.separator + MULE_LIB_FILENAME) : null;
60      }
61      
62      public static File getMuleLocalJarFile()
63      {
64          return isStandalone() ? new File(getMuleLibDir(), MULE_LOCAL_JAR_FILENAME) : null;
65      }
66      
67      public static void addLocalJarFilesToClasspath(File muleHome, File muleBase) throws Exception
68      {
69          DefaultMuleClassPathConfig classPath = new DefaultMuleClassPathConfig(muleHome, muleBase);
70          addLibrariesToClasspath(classPath.getURLs());
71      }
72      
73      public static void addLibrariesToClasspath(List urls) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
74      {
75          ClassLoader sys = ClassLoader.getSystemClassLoader();
76          if (!(sys instanceof URLClassLoader))
77          {
78              throw new IllegalArgumentException(
79                  "PANIC: Mule has been started with an unsupported classloader: " + sys.getClass().getName()
80                                  + ". " + "Please report this error to user<at>mule<dot>codehaus<dot>org");
81          }
82      
83          // system classloader is in this case the one that launched the application,
84          // which is usually something like a JDK-vendor proprietary AppClassLoader
85          URLClassLoader sysCl = (URLClassLoader) sys;
86      
87          /*
88           * IMPORTANT NOTE: The more 'natural' way would be to create a custom
89           * URLClassLoader and configure it, but then there's a chicken-and-egg
90           * problem, as all classes MuleBootstrap depends on would have been loaded by
91           * a parent classloader, and not ours. There's no straightforward way to
92           * change this, and is documented in a Sun's classloader guide. The solution
93           * would've involved overriding the ClassLoader.findClass() method and
94           * modifying the semantics to be child-first, but that way we are calling for
95           * trouble. Hacking the primordial classloader is a bit brutal, but works
96           * perfectly in case of running from the command-line as a standalone app.
97           * All Mule embedding options then delegate the classpath config to the
98           * embedder (a developer embedding Mule in the app), thus classloaders are
99           * not modified in those scenarios.
100          */
101     
102         // get a Method ref from the normal class, but invoke on a proprietary parent
103         // object,
104         // as this method is usually protected in those classloaders
105         Class refClass = URLClassLoader.class;
106         Method methodAddUrl = refClass.getDeclaredMethod("addURL", new Class[]{URL.class});
107         methodAddUrl.setAccessible(true);
108         for (Iterator it = urls.iterator(); it.hasNext();)
109         {
110             URL url = (URL) it.next();
111             methodAddUrl.invoke(sysCl, new Object[]{url});
112         }
113     }
114     
115     public static class ProxyInfo
116     {
117         String host;
118         String port;
119         String username;
120         String password;
121         
122         public ProxyInfo(String host, String port)
123         {
124             this(host, port, null, null);
125         }
126         
127         public ProxyInfo(String host, String port, String username, String password)
128         {
129             this.host = host;
130             this.port = port;
131             this.username = username;
132             this.password = password;
133         }
134     }
135 
136     //////////////////////////////////////////////////////////////////////////////////////////
137     // The following methods are intentionally duplicated from org.mule.util so that 
138     // mule-module-boot has no external dependencies at system startup.
139     //////////////////////////////////////////////////////////////////////////////////////////
140     
141     /**
142      * @see org.mule.util.ClassUtils#getResource
143      */
144     public static URL getResource(final String resourceName, final Class callingClass)
145     {
146         URL url = (URL) AccessController.doPrivileged(new PrivilegedAction()
147         {
148             public Object run()
149             {
150                 final ClassLoader cl = Thread.currentThread().getContextClassLoader();
151                 return cl != null ? cl.getResource(resourceName) : null;
152             }
153         });
154 
155         if (url == null)
156         {
157             url = (URL) AccessController.doPrivileged(new PrivilegedAction()
158             {
159                 public Object run()
160                 {
161                     return MuleBootstrap.class.getClassLoader().getResource(resourceName);
162                 }
163             });
164         }
165 
166         if (url == null)
167         {
168             url = (URL) AccessController.doPrivileged(new PrivilegedAction()
169             {
170                 public Object run()
171                 {
172                     return callingClass.getClassLoader().getResource(resourceName);
173                 }
174             });
175         }
176 
177         return url;
178     }
179 
180     /**
181      * @see org.mule.util.FileUtils#renameFile
182      */
183     public static boolean renameFile(File srcFile, File destFile) throws IOException
184     {
185         boolean isRenamed = false;
186         if (srcFile != null && destFile != null)
187         {
188             if (!destFile.exists())
189             {
190                 if (srcFile.isFile())
191                 {
192                     isRenamed = srcFile.renameTo(destFile);
193                     if (!isRenamed && srcFile.exists())
194                     {
195                         isRenamed = renameFileHard(srcFile, destFile);
196                     }
197                 }
198             }
199         }
200         return isRenamed;
201     }
202     
203     /**
204      * @see org.mule.util.FileUtils#renameFileHard
205      */
206     public static boolean renameFileHard(File srcFile, File destFile) throws IOException
207     {
208         boolean isRenamed = false;
209         if (srcFile != null && destFile != null)
210         {
211             if (!destFile.exists())
212             {
213                 if (srcFile.isFile())
214                 {
215                     FileInputStream in = null;
216                     FileOutputStream out = null;
217                     try
218                     {
219                         in = new FileInputStream(srcFile);
220                         out = new FileOutputStream(destFile);
221                         out.getChannel().transferFrom(in.getChannel(), 0, srcFile.length());
222                         isRenamed = true;
223                     }
224                     finally
225                     {
226                         if (in != null)
227                         {
228                             in.close();
229                         }
230                         if (out != null)
231                         {
232                             out.close();
233                         }
234                     }
235                     if (isRenamed)
236                     {
237                         srcFile.delete();
238                     }
239                     else
240                     {
241                         destFile.delete();
242                     }
243                 }
244             }
245         }
246         return isRenamed;
247     }
248 
249     /**
250      * @see org.mule.util.IOUtils#copy
251      */
252     public static int copy(InputStream input, OutputStream output) throws IOException {
253         long count = copyLarge(input, output);
254         if (count > Integer.MAX_VALUE) {
255             return -1;
256         }
257         return (int) count;
258     }
259 
260     /**
261      * @see org.mule.util.IOUtils#copyLarge
262      */
263     public static long copyLarge(InputStream input, OutputStream output) throws IOException {
264         byte[] buffer = new byte[1024 * 4];
265         long count = 0;
266         int n = 0;
267         while (-1 != (n = input.read(buffer))) {
268             output.write(buffer, 0, n);
269             count += n;
270         }
271         return count;
272     }
273 }