PageRenderTime 115ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/b3log-solo/core/src/main/java/org/b3log/solo/filter/PageCacheFilter.java

http://b3log-solo.googlecode.com/
Java | 215 lines | 139 code | 28 blank | 48 comment | 9 complexity | c0ea51b8b5ecfaf7716964ae069c4822 MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.1
  1. /*
  2. * Copyright (c) 2009, 2010, 2011, 2012, B3log Team
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.b3log.solo.filter;
  17. import java.util.logging.Level;
  18. import java.util.logging.Logger;
  19. import java.io.IOException;
  20. import java.io.PrintWriter;
  21. import javax.servlet.Filter;
  22. import javax.servlet.FilterChain;
  23. import javax.servlet.FilterConfig;
  24. import javax.servlet.ServletException;
  25. import javax.servlet.ServletRequest;
  26. import javax.servlet.ServletResponse;
  27. import javax.servlet.http.HttpServletRequest;
  28. import javax.servlet.http.HttpServletResponse;
  29. import org.apache.commons.lang.time.DateFormatUtils;
  30. import org.b3log.latke.Keys;
  31. import org.b3log.latke.Latkes;
  32. import org.b3log.latke.action.AbstractCacheablePageAction;
  33. import org.b3log.latke.cache.PageCaches;
  34. import org.b3log.latke.repository.RepositoryException;
  35. import org.b3log.latke.service.LangPropsService;
  36. import org.b3log.latke.service.ServiceException;
  37. import org.b3log.latke.util.StaticResources;
  38. import org.b3log.latke.util.Strings;
  39. import org.b3log.solo.model.Article;
  40. import org.b3log.solo.model.Common;
  41. import org.b3log.solo.model.PageTypes;
  42. import org.b3log.solo.processor.util.TopBars;
  43. import org.b3log.solo.repository.ArticleRepository;
  44. import org.b3log.solo.repository.impl.ArticleRepositoryImpl;
  45. import org.b3log.solo.util.Articles;
  46. import org.b3log.solo.util.Statistics;
  47. import org.json.JSONException;
  48. import org.json.JSONObject;
  49. /**
  50. * Page cache filter.
  51. *
  52. * @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
  53. * @version 1.0.0.9, Mar 31, 2012
  54. * @since 0.3.1
  55. */
  56. public final class PageCacheFilter implements Filter {
  57. /**
  58. * Logger.
  59. */
  60. private static final Logger LOGGER = Logger.getLogger(PageCacheFilter.class.getName());
  61. /**
  62. * Statistic utilities.
  63. */
  64. private Statistics statistics = Statistics.getInstance();
  65. /**
  66. * Article repository.
  67. */
  68. private ArticleRepository articleRepository = ArticleRepositoryImpl.getInstance();
  69. /**
  70. * Language service.
  71. */
  72. private LangPropsService langPropsService = LangPropsService.getInstance();
  73. /**
  74. * Article utilities.
  75. */
  76. private Articles articles = Articles.getInstance();
  77. @Override
  78. public void init(final FilterConfig filterConfig) throws ServletException {
  79. }
  80. /**
  81. * Try to write response from cache.
  82. *
  83. * @param request the specified request
  84. * @param response the specified response
  85. * @param chain filter chain
  86. * @throws IOException io exception
  87. * @throws ServletException servlet exception
  88. */
  89. @Override
  90. public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
  91. throws IOException, ServletException {
  92. final long startTimeMillis = System.currentTimeMillis();
  93. request.setAttribute(Keys.HttpRequest.START_TIME_MILLIS, startTimeMillis);
  94. final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
  95. final String requestURI = httpServletRequest.getRequestURI();
  96. LOGGER.log(Level.FINER, "Request URI[{0}]", requestURI);
  97. if (StaticResources.isStatic(httpServletRequest)) {
  98. final String path = httpServletRequest.getServletPath() + httpServletRequest.getPathInfo();
  99. LOGGER.log(Level.FINEST, "Requests a static resource, forwards to servlet[path={0}]", path);
  100. request.getRequestDispatcher(path).forward(request, response);
  101. return;
  102. }
  103. if (!Latkes.isPageCacheEnabled()) {
  104. LOGGER.log(Level.FINEST, "Page cache is disabled");
  105. chain.doFilter(request, response);
  106. return;
  107. }
  108. final String skinDirName = (String) httpServletRequest.getAttribute(Keys.TEMAPLTE_DIR_NAME);
  109. if ("mobile".equals(skinDirName)) {
  110. // Mobile request, bypasses page caching
  111. chain.doFilter(request, response);
  112. return;
  113. }
  114. String pageCacheKey;
  115. final String queryString = httpServletRequest.getQueryString();
  116. pageCacheKey = (String) request.getAttribute(Keys.PAGE_CACHE_KEY);
  117. if (Strings.isEmptyOrNull(pageCacheKey)) {
  118. pageCacheKey = PageCaches.getPageCacheKey(requestURI, queryString);
  119. request.setAttribute(Keys.PAGE_CACHE_KEY, pageCacheKey);
  120. }
  121. final JSONObject cachedPageContentObject = PageCaches.get(pageCacheKey, httpServletRequest);
  122. if (null == cachedPageContentObject) {
  123. LOGGER.log(Level.FINER, "Page cache miss for request URI[{0}]", requestURI);
  124. chain.doFilter(request, response);
  125. return;
  126. }
  127. final String cachedType = cachedPageContentObject.optString(AbstractCacheablePageAction.CACHED_TYPE);
  128. try {
  129. // If cached an article that has view password, dispatches the password form
  130. if (langPropsService.get(PageTypes.ARTICLE).equals(cachedType)
  131. && cachedPageContentObject.has(AbstractCacheablePageAction.CACHED_PWD)) {
  132. JSONObject article = new JSONObject();
  133. final String articleId = cachedPageContentObject.optString(AbstractCacheablePageAction.CACHED_OID);
  134. article.put(Keys.OBJECT_ID, articleId);
  135. article.put(Article.ARTICLE_VIEW_PWD, cachedPageContentObject.optString(AbstractCacheablePageAction.CACHED_PWD));
  136. if (articles.needViewPwd(httpServletRequest, article)) {
  137. article = articleRepository.get(articleId); // Loads the article entity
  138. final HttpServletResponse httpServletResponse = (HttpServletResponse) response;
  139. try {
  140. httpServletResponse.sendRedirect(Latkes.getServePath()
  141. + "/console/article-pwd" + articles.buildArticleViewPwdFormParameters(article));
  142. return;
  143. } catch (final Exception e) {
  144. httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND);
  145. return;
  146. }
  147. }
  148. }
  149. } catch (final Exception e) {
  150. LOGGER.log(Level.SEVERE, e.getMessage(), e);
  151. chain.doFilter(request, response);
  152. }
  153. try {
  154. LOGGER.log(Level.FINEST, "Writes resposne for page[pageCacheKey={0}] from cache", pageCacheKey);
  155. response.setContentType("text/html");
  156. response.setCharacterEncoding("UTF-8");
  157. final PrintWriter writer = response.getWriter();
  158. String cachedPageContent = cachedPageContentObject.getString(AbstractCacheablePageAction.CACHED_CONTENT);
  159. final String topBarHTML = TopBars.getTopBarHTML((HttpServletRequest) request, (HttpServletResponse) response);
  160. cachedPageContent = cachedPageContent.replace(Common.TOP_BAR_REPLACEMENT_FLAG, topBarHTML);
  161. final String cachedTitle = cachedPageContentObject.getString(AbstractCacheablePageAction.CACHED_TITLE);
  162. LOGGER.log(Level.FINEST, "Cached value[key={0}, type={1}, title={2}]",
  163. new Object[]{pageCacheKey, cachedType, cachedTitle});
  164. statistics.incBlogViewCount((HttpServletRequest) request);
  165. final long endimeMillis = System.currentTimeMillis();
  166. final String dateString = DateFormatUtils.format(endimeMillis, "yyyy/MM/dd HH:mm:ss");
  167. final String msg = String.format("<!-- Cached by B3log Solo(%1$d ms), %2$s -->", endimeMillis - startTimeMillis, dateString);
  168. LOGGER.finer(msg);
  169. cachedPageContent += Strings.LINE_SEPARATOR + msg;
  170. writer.write(cachedPageContent);
  171. writer.flush();
  172. writer.close();
  173. } catch (final JSONException e) {
  174. LOGGER.log(Level.SEVERE, e.getMessage(), e);
  175. chain.doFilter(request, response);
  176. } catch (final RepositoryException e) {
  177. LOGGER.log(Level.SEVERE, e.getMessage(), e);
  178. chain.doFilter(request, response);
  179. } catch (final ServiceException e) {
  180. LOGGER.log(Level.SEVERE, e.getMessage(), e);
  181. chain.doFilter(request, response);
  182. }
  183. }
  184. @Override
  185. public void destroy() {
  186. }
  187. }