001
014
015 package com.liferay.portal.kernel.process;
016
017 import aQute.bnd.annotation.ProviderType;
018
019 import com.liferay.portal.kernel.exception.PortalException;
020 import com.liferay.portal.kernel.log.Log;
021 import com.liferay.portal.kernel.log.LogFactoryUtil;
022 import com.liferay.portal.kernel.process.ProcessConfig.Builder;
023 import com.liferay.portal.kernel.util.CharPool;
024 import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
025 import com.liferay.portal.kernel.util.ServerDetector;
026 import com.liferay.portal.kernel.util.StringBundler;
027 import com.liferay.portal.kernel.util.StringPool;
028 import com.liferay.portal.kernel.util.StringUtil;
029 import com.liferay.portal.kernel.util.URLCodec;
030
031 import java.io.File;
032 import java.io.FileFilter;
033
034 import java.lang.reflect.Method;
035
036 import java.net.MalformedURLException;
037 import java.net.URI;
038 import java.net.URL;
039 import java.net.URLClassLoader;
040 import java.net.URLConnection;
041
042 import java.util.Arrays;
043 import java.util.LinkedHashSet;
044 import java.util.Set;
045
046 import javax.servlet.ServletContext;
047 import javax.servlet.ServletException;
048
049
052 @ProviderType
053 public class ClassPathUtil {
054
055 public static Set<URL> getClassPathURLs(ClassLoader classLoader) {
056 Set<URL> urls = new LinkedHashSet<URL>();
057
058 while (classLoader != null) {
059 if (classLoader instanceof URLClassLoader) {
060 URLClassLoader urlClassLoader = (URLClassLoader)classLoader;
061
062 urls.addAll(Arrays.asList(urlClassLoader.getURLs()));
063 }
064
065 classLoader = classLoader.getParent();
066 }
067
068 return urls;
069 }
070
071 public static URL[] getClassPathURLs(String classPath)
072 throws MalformedURLException {
073
074 String[] paths = StringUtil.split(classPath, File.pathSeparatorChar);
075
076 Set<URL> urls = new LinkedHashSet<URL>();
077
078 for (String path : paths) {
079 File file = new File(path);
080
081 URI uri = file.toURI();
082
083 urls.add(uri.toURL());
084 }
085
086 return urls.toArray(new URL[urls.size()]);
087 }
088
089 public static String getGlobalClassPath() {
090 return _globalClassPath;
091 }
092
093 public static String getJVMClassPath(boolean includeBootClassPath) {
094 String jvmClassPath = System.getProperty("java.class.path");
095
096 if (includeBootClassPath) {
097 String bootClassPath = System.getProperty("sun.boot.class.path");
098
099 jvmClassPath = jvmClassPath.concat(File.pathSeparator).concat(
100 bootClassPath);
101 }
102
103 return jvmClassPath;
104 }
105
106 public static String getPortalClassPath() {
107 return _portalClassPath;
108 }
109
110 public static ProcessConfig getPortalProcessConfig() {
111 return _portalProcessConfig;
112 }
113
114 public static void initializeClassPaths(ServletContext servletContext) {
115 ClassLoader classLoader = PortalClassLoaderUtil.getClassLoader();
116
117 if (classLoader == null) {
118 _log.error("Portal ClassLoader is null");
119
120 return;
121 }
122
123 StringBundler sb = new StringBundler(8);
124
125 String appServerGlobalClassPath = _buildClassPath(
126 classLoader, ServletException.class.getName());
127
128 sb.append(appServerGlobalClassPath);
129 sb.append(File.pathSeparator);
130
131 String portalGlobalClassPath = _buildClassPath(
132 classLoader, PortalException.class.getName());
133
134 sb.append(portalGlobalClassPath);
135
136 _globalClassPath = sb.toString();
137
138 sb.append(File.pathSeparator);
139 sb.append(
140 _buildClassPath(
141 classLoader, "com.liferay.portal.servlet.MainServlet"));
142 sb.append(File.pathSeparator);
143 sb.append(servletContext.getRealPath(""));
144 sb.append("/WEB-INF/classes");
145
146 _portalClassPath = sb.toString();
147
148 Builder builder = new Builder();
149
150 builder.setBootstrapClassPath(_globalClassPath);
151 builder.setReactClassLoader(PortalClassLoaderUtil.getClassLoader());
152 builder.setRuntimeClassPath(_portalClassPath);
153
154 _portalProcessConfig = builder.build();
155 }
156
157 private static String _buildClassPath(
158 ClassLoader classloader, String className) {
159
160 String pathOfClass = StringUtil.replace(
161 className, CharPool.PERIOD, CharPool.SLASH);
162
163 pathOfClass = pathOfClass.concat(".class");
164
165 URL url = classloader.getResource(pathOfClass);
166
167 if (_log.isDebugEnabled()) {
168 _log.debug("Build class path from " + url);
169 }
170
171 String protocol = url.getProtocol();
172
173 if (protocol.equals("bundle") || protocol.equals("bundleresource")) {
174 try {
175 URLConnection urlConnection = url.openConnection();
176
177 Class<?> clazz = urlConnection.getClass();
178
179 Method getLocalURLMethod = clazz.getDeclaredMethod(
180 "getLocalURL");
181
182 getLocalURLMethod.setAccessible(true);
183
184 url = (URL)getLocalURLMethod.invoke(urlConnection);
185 }
186 catch (Exception e) {
187 _log.error("Unable to resolve local URL from bundle", e);
188
189 return StringPool.BLANK;
190 }
191 }
192
193 String path = URLCodec.decodeURL(url.getPath());
194
195 if (_log.isDebugEnabled()) {
196 _log.debug("Path " + path);
197 }
198
199 path = StringUtil.replace(path, CharPool.BACK_SLASH, CharPool.SLASH);
200
201 if (_log.isDebugEnabled()) {
202 _log.debug("Decoded path " + path);
203 }
204
205 if (ServerDetector.isWebLogic() && protocol.equals("zip")) {
206 path = "file:".concat(path);
207 }
208
209 if (ServerDetector.isJBoss() &&
210 (protocol.equals("vfs") || protocol.equals("vfsfile"))) {
211
212 int pos = path.indexOf(".jar/");
213
214 if (pos != -1) {
215 String jarFilePath = path.substring(0, pos + 4);
216
217 File jarFile = new File(jarFilePath);
218
219 if (jarFile.isFile()) {
220 path = jarFilePath + '!' + path.substring(pos + 4);
221 }
222 }
223
224 path = "file:".concat(path);
225 }
226
227 File dir = null;
228
229 int pos = -1;
230
231 if (!path.startsWith("file:") ||
232 ((pos = path.indexOf(CharPool.EXCLAMATION)) == -1)) {
233
234 if (!path.endsWith(pathOfClass)) {
235 _log.error(
236 "Class " + className + " is not loaded from a JAR file");
237
238 return StringPool.BLANK;
239 }
240
241 String classesDirName = path.substring(
242 0, path.length() - pathOfClass.length());
243
244 if (!classesDirName.endsWith("/WEB-INF/classes/")) {
245 _log.error(
246 "Class " + className + " is not loaded from a standard " +
247 "location (/WEB-INF/classes)");
248
249 return StringPool.BLANK;
250 }
251
252 String libDirName = classesDirName.substring(
253 0, classesDirName.length() - "classes/".length());
254
255 libDirName += "/lib";
256
257 dir = new File(libDirName);
258 }
259 else {
260 pos = path.lastIndexOf(CharPool.SLASH, pos);
261
262 dir = new File(path.substring("file:".length(), pos));
263 }
264
265 if (!dir.isDirectory()) {
266 _log.error(dir.toString() + " is not a directory");
267
268 return StringPool.BLANK;
269 }
270
271 File[] files = dir.listFiles(
272 new FileFilter() {
273
274 @Override
275 public boolean accept(File file) {
276 if (file.isDirectory()) {
277 return false;
278 }
279
280 String name = file.getName();
281
282 return name.endsWith(".jar");
283 }
284
285 });
286
287 if (files == null) {
288 return StringPool.BLANK;
289 }
290
291 Arrays.sort(files);
292
293 StringBundler sb = new StringBundler(files.length * 2);
294
295 for (File file : files) {
296 sb.append(file.getAbsolutePath());
297 sb.append(File.pathSeparator);
298 }
299
300 sb.setIndex(sb.index() - 1);
301
302 return sb.toString();
303 }
304
305 private static Log _log = LogFactoryUtil.getLog(ClassPathUtil.class);
306
307 private static String _globalClassPath;
308 private static String _portalClassPath;
309 private static ProcessConfig _portalProcessConfig;
310
311 }