From b0fc83ee058ddf51c8ffadc7f0626ecedddbae5f Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Mon, 17 Jul 2017 08:16:25 +0200 Subject: [PATCH] Polish CssLinkResourceTransformer --- .../resource/CssLinkResourceTransformer.java | 91 +++++++++---------- 1 file changed, 41 insertions(+), 50 deletions(-) diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/CssLinkResourceTransformer.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/CssLinkResourceTransformer.java index 05d514bc175..8aa3002268e 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/CssLinkResourceTransformer.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/CssLinkResourceTransformer.java @@ -22,9 +22,10 @@ import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; -import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; import javax.servlet.http.HttpServletRequest; import org.apache.commons.logging.Log; @@ -82,25 +83,23 @@ public class CssLinkResourceTransformer extends ResourceTransformerSupport { byte[] bytes = FileCopyUtils.copyToByteArray(resource.getInputStream()); String content = new String(bytes, DEFAULT_CHARSET); - List linkSegments = new ArrayList<>(8); + SortedSet links = new TreeSet<>(); for (LinkParser parser : this.linkParsers) { - linkSegments.addAll(parser.parseLink(content)); + parser.parse(content, links); } - if (linkSegments.isEmpty()) { + if (links.isEmpty()) { if (logger.isTraceEnabled()) { logger.trace("No links found."); } return resource; } - Collections.sort(linkSegments); - int index = 0; StringWriter writer = new StringWriter(); - for (Segment linkSegment : linkSegments) { - writer.write(content.substring(index, linkSegment.getStart())); - String link = content.substring(linkSegment.getStart(), linkSegment.getEnd()); + for (ContentChunkInfo linkContentChunkInfo : links) { + writer.write(content.substring(index, linkContentChunkInfo.getStart())); + String link = content.substring(linkContentChunkInfo.getStart(), linkContentChunkInfo.getEnd()); String newLink = null; if (!hasScheme(link)) { String absolutePath = toAbsolutePath(link, request); @@ -115,7 +114,7 @@ public class CssLinkResourceTransformer extends ResourceTransformerSupport { } } writer.write(newLink != null ? newLink : link); - index = linkSegment.getEnd(); + index = linkContentChunkInfo.getEnd(); } writer.write(content.substring(index)); @@ -128,60 +127,51 @@ public class CssLinkResourceTransformer extends ResourceTransformerSupport { } + /** + * Extract content chunks that represent links. + */ @FunctionalInterface protected interface LinkParser { - Set parseLink(String content); + void parse(String content, SortedSet result); } protected static abstract class AbstractLinkParser implements LinkParser { - /** - * Return the keyword to use to search for links. - */ + /** Return the keyword to use to search for links, e.g. "@import", "url(" */ protected abstract String getKeyword(); @Override - public Set parseLink(String content) { - Set linksToAdd = new HashSet<>(8); - int index = 0; - do { - index = content.indexOf(getKeyword(), index); - if (index == -1) { - break; + public void parse(String content, SortedSet result) { + int position = 0; + while (true) { + position = content.indexOf(getKeyword(), position); + if (position == -1) { + return; } - index = skipWhitespace(content, index + getKeyword().length()); - if (content.charAt(index) == '\'') { - index = addLink(index, "'", content, linksToAdd); + position += getKeyword().length(); + while (Character.isWhitespace(content.charAt(position))) { + position++; } - else if (content.charAt(index) == '"') { - index = addLink(index, "\"", content, linksToAdd); + if (content.charAt(position) == '\'') { + position = extractLink(position, "'", content, result); } - else { - index = extractLink(index, content, linksToAdd); - + else if (content.charAt(position) == '"') { + position = extractLink(position, "\"", content, result); } - } - while (true); - return linksToAdd; - } + else { + position = extractLink(position, content, result); - private int skipWhitespace(String content, int index) { - while (true) { - if (Character.isWhitespace(content.charAt(index))) { - index++; - continue; } - return index; } } - protected int addLink(int index, String endKey, String content, Set linksToAdd) { + protected int extractLink(int index, String endKey, String content, SortedSet linksToAdd) { int start = index + 1; int end = content.indexOf(endKey, start); - linksToAdd.add(new Segment(start, end)); + linksToAdd.add(new ContentChunkInfo(start, end)); return end + endKey.length(); } @@ -189,7 +179,8 @@ public class CssLinkResourceTransformer extends ResourceTransformerSupport { * Invoked after a keyword match, after whitespaces removed, and when * the next char is neither a single nor double quote. */ - protected abstract int extractLink(int index, String content, Set linksToAdd); + protected abstract int extractLink(int index, String content, + SortedSet linksToAdd); } @@ -202,7 +193,7 @@ public class CssLinkResourceTransformer extends ResourceTransformerSupport { } @Override - protected int extractLink(int index, String content, Set linksToAdd) { + protected int extractLink(int index, String content, SortedSet linksToAdd) { if (content.substring(index, index + 4).equals("url(")) { // Ignore, UrlLinkParser will take care } @@ -222,20 +213,20 @@ public class CssLinkResourceTransformer extends ResourceTransformerSupport { } @Override - protected int extractLink(int index, String content, Set linksToAdd) { + protected int extractLink(int index, String content, SortedSet linksToAdd) { // A url() function without unquoted - return addLink(index - 1, ")", content, linksToAdd); + return extractLink(index - 1, ")", content, linksToAdd); } } - private static class Segment implements Comparable { + private static class ContentChunkInfo implements Comparable { private final int start; private final int end; - public Segment(int start, int end) { + ContentChunkInfo(int start, int end) { this.start = start; this.end = end; } @@ -249,7 +240,7 @@ public class CssLinkResourceTransformer extends ResourceTransformerSupport { } @Override - public int compareTo(Segment other) { + public int compareTo(ContentChunkInfo other) { return (this.start < other.start ? -1 : (this.start == other.start ? 0 : 1)); } @@ -258,8 +249,8 @@ public class CssLinkResourceTransformer extends ResourceTransformerSupport { if (this == obj) { return true; } - if (obj instanceof Segment) { - Segment other = (Segment) obj; + if (obj instanceof ContentChunkInfo) { + ContentChunkInfo other = (ContentChunkInfo) obj; return (this.start == other.start && this.end == other.end); } return false;