001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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.GetterUtil;
020    import com.liferay.portal.kernel.util.PropsKeys;
021    import com.liferay.portal.kernel.util.PropsUtil;
022    import com.liferay.portal.kernel.util.ReflectionUtil;
023    import com.liferay.portal.kernel.util.StringPool;
024    
025    import java.io.File;
026    
027    import java.lang.reflect.Method;
028    
029    import java.util.List;
030    import java.util.Map;
031    import java.util.concurrent.ConcurrentHashMap;
032    
033    import javax.servlet.Servlet;
034    import javax.servlet.ServletConfig;
035    import javax.servlet.ServletContext;
036    
037    /**
038     * @author Shuyang Zhou
039     */
040    public class DirectServletRegistry {
041    
042            public static void clearServlets() {
043                    _instance._clearServlets();
044            }
045    
046            public static Servlet getServlet(String path) {
047                    return _instance._getServlet(path);
048            }
049    
050            public static void putServlet(String path, Servlet servlet) {
051                    _instance._putServlet(path, servlet);
052            }
053    
054            private DirectServletRegistry() {
055            }
056    
057            private void _clearServlets() {
058                    _servletInfos.clear();
059            }
060    
061            private long _getFileLastModified(String path, Servlet servlet) {
062                    ServletConfig servletConfig = servlet.getServletConfig();
063    
064                    ServletContext servletContext = servletConfig.getServletContext();
065    
066                    String rootPath = servletContext.getRealPath(StringPool.BLANK);
067    
068                    File file = new File(rootPath, path);
069    
070                    return file.lastModified();
071            }
072    
073            private Servlet _getServlet(String path) {
074                    ServletInfo servletInfo = _servletInfos.get(path);
075    
076                    if (servletInfo == null) {
077                            return null;
078                    }
079    
080                    Servlet servlet = servletInfo.getServlet();
081    
082                    if (_DIRECT_SERVLET_CONTEXT_RELOAD) {
083                            long lastModified = _getFileLastModified(path, servlet);
084    
085                            if ((lastModified == 0) ||
086                                    (lastModified > servletInfo.getLastModified())) {
087    
088                                    _servletInfos.remove(path);
089    
090                                    servlet = null;
091    
092                                    if (_log.isDebugEnabled()) {
093                                            _log.debug("Reload " + path);
094                                    }
095                            }
096                            else {
097                                    servlet = _reloadDependents(path, servlet, servletInfo);
098                            }
099                    }
100    
101                    return servlet;
102            }
103    
104            private void _putServlet(String path, Servlet servlet) {
105                    if (_servletInfos.containsKey(path)) {
106                            return;
107                    }
108    
109                    long lastModified = 1;
110    
111                    if (_DIRECT_SERVLET_CONTEXT_RELOAD) {
112                            lastModified = _getFileLastModified(path, servlet);
113                    }
114    
115                    if (lastModified > 0) {
116                            ServletInfo servletInfo = new ServletInfo();
117    
118                            servletInfo.setLastModified(lastModified);
119                            servletInfo.setServlet(servlet);
120    
121                            _servletInfos.put(path, servletInfo);
122                    }
123            }
124    
125            private Servlet _reloadDependents(
126                    String path, Servlet servlet, ServletInfo servletInfo) {
127    
128                    try {
129                            if (!_reloadDependents) {
130                                    return servlet;
131                            }
132    
133                            Method method = ReflectionUtil.getDeclaredMethod(
134                                    servlet.getClass(), "getDependants");
135    
136                            List<String> dependants = (List<String>)method.invoke(
137                                    servlet);
138    
139                            if (dependants == null) {
140                                    return servlet;
141                            }
142    
143                            for (String dependant : dependants) {
144                                    long lastModified = _getFileLastModified(dependant, servlet);
145    
146                                    if ((lastModified == 0) ||
147                                            (lastModified > servletInfo.getLastModified())) {
148    
149                                            _servletInfos.remove(path);
150    
151                                            _updateFileLastModified(path, servlet);
152    
153                                            servlet = null;
154    
155                                            if (_log.isDebugEnabled()) {
156                                                    _log.debug("Reload dependent " + dependant);
157                                            }
158    
159                                            break;
160                                    }
161                            }
162                    }
163                    catch (NoSuchMethodException nsme) {
164                            if (_log.isWarnEnabled()) {
165                                    _log.warn(
166                                            "Reloading of dependant JSP is disabled because your " +
167                                                    "Servlet container is not a variant of Jasper");
168                            }
169    
170                            _reloadDependents = false;
171                    }
172                    catch (Exception e) {
173                            _log.error(e, e);
174                    }
175    
176                    return servlet;
177            }
178    
179            private void _updateFileLastModified(String path, Servlet servlet) {
180                    ServletConfig servletConfig = servlet.getServletConfig();
181    
182                    ServletContext servletContext = servletConfig.getServletContext();
183    
184                    String rootPath = servletContext.getRealPath(StringPool.BLANK);
185    
186                    File file = new File(rootPath, path);
187    
188                    file.setLastModified(System.currentTimeMillis());
189            }
190    
191            private static boolean _DIRECT_SERVLET_CONTEXT_RELOAD =
192                    GetterUtil.getBoolean(
193                            PropsUtil.get(PropsKeys.DIRECT_SERVLET_CONTEXT_RELOAD));
194    
195            private static Log _log = LogFactoryUtil.getLog(
196                    DirectServletRegistry.class);
197    
198            private static DirectServletRegistry _instance =
199                    new DirectServletRegistry();
200    
201            private static boolean _reloadDependents = true;
202    
203            private Map<String, ServletInfo> _servletInfos =
204                    new ConcurrentHashMap<String, ServletInfo>();
205    
206            private class ServletInfo {
207    
208                    public long getLastModified() {
209                            return _lastModified;
210                    }
211    
212                    public Servlet getServlet() {
213                            return _servlet;
214                    }
215    
216                    public void setLastModified(long lastModified) {
217                            _lastModified = lastModified;
218                    }
219    
220                    public void setServlet(Servlet servlet) {
221                            _servlet = servlet;
222                    }
223    
224                    private long _lastModified;
225                    private Servlet _servlet;
226    
227            }
228    
229    }