@Override public void doFilter( ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse; String url = httpServletRequest.getRequestURI(); httpServletResponse.setHeader(CACHE_HEADER, CacheState.SKIPPED.toString()); if (!isURLAccepted(url) || !isQueryStringAccepted(httpServletRequest.getQueryString()) || !isUserAgentAccepted(httpServletRequest.getHeader(Constants.HTTP_USER_AGENT_HEADER))) { LOGGER.debug("Skipping Cache filter for: {}?{}", url, httpServletRequest.getQueryString()); LOGGER.debug("URL, QueryString or UserAgent not accepted"); filterChain.doFilter(servletRequest, servletResponse); return; } long now = new Date().getTime(); CacheObject cacheObject = cache.getIfPresent(url); boolean expireCache = httpServletRequest.getParameter(Constants.PARAM_EXPIRE_CACHE) != null; if (expireCache) { LOGGER.trace("Removing Cache for {} due to URL parameter.", url); cache.invalidate(url); } boolean resetCache = httpServletRequest.getParameter(Constants.PARAM_RESET_CACHE) != null || resetTime > 0 && (now - lastResetTime) / 1000 > resetTime; if (resetCache) { LOGGER.trace("Resetting whole Cache for {} due to URL parameter.", url); cache.invalidateAll(); // fixme: we don't need reset since cache values are soft referenced. lastResetTime = now; } boolean skipCache = httpServletRequest.getParameter(Constants.PARAM_DEBUG) != null || httpServletRequest.getParameter(Constants.PARAM_SKIP_CACHE) != null; if (skipCache) { filterChain.doFilter(servletRequest, servletResponse); LOGGER.trace("Skipping Cache for {} due to URL parameter.", url); return; } List<String> requestedResources = findResourcesToMerge(httpServletRequest.getContextPath(), url); ServletContext context = filterConfig.getServletContext(); String extensionOrPath = detectExtension(url); // in case of non js/css files it null if (extensionOrPath == null) { extensionOrPath = requestedResources.get( 0); // non grouped i.e. non css/js file, we refer it's path in that case } JSCSSMergeServlet.ResourceStatus status = JSCSSMergeServlet.isNotModified(context, httpServletRequest, requestedResources, false); if (status.isNotModified()) { LOGGER.trace("Resources Not Modified. Sending 304."); cache.invalidate(url); JSCSSMergeServlet.sendNotModified( httpServletResponse, extensionOrPath, status.getActualETag(), DEFAULT_EXPIRES_MINUTES, DEFAULT_CACHE_CONTROL); return; } boolean cacheFound = false; if (cacheObject != null && cacheObject.getWebUtilitiesResponseWrapper() != null) { if (requestedResources != null && isAnyResourceModifiedSince(requestedResources, cacheObject.getTime(), context)) { LOGGER.trace("Some resources have been modified since last cache: {}", url); cache.invalidate(url); cacheFound = false; } else { LOGGER.trace("Found valid cached response."); // cacheObject.increaseAccessCount(); cacheFound = true; } } if (cacheFound) { LOGGER.debug("Returning Cached response."); cacheObject.getWebUtilitiesResponseWrapper().fill(httpServletResponse); httpServletResponse.setHeader(CACHE_HEADER, CacheState.FOUND.toString()); // fillResponseFromCache(httpServletResponse, cacheObject.getModuleResponse()); } else { LOGGER.trace("Cache not found or invalidated"); httpServletResponse.setHeader(CACHE_HEADER, CacheState.NOT_FOUND.toString()); WebUtilitiesResponseWrapper wrapper = new WebUtilitiesResponseWrapper(httpServletResponse); filterChain.doFilter(servletRequest, wrapper); // some filters return no status code, but we believe that it is "200 OK" if (wrapper.getStatus() == 0) { wrapper.setStatus(200); } if (isMIMEAccepted(wrapper.getContentType()) && !expireCache && !resetCache && wrapper.getStatus() == 200) { // Cache only 200 status response cache.put(url, new CacheObject(getLastModifiedFor(requestedResources, context), wrapper)); LOGGER.debug("Cache added for: {}", url); httpServletResponse.setHeader(CACHE_HEADER, CacheState.ADDED.toString()); } else { LOGGER.trace("Cache NOT added for: {}", url); LOGGER.trace("is MIME not accepted: {}", isMIMEAccepted(wrapper.getContentType())); LOGGER.trace("is expireCache: {}", expireCache); LOGGER.trace("is resetCache: {}", resetCache); } wrapper.fill(httpServletResponse); } }