/** * Starts bundle usage by creating new {@link BundleAction}. */ public BundleAction start(final String servletPath, final String bundleName) { return new BundleAction(this, servletPath, bundleName); }
public HtmlStaplerTagAdapter(final HtmlStaplerBundlesManager bundlesManager, final String servletPath, final TagVisitor target) { super(target); this.bundlesManager = bundlesManager; jsBundleAction = bundlesManager.start(servletPath, "js"); cssBundleAction = bundlesManager.start(servletPath, "css"); insideConditionalComment = false; }
/** * Post process final content. Required for <code>RESOURCE_ONLY</code> strategy. */ public char[] postProcess(char[] content) { content = jsBundleAction.replaceBundleId(content); content = cssBundleAction.replaceBundleId(content); return content; } }
File bundleFile = createBundleFile(bundleId); if (bundleFile.exists()) { return; if (isExternalResource(src)) { try { content = NetUtil.downloadString(src, localFilesEncoding); if (isCssResource(src)) { content = fixCssRelativeUrls(content, src); content = onResourceContent(content); sb.append(content);
@Override protected boolean processActionPath(final HttpServletRequest servletRequest, final HttpServletResponse servletResponse, final String actionPath) throws IOException { String bundlePath = '/' + bundlesManager.getStaplerPath() + '/'; if (!actionPath.startsWith(bundlePath)) { return false; } String bundleId = actionPath.substring(bundlePath.length()); File file = bundlesManager.lookupBundleFile(bundleId); if (log.isDebugEnabled()) { log.debug("bundle: " + bundleId); } int ndx = bundleId.lastIndexOf('.'); String extension = bundleId.substring(ndx + 1); String contentType = MimeTypes.getMimeType(extension); servletResponse.setContentType(contentType); if (useGzip && ServletUtil.isGzipSupported(servletRequest)) { file = bundlesManager.lookupGzipBundleFile(file); servletResponse.setHeader("Content-Encoding", "gzip"); } if (!file.exists()) { throw new IOException("bundle not found: " + bundleId); } servletResponse.setHeader("Content-Length", String.valueOf(file.length())); servletResponse.setHeader("Last-Modified", TimeUtil.formatHttpDate(file.lastModified())); if (cacheMaxAge > 0) { servletResponse.setHeader("Cache-Control", "max-age=" + cacheMaxAge); } sendBundleFile(servletResponse, file); return true; }
String bundleId = createDigest(sourcesString); bundleId += '.' + bundleContentType; createBundle(contextPath, actionPath, bundleId, sources); } catch (IOException ioex) { throw new HtmlStaplerException("Can't create bundle", ioex);
@Test void testRandomDigest() { HtmlStaplerBundlesManager hsbm = new HtmlStaplerBundlesManager("/ctx", "/", RESOURCES_ONLY); String digest = hsbm.createDigest("source"); hsbm.setRandomDigestChars(5); String digest2 = hsbm.createDigest("source"); String digest3 = hsbm.createDigest("source"); assertEquals(digest2, digest3); assertTrue(digest2.startsWith(digest)); hsbm.setRandomDigestChars(0); digest2 = hsbm.createDigest("source"); assertEquals(digest, digest2); } }
@Override protected char[] parse(final TagWriter rootTagWriter, final HttpServletRequest request) { TagVisitor visitor = rootTagWriter; if (stripHtml) { visitor = new StripHtmlTagAdapter(rootTagWriter) { @Override public void end() { super.end(); if (log.isDebugEnabled()) { log.debug("Stripped: " + getStrippedCharsCount() + " chars"); } } }; } String servletPath = DispatcherUtil.getServletPath(request); HtmlStaplerTagAdapter htmlStaplerTagAdapter = new HtmlStaplerTagAdapter(bundlesManager, servletPath, visitor); // todo add more adapters char[] content = invokeLagarto(htmlStaplerTagAdapter); return htmlStaplerTagAdapter.postProcess(content); } };
/** * Creates new bundle action. */ public BundleAction(final HtmlStaplerBundlesManager bundlesManager, final String servletPath, final String bundleContentType) { this.bundlesManager = bundlesManager; this.bundleContentType = bundleContentType; this.strategy = bundlesManager.getStrategy(); String realActionPath = bundlesManager.resolveRealActionPath(servletPath); actionPath = realActionPath + '*' + bundleContentType; contextPath = bundlesManager.contextPath; if (strategy == ACTION_MANAGED) { bundleId = bundlesManager.lookupBundleId(actionPath); newAction = (bundleId == null); if (newAction) { sources = new ArrayList<>(); } } else { bundleId = BUNDLE_ID_MARKER + bundleContentType; bundleIdMark = bundleId.toCharArray(); newAction = true; sources = new ArrayList<>(); } firstScriptTag = true; }
super.init(filterConfig); bundlesManager = createBundleManager(filterConfig.getServletContext(), staplerStrategy); readFilterConfigParameters(filterConfig, this, "enabled", "stripHtml", readFilterConfigParameters(filterConfig, bundlesManager, "bundleFolder", "downloadLocal", bundlesManager.reset();
@Test void testRelativeCssUrls() { HtmlStaplerBundlesManager htmlStapler = new HtmlStaplerBundlesManager("/", "", HtmlStaplerBundlesManager.Strategy.RESOURCES_ONLY); assertEquals( "background: url('/absolute/path')", htmlStapler.fixCssRelativeUrls("background: url(/absolute/path)", "css/")); assertEquals( "background: url('../css/relative/path')", htmlStapler.fixCssRelativeUrls("background: url(relative/path)", "css/")); } }
@Override public void script(final Tag tag, final CharSequence body) { if (!insideConditionalComment) { String src = Util.toString(tag.getAttributeValue("src")); if (src == null) { super.script(tag, body); return; } if (jsBundleAction.acceptLink(src)) { String link = jsBundleAction.processLink(src); if (link != null) { tag.setAttributeValue("src", link); super.script(tag, body); } return; } } super.script(tag, body); }
/** * Process links. Returns bundle link if this is the first resource * of the same type. Otherwise, returns <code>null</code> indicating * that collection is going on and the original link should be removed. */ public String processLink(final String src) { if (newAction) { if (bundleId == null) { bundleId = bundlesManager.registerNewBundleId(); bundleId += '.' + bundleContentType; } sources.add(src); } if (firstScriptTag) { // this is the first tag, change the url to point to the bundle firstScriptTag = false; return buildStaplerUrl(); } else { // ignore all other script tags return null; } }
/** * Creates {@link HtmlStaplerBundlesManager} instance. */ protected HtmlStaplerBundlesManager createBundleManager(final ServletContext servletContext, final Strategy strategy) { String webRoot = servletContext.getRealPath(StringPool.EMPTY); String contextPath = ServletUtil.getContextPath(servletContext); return new HtmlStaplerBundlesManager(contextPath, webRoot, strategy); }
/** * Builds stapler URL based on bundle action data. */ protected String buildStaplerUrl() { return contextPath + '/' + bundlesManager.getStaplerPath() + '/' + bundleId; }
/** * Called on end of parsing. */ public void end() { if (newAction) { bundleId = bundlesManager.registerBundle(contextPath, actionPath, bundleId, bundleContentType, sources); } }
/** * Lookups for bundle file. */ public File lookupBundleFile(String bundleId) { if ((mirrors != null) && (!mirrors.isEmpty())) { String realBundleId = mirrors.remove(bundleId); if (realBundleId != null) { bundleId = realBundleId; } } return createBundleFile(bundleId); }
/** * Returns the content with all relative URLs fixed. */ protected String fixCssRelativeUrls(final String content, final String src) { String path = FileNameUtil.getPath(src); Matcher matcher = CSS_URL_PATTERN.matcher(content); StringBuilder sb = new StringBuilder(content.length()); int start = 0; while (matcher.find()) { sb.append(content.substring(start, matcher.start())); String url = fixRelativeUrl(matcher.group(1), path); sb.append(url); start = matcher.end(); } sb.append(content.substring(start)); return sb.toString(); }
@Override public void tag(final Tag tag) { if (!insideConditionalComment) { if (tag.nameEquals(T_LINK)) { CharSequence type = tag.getAttributeValue("type"); if (type != null && CharSequenceUtil.equalsIgnoreCase(type, "text/css")) { String media = Util.toString(tag.getAttributeValue("media")); if (media == null || media.contains("screen")) { String href = Util.toString(tag.getAttributeValue("href")); if (cssBundleAction.acceptLink(href)) { String link = cssBundleAction.processLink(href); if (link != null) { tag.setAttribute("href", link); super.tag(tag); } return; } } } } } super.tag(tag); }