1
2
3
4
5
6
7
8
9
10
11 package org.mule.module.launcher;
12
13 import org.mule.api.config.MuleProperties;
14 import org.mule.util.FileUtils;
15 import org.mule.util.SystemUtils;
16
17 import java.io.File;
18 import java.io.IOException;
19 import java.net.MalformedURLException;
20 import java.net.URL;
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.Enumeration;
25 import java.util.List;
26 import java.util.Set;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30
31 public class MuleApplicationClassLoader extends FineGrainedControlClassLoader
32 {
33
34
35
36
37 public static final String PATH_LIBRARY = "lib";
38
39
40
41
42 public static final String PATH_CLASSES = "classes";
43
44
45
46
47 public static final String PATH_MULE = "mule";
48
49
50
51
52 public static final String PATH_PER_APP = "per-app";
53
54 protected static final URL[] CLASSPATH_EMPTY = new URL[0];
55 protected final transient Log logger = LogFactory.getLog(getClass());
56
57 protected List<ShutdownListener> shutdownListeners = new ArrayList<ShutdownListener>();
58
59 private String appName;
60
61 public MuleApplicationClassLoader(String appName, ClassLoader parentCl)
62 {
63 this(appName, parentCl, Collections.<String>emptySet());
64 }
65
66 public MuleApplicationClassLoader(String appName, ClassLoader parentCl, Set<String> loaderOverrides)
67 {
68 super(CLASSPATH_EMPTY, parentCl, loaderOverrides);
69 this.appName = appName;
70 try
71 {
72
73 final String muleHome = System.getProperty(MuleProperties.MULE_HOME_DIRECTORY_PROPERTY);
74 String configPath = String.format("%s/apps/%s", muleHome, appName);
75 File parentFile = new File(configPath);
76 File classesDir = new File(parentFile, PATH_CLASSES);
77 addURL(classesDir.toURI().toURL());
78
79 File libDir = new File(parentFile, PATH_LIBRARY);
80 addJars(appName, libDir, true);
81
82
83 File libs = new File(muleHome, PATH_LIBRARY);
84 File muleLibs = new File(libs, PATH_MULE);
85 File perAppLibs = new File(muleLibs, PATH_PER_APP);
86 addJars(appName, perAppLibs, false);
87 }
88 catch (IOException e)
89 {
90 if (logger.isDebugEnabled())
91 {
92 logger.debug(String.format("[%s]", appName), e);
93 }
94 }
95 }
96
97
98
99
100 private void addJars(String appName, File dir, boolean verbose) throws MalformedURLException
101 {
102 if (dir.exists() && dir.canRead())
103 {
104 @SuppressWarnings("unchecked")
105 Collection<File> jars = FileUtils.listFiles(dir, new String[]{"jar"}, false);
106
107 if (!jars.isEmpty() && logger.isInfoEnabled())
108 {
109 StringBuilder sb = new StringBuilder();
110 sb.append(String.format("[%s] Loading the following jars:%n", appName));
111 sb.append("=============================").append(SystemUtils.LINE_SEPARATOR);
112
113 for (File jar : jars)
114 {
115 sb.append(jar.toURI().toURL()).append(SystemUtils.LINE_SEPARATOR);
116 }
117
118 sb.append("=============================").append(SystemUtils.LINE_SEPARATOR);
119
120 if (verbose)
121 {
122 logger.info(sb.toString());
123 }
124 else
125 {
126 logger.debug(sb.toString());
127 }
128 }
129
130 for (File jar : jars)
131 {
132 addURL(jar.toURI().toURL());
133 }
134 }
135 }
136
137 @Override
138 protected Class<?> findClass(String name) throws ClassNotFoundException
139 {
140 return super.findClass(name);
141 }
142
143 @Override
144 protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
145 {
146 return super.loadClass(name, resolve);
147 }
148
149 @Override
150 public URL getResource(String name)
151 {
152 return super.getResource(name);
153 }
154
155 @Override
156 public Enumeration<URL> getResources(String name) throws IOException
157 {
158 return super.getResources(name);
159 }
160
161 @Override
162 public void close()
163 {
164 for (ShutdownListener listener : shutdownListeners)
165 {
166 try
167 {
168 listener.execute();
169 }
170 catch (Exception e)
171 {
172 logger.error(e);
173 }
174 }
175 super.close();
176 }
177
178 public void addShutdownListener(ShutdownListener listener)
179 {
180 this.shutdownListeners.add(listener);
181 }
182
183 public String getAppName()
184 {
185 return appName;
186 }
187
188 @Override
189 public String toString()
190 {
191 return String.format("%s[%s]@%s", getClass().getName(),
192 appName,
193 Integer.toHexString(System.identityHashCode(this)));
194 }
195
196
197
198
199 public interface ShutdownListener
200 {
201 void execute();
202 }
203 }