View Javadoc

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