001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.process;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.util.CharPool;
021    import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
022    import com.liferay.portal.kernel.util.ServerDetector;
023    import com.liferay.portal.kernel.util.StringBundler;
024    import com.liferay.portal.kernel.util.StringPool;
025    import com.liferay.portal.kernel.util.StringUtil;
026    import com.liferay.portal.kernel.util.URLCodec;
027    
028    import java.io.File;
029    
030    import java.lang.reflect.Method;
031    
032    import java.net.MalformedURLException;
033    import java.net.URI;
034    import java.net.URL;
035    import java.net.URLConnection;
036    
037    import java.util.ArrayList;
038    import java.util.Arrays;
039    import java.util.List;
040    
041    import javax.servlet.ServletContext;
042    import javax.servlet.ServletException;
043    
044    /**
045     * @author Shuyang Zhou
046     */
047    public class ClassPathUtil {
048    
049            public static URL[] getClassPathURLs(String classPath)
050                    throws MalformedURLException {
051    
052                    String[] paths = StringUtil.split(classPath, File.pathSeparatorChar);
053    
054                    List<URL> urls = new ArrayList<URL>();
055    
056                    for (String path : paths) {
057                            File file = new File(path);
058    
059                            URI uri = file.toURI();
060    
061                            urls.add(uri.toURL());
062                    }
063    
064                    return urls.toArray(new URL[urls.size()]);
065            }
066    
067            public static String getGlobalClassPath() {
068                    return _globalClassPath;
069            }
070    
071            public static String getJVMClassPath(boolean includeBootClassPath) {
072                    String jvmClassPath = System.getProperty("java.class.path");
073    
074                    if (includeBootClassPath) {
075                            String bootClassPath = System.getProperty("sun.boot.class.path");
076    
077                            jvmClassPath = jvmClassPath.concat(File.pathSeparator).concat(
078                                    bootClassPath);
079                    }
080    
081                    return jvmClassPath;
082            }
083    
084            public static String getPortalClassPath() {
085                    return _portalClassPath;
086            }
087    
088            public static void initializeClassPaths(ServletContext servletContext) {
089                    ClassLoader classLoader = PortalClassLoaderUtil.getClassLoader();
090    
091                    if (classLoader == null) {
092                            _log.error("Portal ClassLoader is null");
093    
094                            return;
095                    }
096    
097                    StringBundler sb = new StringBundler(8);
098    
099                    String appServerGlobalClassPath = _buildClassPath(
100                            classLoader, ServletException.class.getName());
101    
102                    sb.append(appServerGlobalClassPath);
103                    sb.append(File.pathSeparator);
104    
105                    String portalGlobalClassPath = _buildClassPath(
106                            classLoader, PortalException.class.getName());
107    
108                    sb.append(portalGlobalClassPath);
109    
110                    _globalClassPath = sb.toString();
111    
112                    sb.append(File.pathSeparator);
113                    sb.append(
114                            _buildClassPath(
115                                    classLoader, "com.liferay.portal.servlet.MainServlet"));
116                    sb.append(File.pathSeparator);
117                    sb.append(servletContext.getRealPath(""));
118                    sb.append("/WEB-INF/classes");
119    
120                    _portalClassPath = sb.toString();
121            }
122    
123            private static String _buildClassPath(
124                    ClassLoader classloader, String className) {
125    
126                    String pathOfClass = StringUtil.replace(
127                            className, CharPool.PERIOD, CharPool.SLASH);
128    
129                    pathOfClass = pathOfClass.concat(".class");
130    
131                    URL url = classloader.getResource(pathOfClass);
132    
133                    if (_log.isDebugEnabled()) {
134                            _log.debug("Build class path from " + url);
135                    }
136    
137                    String protocol = url.getProtocol();
138    
139                    if (protocol.equals("bundle") || protocol.equals("bundleresource")) {
140                            try {
141                                    URLConnection urlConnection = url.openConnection();
142    
143                                    Class<?> clazz = urlConnection.getClass();
144    
145                                    Method getLocalURLMethod = clazz.getDeclaredMethod(
146                                            "getLocalURL");
147    
148                                    getLocalURLMethod.setAccessible(true);
149    
150                                    url = (URL)getLocalURLMethod.invoke(urlConnection);
151                            }
152                            catch (Exception e) {
153                                    _log.error("Unable to resolve local URL from bundle", e);
154    
155                                    return StringPool.BLANK;
156                            }
157                    }
158    
159                    String path = URLCodec.decodeURL(url.getPath());
160    
161                    if (_log.isDebugEnabled()) {
162                            _log.debug("Path " + path);
163                    }
164    
165                    path = StringUtil.replace(path, CharPool.BACK_SLASH, CharPool.SLASH);
166    
167                    if (_log.isDebugEnabled()) {
168                            _log.debug("Decoded path " + path);
169                    }
170    
171                    if (ServerDetector.isWebLogic() && protocol.equals("zip")) {
172                            path = "file:".concat(path);
173                    }
174    
175                    if (ServerDetector.isJBoss() &&
176                            (protocol.equals("vfs") || protocol.equals("vfsfile"))) {
177    
178                            int pos = path.indexOf(".jar/");
179    
180                            if (pos != -1) {
181                                    String jarFilePath = path.substring(0, pos + 4);
182    
183                                    File jarFile = new File(jarFilePath);
184    
185                                    if (jarFile.isFile()) {
186                                            path = jarFilePath + '!' + path.substring(pos + 4);
187                                    }
188                            }
189    
190                            path = "file:".concat(path);
191                    }
192    
193                    File dir = null;
194    
195                    int pos = -1;
196    
197                    if (!path.startsWith("file:") ||
198                            ((pos = path.indexOf(CharPool.EXCLAMATION)) == -1)) {
199    
200                            if (!path.endsWith(pathOfClass)) {
201                                    _log.error(
202                                            "Class " + className + " is not loaded from a JAR file");
203    
204                                    return StringPool.BLANK;
205                            }
206    
207                            String classesDirName = path.substring(
208                                    0, path.length() - pathOfClass.length());
209    
210                            if (!classesDirName.endsWith("/WEB-INF/classes/")) {
211                                    _log.error(
212                                            "Class " + className + " is not loaded from a standard " +
213                                                    "location (/WEB-INF/classes)");
214    
215                                    return StringPool.BLANK;
216                            }
217    
218                            String libDirName = classesDirName.substring(
219                                    0, classesDirName.length() - "classes/".length());
220    
221                            libDirName += "/lib";
222    
223                            dir = new File(libDirName);
224                    }
225                    else {
226                            pos = path.lastIndexOf(CharPool.SLASH, pos);
227    
228                            dir = new File(path.substring("file:".length(), pos));
229                    }
230    
231                    if (!dir.isDirectory()) {
232                            _log.error(dir.toString() + " is not a directory");
233    
234                            return StringPool.BLANK;
235                    }
236    
237                    File[] files = dir.listFiles();
238    
239                    Arrays.sort(files);
240    
241                    StringBundler sb = new StringBundler(files.length * 2);
242    
243                    for (File file : files) {
244                            sb.append(file.getAbsolutePath());
245                            sb.append(File.pathSeparator);
246                    }
247    
248                    sb.setIndex(sb.index() - 1);
249    
250                    return sb.toString();
251            }
252    
253            private static Log _log = LogFactoryUtil.getLog(ClassPathUtil.class);
254    
255            private static String _globalClassPath;
256            private static String _portalClassPath;
257    
258    }