@ -22,9 +22,10 @@ import java.nio.charset.Charset;
@@ -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 {
@@ -82,25 +83,23 @@ public class CssLinkResourceTransformer extends ResourceTransformerSupport {
byte [ ] bytes = FileCopyUtils . copyToByteArray ( resource . getInputStream ( ) ) ;
String content = new String ( bytes , DEFAULT_CHARSET ) ;
List < Segment > linkSegment s = new ArrayLis t< > ( 8 ) ;
SortedSet < ContentChunkInfo > links = new TreeSe t< > ( ) ;
for ( LinkParser parser : this . linkParsers ) {
linkSegments . addAll ( parser . parseLink ( content ) ) ;
parser . parse ( content , links ) ;
}
if ( linkSegment s . 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 : linkSegment s ) {
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 {
@@ -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 {
@@ -128,60 +127,51 @@ public class CssLinkResourceTransformer extends ResourceTransformerSupport {
}
/ * *
* Extract content chunks that represent links .
* /
@FunctionalInterface
protected interface LinkParser {
Set < Segment > parseLink ( String conten t) ;
void parse ( String content , SortedSet < ContentChunkInfo > resul t) ;
}
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 < Segment > parseLink ( String content ) {
Set < Segment > linksToAdd = new HashSet < > ( 8 ) ;
int index = 0 ;
do {
index = content . indexOf ( getKeyword ( ) , index ) ;
if ( index = = - 1 ) {
break ;
public void parse ( String content , SortedSet < ContentChunkInfo > 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 = add Link( index , "\" " , content , linksToAdd ) ;
if ( content . charAt ( posit io n) = = '\' ' ) {
position = extract Link( posit io n, "' " , 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 add Link( int index , String endKey , String content , Set < Segment > linksToAdd ) {
protected int extractLink ( int index , String endKey , String content , SortedSet < ContentChunkInfo > 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 {
@@ -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 < Segment > linksToAdd ) ;
protected abstract int extractLink ( int index , String content ,
SortedSet < ContentChunkInfo > linksToAdd ) ;
}
@ -202,7 +193,7 @@ public class CssLinkResourceTransformer extends ResourceTransformerSupport {
@@ -202,7 +193,7 @@ public class CssLinkResourceTransformer extends ResourceTransformerSupport {
}
@Override
protected int extractLink ( int index , String content , Set < Segment > linksToAdd ) {
protected int extractLink ( int index , String content , SortedS et < ContentChunkInfo > linksToAdd ) {
if ( content . substring ( index , index + 4 ) . equals ( "url(" ) ) {
// Ignore, UrlLinkParser will take care
}
@ -222,20 +213,20 @@ public class CssLinkResourceTransformer extends ResourceTransformerSupport {
@@ -222,20 +213,20 @@ public class CssLinkResourceTransformer extends ResourceTransformerSupport {
}
@Override
protected int extractLink ( int index , String content , Set < Segment > linksToAdd ) {
protected int extractLink ( int index , String content , SortedS et < ContentChunkInfo > linksToAdd ) {
// A url() function without unquoted
return add Link( index - 1 , ")" , content , linksToAdd ) ;
return extract Link( index - 1 , ")" , content , linksToAdd ) ;
}
}
private static class Segment implements Comparable < Segment > {
private static class ContentChunkInfo implements Comparable < ContentChunkInfo > {
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 {
@@ -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 {
@@ -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 ;