Author: fschumacher Date: Thu Jan 22 19:16:33 2015 New Revision: 1654013 URL: http://svn.apache.org/r1654013 Log: Enable UEncoder instances to share safeChars BitSet while ensuring that the shared BitSet is immutable to be threadsafe.
Change Response to use UEncoder instances with shared safeChars. Modified: tomcat/trunk/java/org/apache/catalina/connector/Response.java tomcat/trunk/java/org/apache/tomcat/util/buf/UEncoder.java tomcat/trunk/test/org/apache/tomcat/util/buf/TestUEncoder.java Modified: tomcat/trunk/java/org/apache/catalina/connector/Response.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/connector/Response.java?rev=1654013&r1=1654012&r2=1654013&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/connector/Response.java (original) +++ tomcat/trunk/java/org/apache/catalina/connector/Response.java Thu Jan 22 19:16:33 2015 @@ -50,6 +50,7 @@ import org.apache.catalina.util.SessionC import org.apache.coyote.ActionCode; import org.apache.tomcat.util.buf.CharChunk; import org.apache.tomcat.util.buf.UEncoder; +import org.apache.tomcat.util.buf.UEncoder.SafeCharsSet; import org.apache.tomcat.util.http.FastHttpDateFormat; import org.apache.tomcat.util.http.MimeHeaders; import org.apache.tomcat.util.http.parser.MediaTypeCache; @@ -89,7 +90,6 @@ public class Response } public Response() { - urlEncoder.addSafeCharacter('/'); } @@ -241,7 +241,7 @@ public class Response /** * URL encoder. */ - protected final UEncoder urlEncoder = new UEncoder(); + protected final UEncoder urlEncoder = new UEncoder(SafeCharsSet.WITH_SLASH); /** Modified: tomcat/trunk/java/org/apache/tomcat/util/buf/UEncoder.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/buf/UEncoder.java?rev=1654013&r1=1654012&r2=1654013&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/buf/UEncoder.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/buf/UEncoder.java Thu Jan 22 19:16:33 2015 @@ -32,6 +32,22 @@ import java.util.BitSet; */ public final class UEncoder { + public enum SafeCharsSet { + WITH_SLASH("/"), DEFAULT(""); + private final BitSet safeChars; + + private BitSet getSafeChars() { + return this.safeChars; + } + + private SafeCharsSet(String additionalSafeChars) { + safeChars = initialSafeChars(); + for (char c : additionalSafeChars.toCharArray()) { + safeChars.set(c); + } + } + } + // Not static - the set may differ ( it's better than adding // an extra check for "/", "+", etc private BitSet safeChars=null; @@ -39,14 +55,34 @@ public final class UEncoder { private ByteChunk bb=null; private CharChunk cb=null; private CharChunk output=null; + private final boolean readOnlySafeChars; private final String ENCODING = "UTF8"; public UEncoder() { - initSafeChars(); + this.safeChars = initialSafeChars(); + readOnlySafeChars = false; } + /** + * Create a UEncoder with an unmodifiable safe character set. + * <p> + * Calls to {@link UEncoder#addSafeCharacter(char) addSafeCharacter(char)} + * on instances created by this constructor will throw an + * {@link IllegalStateException}. + * + * @param safeCharsSet + * safe characters for this encoder + */ + public UEncoder(SafeCharsSet safeCharsSet) { + this.safeChars = safeCharsSet.getSafeChars(); + readOnlySafeChars = true; + } + public void addSafeCharacter( char c ) { + if (readOnlySafeChars) { + throw new IllegalStateException("UEncoders safeChararacters are read only"); + } safeChars.set( c ); } @@ -116,33 +152,34 @@ public final class UEncoder { // -------------------- Internal implementation -------------------- - private void initSafeChars() { - safeChars=new BitSet(128); + private static BitSet initialSafeChars() { + BitSet initialSafeChars=new BitSet(128); int i; for (i = 'a'; i <= 'z'; i++) { - safeChars.set(i); + initialSafeChars.set(i); } for (i = 'A'; i <= 'Z'; i++) { - safeChars.set(i); + initialSafeChars.set(i); } for (i = '0'; i <= '9'; i++) { - safeChars.set(i); + initialSafeChars.set(i); } //safe - safeChars.set('$'); - safeChars.set('-'); - safeChars.set('_'); - safeChars.set('.'); + initialSafeChars.set('$'); + initialSafeChars.set('-'); + initialSafeChars.set('_'); + initialSafeChars.set('.'); // Dangerous: someone may treat this as " " // RFC1738 does allow it, it's not reserved - // safeChars.set('+'); + // initialSafeChars.set('+'); //extra - safeChars.set('!'); - safeChars.set('*'); - safeChars.set('\''); - safeChars.set('('); - safeChars.set(')'); - safeChars.set(','); + initialSafeChars.set('!'); + initialSafeChars.set('*'); + initialSafeChars.set('\''); + initialSafeChars.set('('); + initialSafeChars.set(')'); + initialSafeChars.set(','); + return initialSafeChars; } } Modified: tomcat/trunk/test/org/apache/tomcat/util/buf/TestUEncoder.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/buf/TestUEncoder.java?rev=1654013&r1=1654012&r2=1654013&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/tomcat/util/buf/TestUEncoder.java (original) +++ tomcat/trunk/test/org/apache/tomcat/util/buf/TestUEncoder.java Thu Jan 22 19:16:33 2015 @@ -20,6 +20,9 @@ package org.apache.tomcat.util.buf; import java.io.IOException; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.apache.tomcat.util.buf.UEncoder.SafeCharsSet; import org.junit.Test; /** @@ -45,4 +48,27 @@ public class TestUEncoder { assertTrue(urlEncoder.encodeURL(s, 0, s.length()) .equals("%f0%90%90%81")); } + + @Test + public void testEncodeURLWithSlashInit() throws IOException { + UEncoder urlEncoder = new UEncoder(SafeCharsSet.WITH_SLASH); + + String s = "a+b/c/d+e.class"; + assertTrue(urlEncoder.encodeURL(s, 0, s.length()).equals( + "a%2bb/c/d%2be.class")); + assertTrue(urlEncoder.encodeURL(s, 2, s.length() - 2).equals( + "b/c/d%2be.cla")); + + try { + urlEncoder.addSafeCharacter('+'); + fail(); + } catch (IllegalStateException e) { + // OK + } + + s = new String(new char[] { 0xD801, 0xDC01 }); + assertTrue(urlEncoder.encodeURL(s, 0, s.length()) + .equals("%f0%90%90%81")); + } + } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org