@Override public int execute(ModuleRequest request, ModuleResponse response, ServletContext context) { this.context = context; String url = getURL(request); LOGGER.trace("Started processing request : {}", url); List<String> resourcesToMerge = Utils.findResourcesToMerge(request.getContextPath(), url); // If not modified, return 304 and stop ResourceStatus status = isNotModified(request, response, resourcesToMerge); if (status.isNotModified()) { LOGGER.debug("Resources Not Modified. Sending 304."); sendNotModified(response); return STOP_CHAIN; } String extensionOrPath = Utils.detectExtension(url); // in case of non js/css files it null if (extensionOrPath == null) { extensionOrPath = resourcesToMerge.get( 0); // non grouped i.e. non css/js file, we refer it's path in that case } // Add appropriate headers addAppropriateResponseHeaders( extensionOrPath, resourcesToMerge, status.getActualETag(), response); try { OutputStream outputStream = response.getOutputStream(); int resourcesNotFound = processResources( request.getContextPath(), outputStream, resourcesToMerge, autoCorrectUrlsInCss); if (resourcesNotFound > 0 && resourcesNotFound == resourcesToMerge.size()) { // all resources not found response.sendError(HttpServletResponse.SC_NOT_FOUND); LOGGER.warn("All resources are not found. Sending 404."); return STOP_CHAIN; } if (outputStream != null) { // try { response.setStatus(HttpServletResponse.SC_OK); outputStream.close(); // response.commit(); // } catch (IOException e) { // e.printStackTrace(); // LOGGER.error(Utils.buildLoggerMessage("Response commit failed.", e.getMessage())); // return IRule.Status.CONTINUE; // } } } catch (IOException ex) { // ex.printStackTrace(); LOGGER.error("Error in processing request.", ex); return OK; } LOGGER.debug("Finished processing Request : {}", url); return STOP_CHAIN; }
public void setupRequest() { super.setupRequest(); boolean removePreviousFilters = Utils.readBoolean( properties.getProperty(this.currentTestNumber + ".test.removePreviousFilters"), true); if (removePreviousFilters) { filters.clear(); servletTestModule.setDoChain(false); } else { for (Filter filter : filters) { servletTestModule.addFilter(filter); servletTestModule.setDoChain(true); } } String filter = properties.getProperty(this.currentTestNumber + ".test.filter"); if (filter != null && !filter.trim().equals("")) { String[] filtersString = filter.split(","); for (String filterClass : filtersString) { Class<?> clazz = null; try { clazz = Class.forName(filterClass); Filter f = servletTestModule.createFilter(clazz); if (!filters.contains(f)) { filters.add(f); servletTestModule.setDoChain(true); } } catch (ClassNotFoundException e) { LOGGER.debug("Error: ", e); } } } }
@Override public DirectivePair parseDirectives(String ruleString) { DirectivePair pair = null; int index = 0; boolean autoCorrectUrlsInCss = true; String[] splits = ruleString.split("\\s+"); assert splits.length >= 1; if (!splits[index++].equals(JSCSSMergeModule.class.getSimpleName())) return pair; if (splits.length > 1) { if ("autoCorrectUrlsInCss".equals(splits[index++])) { if (splits.length > 2) { autoCorrectUrlsInCss = Utils.readBoolean(splits[index], true); } } } pair = new DirectivePair(new JSCSSMergeDirective(autoCorrectUrlsInCss), null); return pair; }
/** * @param request - HttpServletRequest * @param response - HttpServletResponse * @param resourcesToMerge - List of resources relative paths * @return true if not modified based on if-None-Match and If-Modified-Since */ private ResourceStatus isNotModified( HttpServletRequest request, HttpServletResponse response, List<String> resourcesToMerge) { // If-Modified-Since String ifModifiedSince = request.getHeader(HTTP_IF_MODIFIED_SINCE); if (ifModifiedSince != null) { Date date = Utils.readDateFromHeader(ifModifiedSince); if (date != null) { if (!Utils.isAnyResourceModifiedSince(resourcesToMerge, date.getTime(), context)) { this.sendNotModified(response); return new ResourceStatus(null, true); } } } // If-None-match String requestETag = request.getHeader(HTTP_IF_NONE_MATCH_HEADER); String actualETag = Utils.buildETagForResources(resourcesToMerge, context); if (!Utils.isAnyResourceETagModified(resourcesToMerge, requestETag, actualETag, context)) { return new ResourceStatus(actualETag, true); } return new ResourceStatus(actualETag, false); }
@Override public DirectivePair parseDirectives(String ruleString) { DirectivePair pair = null; int index = 0; int lineBreak = -1; boolean noMunge = false; boolean preserveSemi = false; boolean disableOptimizations = false; String charset = DEFAULT_CHARSET; String[] splits = ruleString.split("\\s+"); if (!splits[index++].equals(YUICompressModule.class.getSimpleName())) return pair; while (index < splits.length) { if ((splits[index++]).equalsIgnoreCase(INIT_PARAM_LINE_BREAK)) { lineBreak = Utils.readInt(splits[index++], lineBreak); } else if ((splits[index++]).equalsIgnoreCase(INIT_PARAM_NO_MUNGE)) { noMunge = Utils.readBoolean(splits[index++], noMunge); } else if ((splits[index++]).equalsIgnoreCase(INIT_PARAM_PRESERVE_SEMI)) { preserveSemi = Utils.readBoolean(splits[index++], preserveSemi); } else if ((splits[index++]).equalsIgnoreCase(INIT_PARAM_DISABLE_OPTIMIZATIONS)) { disableOptimizations = Utils.readBoolean(splits[index++], disableOptimizations); } else if ((splits[index++]).equalsIgnoreCase(INIT_PARAM_CHARSET)) { charset = Utils.readString(splits[index++], charset); } } pair = new YUICompressRulesPair( new PreMinifyDirective(lineBreak, noMunge, preserveSemi, disableOptimizations, charset), null); return pair; }
public boolean hasCorrectDateHeaders() { Date now = new Date(); Date lastModified = Utils.readDateFromHeader( webMockObjectFactory.getMockResponse().getHeader(HEADER_LAST_MODIFIED)); Date expires = Utils.readDateFromHeader(webMockObjectFactory.getMockResponse().getHeader(HEADER_EXPIRES)); if (lastModified == null || expires == null) return false; long differenceInMilliseconds = expires.getTime() - now.getTime(); // !TODO test lastModified value return (expiresMinutes - differenceInMilliseconds <= 5 * 1000); // ensure difference between last modified and expires is almost same (tolerate // 5 sec) }
/** * @param extensionOrFile - .css or .js etc. (lower case) or the absolute path of the file in case * of image files * @param resourcesToMerge - from request * @param hashForETag - from request * @param resp - response object */ private void addAppropriateResponseHeaders( String extensionOrFile, List<String> resourcesToMerge, String hashForETag, HttpServletResponse resp) { String mime = Utils.selectMimeForExtension(extensionOrFile); if (mime != null) { LOGGER.trace("Setting MIME to ", mime); resp.setContentType(mime); } if (hashForETag != null) { resp.addHeader(HTTP_ETAG_HEADER, hashForETag); LOGGER.trace("Added ETag headers"); } resp.addHeader(HEADER_X_OPTIMIZED_BY, X_OPTIMIZED_BY_VALUE); }
/** * @param context - ServletContext * @param contextPath - context path or custom configured context path * @param cssFilePath - css file path * @param line - one single line in a css file * @return processed string with appropriate replacement of image URLs if any */ private String processCSSLine( ServletContext context, String contextPath, String cssFilePath, StringBuffer line) { Matcher matcher = CSS_IMG_URL_PATTERN.matcher(line); String cssRealPath = context.getRealPath(cssFilePath); while (matcher.find()) { String refImgPath = matcher.group(1); if (!Utils.isProtocolURL(refImgPath)) { // ignore absolute protocol paths String resolvedImgPath = refImgPath; if (!refImgPath.startsWith("/")) { resolvedImgPath = Utils.buildProperPath(Utils.getParentPath(cssFilePath), refImgPath); } String imgRealPath = context.getRealPath(resolvedImgPath); String fingerPrint = Utils.buildETagForResource(resolvedImgPath, context); int offset = line.indexOf(refImgPath); line.replace( offset, // from offset + refImgPath.length(), // to contextPath + Utils.addFingerPrint(fingerPrint, resolvedImgPath)); Utils.updateReferenceMap(cssRealPath, imgRealPath); } } return line.toString(); }
/** * @param request HttpServletRequest * @return The URL without fingerprint if it has any */ private String getURL(HttpServletRequest request) { return Utils.removeFingerPrint(request.getRequestURI()); }