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<>();
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<>();
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.setArguments(Arrays.asList("-Djava.awt.headless=true"));
151 builder.setBootstrapClassPath(_globalClassPath);
152 builder.setReactClassLoader(PortalClassLoaderUtil.getClassLoader());
153 builder.setRuntimeClassPath(_portalClassPath);
154
155 _portalProcessConfig = builder.build();
156 }
157
158 private static String _buildClassPath(
159 ClassLoader classloader, String className) {
160
161 String pathOfClass = StringUtil.replace(
162 className, CharPool.PERIOD, CharPool.SLASH);
163
164 pathOfClass = pathOfClass.concat(".class");
165
166 URL url = classloader.getResource(pathOfClass);
167
168 if (_log.isDebugEnabled()) {
169 _log.debug("Build class path from " + url);
170 }
171
172 String protocol = url.getProtocol();
173
174 if (protocol.equals("bundle") || protocol.equals("bundleresource")) {
175 try {
176 URLConnection urlConnection = url.openConnection();
177
178 Class<?> clazz = urlConnection.getClass();
179
180 Method getLocalURLMethod = clazz.getDeclaredMethod(
181 "getLocalURL");
182
183 getLocalURLMethod.setAccessible(true);
184
185 url = (URL)getLocalURLMethod.invoke(urlConnection);
186 }
187 catch (Exception e) {
188 _log.error("Unable to resolve local URL from bundle", e);
189
190 return StringPool.BLANK;
191 }
192 }
193
194 String path = URLCodec.decodeURL(url.getPath());
195
196 if (_log.isDebugEnabled()) {
197 _log.debug("Path " + path);
198 }
199
200 path = StringUtil.replace(path, CharPool.BACK_SLASH, CharPool.SLASH);
201
202 if (_log.isDebugEnabled()) {
203 _log.debug("Decoded path " + path);
204 }
205
206 if (ServerDetector.isWebLogic() && protocol.equals("zip")) {
207 path = "file:".concat(path);
208 }
209
210 if ((ServerDetector.isJBoss() || ServerDetector.isWildfly()) &&
211 (protocol.equals("vfs") || protocol.equals("vfsfile"))) {
212
213 int pos = path.indexOf(".jar/");
214
215 if (pos != -1) {
216 String jarFilePath = path.substring(0, pos + 4);
217
218 File jarFile = new File(jarFilePath);
219
220 if (jarFile.isFile()) {
221 path = jarFilePath + '!' + path.substring(pos + 4);
222 }
223 }
224
225 path = "file:".concat(path);
226 }
227
228 File dir = null;
229
230 int pos = -1;
231
232 if (!path.startsWith("file:") ||
233 ((pos = path.indexOf(CharPool.EXCLAMATION)) == -1)) {
234
235 if (!path.endsWith(pathOfClass)) {
236 _log.error(
237 "Class " + className + " is not loaded from a JAR file");
238
239 return StringPool.BLANK;
240 }
241
242 String classesDirName = path.substring(
243 0, path.length() - pathOfClass.length());
244
245 if (!classesDirName.endsWith("/WEB-INF/classes/")) {
246 _log.error(
247 "Class " + className + " is not loaded from a standard " +
248 "location (/WEB-INF/classes)");
249
250 return StringPool.BLANK;
251 }
252
253 String libDirName = classesDirName.substring(
254 0, classesDirName.length() - "classes/".length());
255
256 libDirName += "/lib";
257
258 dir = new File(libDirName);
259 }
260 else {
261 pos = path.lastIndexOf(CharPool.SLASH, pos);
262
263 dir = new File(path.substring("file:".length(), pos));
264 }
265
266 if (!dir.isDirectory()) {
267 _log.error(dir.toString() + " is not a directory");
268
269 return StringPool.BLANK;
270 }
271
272 File[] files = dir.listFiles(
273 new FileFilter() {
274
275 @Override
276 public boolean accept(File file) {
277 if (file.isDirectory()) {
278 return false;
279 }
280
281 String name = file.getName();
282
283 return name.endsWith(".jar");
284 }
285
286 });
287
288 if (files == null) {
289 return StringPool.BLANK;
290 }
291
292 Arrays.sort(files);
293
294 StringBundler sb = new StringBundler(files.length * 2);
295
296 for (File file : files) {
297 sb.append(file.getAbsolutePath());
298 sb.append(File.pathSeparator);
299 }
300
301 sb.setIndex(sb.index() - 1);
302
303 return sb.toString();
304 }
305
306 private static final Log _log = LogFactoryUtil.getLog(ClassPathUtil.class);
307
308 private static String _globalClassPath;
309 private static String _portalClassPath;
310 private static ProcessConfig _portalProcessConfig;
311
312 }