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.launcher;
8   
9   import org.mule.api.config.MuleProperties;
10  import org.mule.util.FileUtils;
11  import org.mule.util.SystemUtils;
12  
13  import java.io.File;
14  import java.io.IOException;
15  import java.net.URL;
16  import java.util.ArrayList;
17  import java.util.Collection;
18  import java.util.List;
19  
20  import org.apache.commons.logging.Log;
21  import org.apache.commons.logging.LogFactory;
22  
23  public class MuleApplicationClassLoader extends GoodCitizenClassLoader
24  {
25  
26      /**
27       * Library directory in Mule application.
28       */
29      public static final String PATH_LIBRARY = "lib";
30  
31      /**
32       * Classes and resources directory in Mule application.
33       */
34      public static final String PATH_CLASSES = "classes";
35  
36      protected static final URL[] CLASSPATH_EMPTY = new URL[0];
37      protected final transient Log logger = LogFactory.getLog(getClass());
38  
39      protected List<ShutdownListener> shutdownListeners = new ArrayList<ShutdownListener>();
40  
41      private String appName;
42  
43      public MuleApplicationClassLoader(String appName, ClassLoader parentCl)
44      {
45          super(CLASSPATH_EMPTY, parentCl);
46          this.appName = appName;
47          try
48          {
49              // get lib dir
50              final String muleHome = System.getProperty(MuleProperties.MULE_HOME_DIRECTORY_PROPERTY);
51              String configPath = String.format("%s/apps/%s", muleHome, appName);
52              File parentFile = new File(configPath); 
53              File classesDir = new File(parentFile, PATH_CLASSES);
54              addURL(classesDir.toURI().toURL());
55  
56              File libDir = new File(parentFile, PATH_LIBRARY);
57  
58              if (libDir.exists() && libDir.canRead())
59              {
60                  @SuppressWarnings("unchecked")
61                  Collection<File> jars = FileUtils.listFiles(libDir, new String[] {"jar"}, false);
62  
63                  if (!jars.isEmpty() && logger.isInfoEnabled())
64                  {
65                      StringBuilder sb = new StringBuilder();
66                      sb.append(String.format("[%s] Loading the following jars:%n", appName));
67                      sb.append("=============================").append(SystemUtils.LINE_SEPARATOR);
68  
69                      for (File jar : jars)
70                      {
71                          sb.append(jar.toURI().toURL()).append(SystemUtils.LINE_SEPARATOR);
72                      }
73  
74                      sb.append("=============================").append(SystemUtils.LINE_SEPARATOR);
75  
76                      logger.info(sb.toString());
77                  }
78  
79                  for (File jar : jars)
80                  {
81                      addURL(jar.toURI().toURL());
82                  }
83              }
84  
85          }
86          catch (IOException e)
87          {
88              if (logger.isDebugEnabled())
89              {
90                  logger.debug(String.format("[%s]", appName), e);
91              }
92          }
93      }
94  
95      @Override
96      public void close()
97      {
98          for (ShutdownListener listener : shutdownListeners)
99          {
100             try
101             {
102                 listener.execute();
103             }
104             catch (Exception e)
105             {
106                 logger.error(e);
107             }
108         }
109         super.close();
110     }
111 
112     public void addShutdownListener(ShutdownListener listener)
113     {
114         this.shutdownListeners.add(listener);
115     }
116 
117     public String getAppName()
118     {
119         return appName;
120     }
121 
122     @Override
123     public String toString()
124     {
125         return String.format("%s[%s]@%s", getClass().getName(),
126                              appName,
127                              Integer.toHexString(System.identityHashCode(this)));
128     }
129 
130     /**
131      * Optional hook, invoked synchronously right before the classloader is disposed of and closed.
132      */
133     public interface ShutdownListener
134     {
135         void execute();
136     }
137 }