001    /**
002     * Copyright (c) 2000-2012 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.servlet;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.util.CharPool;
020    import com.liferay.portal.kernel.util.StringPool;
021    import com.liferay.portal.kernel.util.StringUtil;
022    
023    import java.io.IOException;
024    
025    import java.net.MalformedURLException;
026    import java.net.URL;
027    import java.net.URLConnection;
028    
029    import java.util.HashSet;
030    import java.util.Set;
031    import java.util.jar.JarEntry;
032    import java.util.jar.JarInputStream;
033    
034    import javax.servlet.ServletContext;
035    
036    /**
037     * @author Brian Wing Shun Chan
038     * @author Raymond Augé
039     */
040    public class ServletContextUtil {
041    
042            public static Set<String> getClassNames(ServletContext servletContext)
043                    throws IOException {
044    
045                    Set<String> classNames = new HashSet<String>();
046    
047                    _getClassNames(servletContext, "/WEB-INF/classes", classNames);
048                    _getClassNames(servletContext, "/WEB-INF/lib", classNames);
049    
050                    return classNames;
051            }
052    
053            public static long getLastModified(ServletContext servletContext) {
054                    return getLastModified(servletContext, StringPool.SLASH);
055            }
056    
057            public static long getLastModified(
058                    ServletContext servletContext, String resourcePath) {
059    
060                    return getLastModified(servletContext, resourcePath, false);
061            }
062    
063            public static long getLastModified(
064                    ServletContext servletContext, String resourcePath, boolean cache) {
065    
066                    if (cache) {
067                            Long lastModified = (Long)servletContext.getAttribute(
068                                    ServletContextUtil.class.getName() + StringPool.PERIOD +
069                                            resourcePath);
070    
071                            if (lastModified != null) {
072                                    return lastModified.longValue();
073                            }
074                    }
075    
076                    long lastModified = 0;
077    
078                    Set<String> resourcePaths = null;
079    
080                    if (resourcePath.endsWith(StringPool.SLASH)) {
081                            resourcePaths = servletContext.getResourcePaths(resourcePath);
082                    }
083                    else {
084                            resourcePaths = new HashSet<String>();
085    
086                            resourcePaths.add(resourcePath);
087                    }
088    
089                    if ((resourcePaths == null) || resourcePaths.isEmpty()) {
090                            if (cache) {
091                                    servletContext.setAttribute(
092                                            ServletContextUtil.class.getName() + StringPool.PERIOD +
093                                                    resourcePath,
094                                            new Long(lastModified));
095                            }
096    
097                            return lastModified;
098                    }
099    
100                    for (String curResourcePath : resourcePaths) {
101                            if (curResourcePath.endsWith(StringPool.SLASH)) {
102                                    long curLastModified = getLastModified(
103                                            servletContext, curResourcePath);
104    
105                                    if (curLastModified > lastModified) {
106                                            lastModified = curLastModified;
107                                    }
108                            }
109                            else {
110                                    try {
111                                            URL resourceURL = servletContext.getResource(
112                                                    curResourcePath);
113    
114                                            if (resourceURL == null) {
115                                                    _log.error(
116                                                            "Resource url for " + curResourcePath + " is null");
117    
118                                                    continue;
119                                            }
120    
121                                            URLConnection urlConnection = resourceURL.openConnection();
122    
123                                            if (urlConnection.getLastModified() > lastModified) {
124                                                    lastModified = urlConnection.getLastModified();
125                                            }
126                                    }
127                                    catch (IOException ioe) {
128                                            _log.error(ioe, ioe);
129                                    }
130                            }
131                    }
132    
133                    if (cache) {
134                            servletContext.setAttribute(
135                                    ServletContextUtil.class.getName() + StringPool.PERIOD +
136                                            resourcePath,
137                                    new Long(lastModified));
138                    }
139    
140                    return lastModified;
141            }
142    
143            public static String getRootPath(ServletContext servletContext)
144                    throws MalformedURLException {
145    
146                    URL rootURL = servletContext.getResource(_PATH_WEB_XML);
147    
148                    String rootPath = rootURL.getPath();
149    
150                    int pos = rootPath.indexOf(_PATH_WEB_XML);
151    
152                    return rootPath.substring(0, pos);
153            }
154    
155            private static String _getClassName(String path) {
156                    return _getClassName(null, path);
157            }
158    
159            private static String _getClassName(String rootResourcePath, String path) {
160                    String className = path.substring(
161                            0, path.length() - _EXT_CLASS.length());
162    
163                    if (rootResourcePath != null) {
164                            className = className.substring(rootResourcePath.length() + 1);
165                    }
166    
167                    className = StringUtil.replace(
168                            className, CharPool.SLASH, CharPool.PERIOD);
169    
170                    return className;
171            }
172    
173            private static void _getClassNames(
174                            ServletContext servletContext, String rootResourcePath,
175                            Set<String> classNames)
176                    throws IOException {
177    
178                    _getClassNames(
179                            servletContext, rootResourcePath,
180                            servletContext.getResourcePaths(rootResourcePath), classNames);
181            }
182    
183            private static void _getClassNames(
184                            ServletContext servletContext, String rootResourcePath,
185                            Set<String> resourcePaths, Set<String> classNames)
186                    throws IOException {
187    
188                    if (resourcePaths == null) {
189                            return;
190                    }
191    
192                    for (String resourcePath : resourcePaths) {
193                            if (resourcePath.endsWith(_EXT_CLASS)) {
194                                    String className = _getClassName(
195                                            rootResourcePath, resourcePath);
196    
197                                    classNames.add(className);
198                            }
199                            else if (resourcePath.endsWith(_EXT_JAR)) {
200                                    JarInputStream jarFile = new JarInputStream(
201                                            servletContext.getResourceAsStream(resourcePath));
202    
203                                    while (true) {
204                                            JarEntry jarEntry = jarFile.getNextJarEntry();
205    
206                                            if (jarEntry == null) {
207                                                    break;
208                                            }
209    
210                                            String jarEntryName = jarEntry.getName();
211    
212                                            if (jarEntryName.endsWith(_EXT_CLASS)) {
213                                                    String className = _getClassName(jarEntryName);
214    
215                                                    classNames.add(className);
216                                            }
217                                    }
218    
219                                    jarFile.close();
220    
221                            }
222                            else if (resourcePath.endsWith(StringPool.SLASH)) {
223                                    _getClassNames(
224                                            servletContext, rootResourcePath,
225                                            servletContext.getResourcePaths(resourcePath), classNames);
226                            }
227                    }
228            }
229    
230            private static final String _EXT_CLASS = ".class";
231    
232            private static final String _EXT_JAR = ".jar";
233    
234            private static final String _PATH_WEB_XML = "/WEB-INF/web.xml";
235    
236            private static Log _log = LogFactoryUtil.getLog(ServletContextUtil.class);
237    
238    }