/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.portal.servlet; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.security.pacl.DoPrivileged; import com.liferay.portal.kernel.servlet.DirectServletRegistry; import com.liferay.portal.kernel.util.ReflectionUtil; import com.liferay.portal.kernel.util.StringPool; import com.liferay.portal.util.PropsValues; import java.io.File; import java.lang.reflect.Method; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; /** * @author Shuyang Zhou */ @DoPrivileged public class DirectServletRegistryImpl implements DirectServletRegistry { @Override public void clearServlets() { _servletInfos.clear(); } @Override public Servlet getServlet(String path) { ServletInfo servletInfo = _servletInfos.get(path); if (servletInfo == null) { return null; } Servlet servlet = servletInfo.getServlet(); if (PropsValues.DIRECT_SERVLET_CONTEXT_RELOAD) { long lastModified = getFileLastModified(path, servlet); if ((lastModified == 0) || (lastModified != servletInfo.getLastModified())) { _servletInfos.remove(path); servlet = null; if (_log.isDebugEnabled()) { _log.debug("Reload " + path); } } else { servlet = reloadDependants(path, servlet, servletInfo); } } return servlet; } @Override public void putServlet(String path, Servlet servlet) { if (_servletInfos.containsKey(path)) { return; } long lastModified = 1; if (PropsValues.DIRECT_SERVLET_CONTEXT_RELOAD) { lastModified = getFileLastModified(path, servlet); } if (lastModified > 0) { ServletInfo servletInfo = new ServletInfo(); servletInfo.setLastModified(lastModified); servletInfo.setServlet(servlet); _servletInfos.put(path, servletInfo); } } protected long getFileLastModified(String path, Servlet servlet) { ServletConfig servletConfig = servlet.getServletConfig(); ServletContext servletContext = servletConfig.getServletContext(); String rootPath = servletContext.getRealPath(StringPool.BLANK); File file = new File(rootPath, path); if (file.exists()) { return file.lastModified(); } return -1; } protected Servlet reloadDependants( String path, Servlet servlet, ServletInfo servletInfo) { if (!_reloadDependants) { return servlet; } try { Method method = ReflectionUtil.getDeclaredMethod( servlet.getClass(), "getDependants"); Collection<String> dependants = null; if (JasperVersionDetector.hasJspServletDependantsMap()) { Map<String, ?> dependantsMap = (Map<String, ?>)method.invoke( servlet); if (dependantsMap != null) { dependants = dependantsMap.keySet(); } } else { dependants = (List<String>)method.invoke(servlet); } if (dependants == null) { return servlet; } boolean reloadServlet = false; for (String dependant : dependants) { long lastModified = getFileLastModified(dependant, servlet); Long previousLastModified = _dependantTimestamps.get(dependant); if (previousLastModified == null) { _dependantTimestamps.put(dependant, lastModified); previousLastModified = lastModified; } if ((lastModified == 0) || (lastModified != previousLastModified.longValue())) { reloadServlet = true; _dependantTimestamps.put(dependant, lastModified); if (_log.isDebugEnabled()) { _log.debug("Reload dependant " + dependant); } } } if (reloadServlet) { _servletInfos.remove(path); updateFileLastModified(path, servlet); servlet = null; } } catch (NoSuchMethodException nsme) { if (_log.isWarnEnabled()) { _log.warn( "Reloading of dependant JSP is disabled because your " + "Servlet container is not a variant of Jasper"); } _reloadDependants = false; } catch (Exception e) { _log.error(e, e); } return servlet; } protected void updateFileLastModified(String path, Servlet servlet) { ServletConfig servletConfig = servlet.getServletConfig(); ServletContext servletContext = servletConfig.getServletContext(); String rootPath = servletContext.getRealPath(StringPool.BLANK); File file = new File(rootPath, path); file.setLastModified(System.currentTimeMillis()); } private static final Log _log = LogFactoryUtil.getLog( DirectServletRegistryImpl.class); private final Map<String, Long> _dependantTimestamps = new ConcurrentHashMap<>(); private boolean _reloadDependants = true; private final Map<String, ServletInfo> _servletInfos = new ConcurrentHashMap<>(); private static class ServletInfo { public long getLastModified() { return _lastModified; } public Servlet getServlet() { return _servlet; } public void setLastModified(long lastModified) { _lastModified = lastModified; } public void setServlet(Servlet servlet) { _servlet = servlet; } private long _lastModified; private Servlet _servlet; } }