You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2012/11/03 21:46:03 UTC

svn commit: r1405415 - in /tomcat/trunk: ./ java/org/apache/catalina/authenticator/ java/org/apache/catalina/connector/ java/org/apache/coyote/ java/org/apache/tomcat/util/http/parser/ test/org/apache/tomcat/util/http/parser/

Author: markt
Date: Sat Nov  3 20:46:02 2012
New Revision: 1405415

URL: http://svn.apache.org/viewvc?rev=1405415&view=rev
Log:
Move media-type parsing to the new parser and drop the JJTree based parser.

Added:
    tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser.java
      - copied, changed from r1405399, tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser2.java
Removed:
    tomcat/trunk/java/org/apache/tomcat/util/http/parser/AstAttribute.java
    tomcat/trunk/java/org/apache/tomcat/util/http/parser/AstMediaType.java
    tomcat/trunk/java/org/apache/tomcat/util/http/parser/AstParameter.java
    tomcat/trunk/java/org/apache/tomcat/util/http/parser/AstSubType.java
    tomcat/trunk/java/org/apache/tomcat/util/http/parser/AstType.java
    tomcat/trunk/java/org/apache/tomcat/util/http/parser/AstValue.java
    tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser.jjt
    tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser2.java
    tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParserConstants.java
    tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParserTokenManager.java
    tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParserTreeConstants.java
    tomcat/trunk/java/org/apache/tomcat/util/http/parser/JJTHttpParserState.java
    tomcat/trunk/java/org/apache/tomcat/util/http/parser/Node.java
    tomcat/trunk/java/org/apache/tomcat/util/http/parser/ParseException.java
    tomcat/trunk/java/org/apache/tomcat/util/http/parser/SimpleCharStream.java
    tomcat/trunk/java/org/apache/tomcat/util/http/parser/SimpleNode.java
    tomcat/trunk/java/org/apache/tomcat/util/http/parser/Token.java
    tomcat/trunk/java/org/apache/tomcat/util/http/parser/TokenMgrError.java
Modified:
    tomcat/trunk/build.xml
    tomcat/trunk/java/org/apache/catalina/authenticator/DigestAuthenticator.java
    tomcat/trunk/java/org/apache/catalina/connector/Response.java
    tomcat/trunk/java/org/apache/coyote/Response.java
    tomcat/trunk/java/org/apache/tomcat/util/http/parser/MediaType.java
    tomcat/trunk/java/org/apache/tomcat/util/http/parser/MediaTypeCache.java
    tomcat/trunk/test/org/apache/tomcat/util/http/parser/TestAuthorizationDigest.java
    tomcat/trunk/test/org/apache/tomcat/util/http/parser/TestMediaType.java

Modified: tomcat/trunk/build.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/build.xml?rev=1405415&r1=1405414&r2=1405415&view=diff
==============================================================================
--- tomcat/trunk/build.xml (original)
+++ tomcat/trunk/build.xml Sat Nov  3 20:46:02 2012
@@ -481,7 +481,6 @@
         <!-- Exclude auto-generated files -->
         <exclude name="java/org/apache/el/parser/ELParser*.java" />
         <exclude name="java/org/apache/el/parser/Node.java" />
-        <exclude name="java/org/apache/tomcat/util/http/parser/HttpParser*.java" />
         <exclude name="java/org/apache/**/parser/JJT*ParserState.java" />
         <exclude name="java/org/apache/**/parser/ParseException.java" />
         <exclude name="java/org/apache/**/parser/SimpleCharStream.java" />

Modified: tomcat/trunk/java/org/apache/catalina/authenticator/DigestAuthenticator.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/DigestAuthenticator.java?rev=1405415&r1=1405414&r2=1405415&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/authenticator/DigestAuthenticator.java (original)
+++ tomcat/trunk/java/org/apache/catalina/authenticator/DigestAuthenticator.java Sat Nov  3 20:46:02 2012
@@ -35,7 +35,7 @@ import org.apache.catalina.util.MD5Encod
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.buf.B2CConverter;
-import org.apache.tomcat.util.http.parser.HttpParser2;
+import org.apache.tomcat.util.http.parser.HttpParser;
 
 
 /**
@@ -479,7 +479,7 @@ public class DigestAuthenticator extends
 
             Map<String,String> directives;
             try {
-                directives = HttpParser2.parseAuthorizationDigest(
+                directives = HttpParser.parseAuthorizationDigest(
                         new StringReader(authorization));
             } catch (IOException e) {
                 return false;

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=1405415&r1=1405414&r2=1405415&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/connector/Response.java (original)
+++ tomcat/trunk/java/org/apache/catalina/connector/Response.java Sat Nov  3 20:46:02 2012
@@ -51,7 +51,6 @@ import org.apache.tomcat.util.http.FastH
 import org.apache.tomcat.util.http.MimeHeaders;
 import org.apache.tomcat.util.http.ServerCookie;
 import org.apache.tomcat.util.http.parser.MediaTypeCache;
-import org.apache.tomcat.util.http.parser.ParseException;
 import org.apache.tomcat.util.net.URL;
 import org.apache.tomcat.util.res.StringManager;
 
@@ -709,10 +708,8 @@ public class Response
             return;
         }
 
-        String[] m = null;
-        try {
-             m = MEDIA_TYPE_CACHE.parse(type);
-        } catch (ParseException e) {
+        String[] m = MEDIA_TYPE_CACHE.parse(type);
+        if (m == null) {
             // Invalid - Assume no charset and just pass through whatever
             // the user provided.
             coyoteResponse.setContentTypeNoCharset(type);

Modified: tomcat/trunk/java/org/apache/coyote/Response.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/Response.java?rev=1405415&r1=1405414&r2=1405415&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/Response.java (original)
+++ tomcat/trunk/java/org/apache/coyote/Response.java Sat Nov  3 20:46:02 2012
@@ -25,9 +25,8 @@ import javax.servlet.WriteListener;
 import org.apache.coyote.http11.AbstractOutputBuffer;
 import org.apache.tomcat.util.buf.ByteChunk;
 import org.apache.tomcat.util.http.MimeHeaders;
-import org.apache.tomcat.util.http.parser.AstMediaType;
 import org.apache.tomcat.util.http.parser.HttpParser;
-import org.apache.tomcat.util.http.parser.ParseException;
+import org.apache.tomcat.util.http.parser.MediaType;
 
 /**
  * Response object.
@@ -434,11 +433,13 @@ public final class Response {
             return;
         }
 
-        AstMediaType m = null;
-        HttpParser hp = new HttpParser(new StringReader(type));
+        MediaType m = null;
         try {
-             m = hp.MediaType();
-        } catch (ParseException e) {
+             m = HttpParser.parseMediaType(new StringReader(type));
+        } catch (IOException e) {
+            // Ignore - null test below handles this
+        }
+        if (m == null) {
             // Invalid - Assume no charset and just pass through whatever
             // the user provided.
             this.contentType = type;

Copied: tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser.java (from r1405399, tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser2.java)
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser.java?p2=tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser.java&p1=tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser2.java&r1=1405399&r2=1405415&rev=1405415&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser2.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser.java Sat Nov  3 20:46:02 2012
@@ -19,6 +19,7 @@ package org.apache.tomcat.util.http.pars
 import java.io.IOException;
 import java.io.StringReader;
 import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.Locale;
 import java.util.Map;
 
@@ -39,10 +40,8 @@ import java.util.Map;
  * - MediaType (used for Content-Type header)
  *
  * Support for additional headers will be provided as required.
- *
- * TODO: Replace HttpParser
  */
-public class HttpParser2 {
+public class HttpParser {
 
     private static final Integer FIELD_TYPE_TOKEN = Integer.valueOf(0);
     private static final Integer FIELD_TYPE_QUOTED_STRING = Integer.valueOf(1);
@@ -113,18 +112,15 @@ public class HttpParser2 {
         if (skipConstant(input, "Digest") != SkipConstantResult.FOUND) {
             return null;
         }
-        skipLws(input);
         // All field names are valid tokens
         String field = readToken(input);
         if (field == null) {
             return null;
         }
         while (!field.equals("")) {
-            skipLws(input);
             if (skipConstant(input, "=") != SkipConstantResult.FOUND) {
                 return null;
             }
-            skipLws(input);
             String value = null;
             Integer type = fieldTypes.get(field.toLowerCase(Locale.US));
             if (type == null) {
@@ -163,11 +159,9 @@ public class HttpParser2 {
             }
             result.put(field, value);
 
-            skipLws(input);
             if (skipConstant(input, ",") == SkipConstantResult.NOT_FOUND) {
                 return null;
             }
-            skipLws(input);
             field = readToken(input);
             if (field == null) {
                 return null;
@@ -186,11 +180,9 @@ public class HttpParser2 {
             return null;
         }
 
-        skipLws(input);
         if (skipConstant(input, "/") == SkipConstantResult.NOT_FOUND) {
             return null;
         }
-        skipLws(input);
 
         // Subtype (required)
         String subtype = readToken(input);
@@ -198,60 +190,59 @@ public class HttpParser2 {
             return null;
         }
 
-        skipLws(input);
-
-        Map<String,String> parameters = new HashMap<>();
+        LinkedHashMap<String,String> parameters = new LinkedHashMap<>();
 
         SkipConstantResult lookForSemiColon = skipConstant(input, ";");
         if (lookForSemiColon == SkipConstantResult.NOT_FOUND) {
             return null;
         }
         while (lookForSemiColon == SkipConstantResult.FOUND) {
-            skipLws(input);
             String attribute = readToken(input);
-            skipLws(input);
 
-            if (skipConstant(input, "=") != SkipConstantResult.FOUND) {
-                return null;
+            if (skipConstant(input, "=") == SkipConstantResult.FOUND) {
+                String value = readTokenOrQuotedString(input, true);
+                parameters.put(attribute, value);
+            } else {
+                parameters.put(attribute, "");
             }
 
-            skipLws(input);
-            String value = readTokenOrQuotedString(input, true);
-            skipLws(input);
-
-            parameters.put(attribute.toLowerCase(), value);
-
             lookForSemiColon = skipConstant(input, ";");
             if (lookForSemiColon == SkipConstantResult.NOT_FOUND) {
                 return null;
             }
         }
 
-        String charset = parameters.remove("charset");
-        StringBuilder noCharSet = new StringBuilder();
-        noCharSet.append(type);
-        noCharSet.append('/');
-        noCharSet.append(subtype);
-        for (Map.Entry<String, String> entry : parameters.entrySet()) {
-            noCharSet.append(';');
-            // Workaround for Adobe Read 9 plug-in on IE bug
-            // Can be removed after 26 June 2013 (EOL of Reader 9)
-            // See BZ 53814
-            noCharSet.append(' ');
-            noCharSet.append(entry.getKey());
-            noCharSet.append('=');
-            noCharSet.append(entry.getValue());
+        return new MediaType(type, subtype, parameters);
+    }
+
+    public static String unquote(String input) {
+        if (input == null || input.length() < 2 || input.charAt(0) != '"') {
+            return input;
         }
 
-        return new MediaType(noCharSet.toString(), charset);
+        StringBuilder result = new StringBuilder();
+        for (int i = 1 ; i < (input.length() - 1); i++) {
+            char c = input.charAt(i);
+            if (input.charAt(i) == '\\') {
+                i++;
+                result.append(input.charAt(i));
+            } else {
+                result.append(c);
+            }
+        }
+        return result.toString();
     }
 
     private static SkipConstantResult skipConstant(StringReader input,
             String constant) throws IOException {
         int len = constant.length();
 
+        int c = input.read();
+        while (c == 32 || c == 9) {
+            c = input.read();
+        }
+
         for (int i = 0; i < len; i++) {
-            int c = input.read();
             if (i == 0 && c == -1) {
                 return SkipConstantResult.EOF;
             }
@@ -259,20 +250,13 @@ public class HttpParser2 {
                 input.skip(-(i + 1));
                 return SkipConstantResult.NOT_FOUND;
             }
+            if (i != (len - 1)) {
+                c = input.read();
+            }
         }
         return SkipConstantResult.FOUND;
     }
 
-    private static void skipLws(StringReader input) throws IOException {
-        int c = input.read();
-        while (c == 32 || c == 9) {
-            c = input.read();
-        }
-
-        // Skip back so non-LWS character is available for next read
-        input.skip(-1);
-    }
-
     /**
      * @return  the token if one was found, the empty string if no data was
      *          available to read or <code>null</code> if data other than a
@@ -282,6 +266,12 @@ public class HttpParser2 {
         StringBuilder result = new StringBuilder();
 
         int c = input.read();
+
+        // Skip lws
+        while (c == 32 || c == 9) {
+            c = input.read();
+        }
+
         while (c != -1 && isToken[c]) {
             result.append((char) c);
             c = input.read();
@@ -305,6 +295,12 @@ public class HttpParser2 {
             boolean returnQuoted) throws IOException {
 
         int c = input.read();
+
+        // Skip lws
+        while (c == 32 || c == 9) {
+            c = input.read();
+        }
+
         if (c != '"') {
             return null;
         }
@@ -314,6 +310,7 @@ public class HttpParser2 {
             result.append('\"');
         }
         c = input.read();
+
         while (c != '"') {
             if (c == -1) {
                 return null;
@@ -337,8 +334,9 @@ public class HttpParser2 {
 
     private static String readTokenOrQuotedString(StringReader input,
             boolean returnQuoted) throws IOException {
+        input.mark(1);
         int c = input.read();
-        input.skip(-1);
+        input.reset();
 
         if (c == '"') {
             return readQuotedString(input, returnQuoted);
@@ -358,6 +356,12 @@ public class HttpParser2 {
         StringBuilder result = new StringBuilder();
 
         int c = input.read();
+
+        // Skip lws
+        while (c == 32 || c == 9) {
+            c = input.read();
+        }
+
         while (c != -1 && isHex[c]) {
             result.append((char) c);
             c = input.read();

Modified: tomcat/trunk/java/org/apache/tomcat/util/http/parser/MediaType.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/http/parser/MediaType.java?rev=1405415&r1=1405414&r2=1405415&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/http/parser/MediaType.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/http/parser/MediaType.java Sat Nov  3 20:46:02 2012
@@ -16,21 +16,109 @@
  */
 package org.apache.tomcat.util.http.parser;
 
+import java.util.LinkedHashMap;
+import java.util.Map;
+
 public class MediaType {
 
-    private final String noCharset;
+    private final String type;
+    private final String subtype;
+    private final LinkedHashMap<String,String> parameters;
     private final String charset;
+    private volatile String noCharset;
+    private volatile String withCharset;
+
+    protected MediaType(String type, String subtype,
+            LinkedHashMap<String,String> parameters) {
+        this.type = type;
+        this.subtype = subtype;
+        this.parameters = parameters;
 
-    protected MediaType(String noCharset, String charset) {
-        this.noCharset = noCharset;
-        this.charset = charset;
+        String cs = parameters.get("charset");
+        if (cs != null && cs.length() > 0 &&
+                cs.charAt(0) == '"') {
+            cs = HttpParser.unquote(cs);
+        }
+        this.charset = cs;
     }
 
-    public String toStringNoCharset() {
-        return noCharset;
+    public String getType() {
+        return type;
     }
 
-    public String getCharSet() {
+    public String getSubtype() {
+        return subtype;
+    }
+
+    public String getCharset() {
         return charset;
     }
+
+    public int getParameterCount() {
+        return parameters.size();
+    }
+
+    public String getParameterValue(String parameter) {
+        return parameters.get(parameter);
+    }
+
+    @Override
+    public String toString() {
+        if (withCharset == null) {
+            synchronized (this) {
+                if (withCharset == null) {
+                    StringBuilder result = new StringBuilder();
+                    result.append(type);
+                    result.append('/');
+                    result.append(subtype);
+                    for (Map.Entry<String, String> entry : parameters.entrySet()) {
+                        String value = entry.getValue();
+                        if (value == null || value.length() == 0) {
+                            continue;
+                        }
+                        result.append(';');
+                        // Workaround for Adobe Read 9 plug-in on IE bug
+                        // Can be removed after 26 June 2013 (EOL of Reader 9)
+                        // See BZ 53814
+                        result.append(' ');
+                        result.append(entry.getKey());
+                        result.append('=');
+                        result.append(value);
+                    }
+
+                    withCharset = result.toString();
+                }
+            }
+        }
+        return withCharset;
+    }
+
+    public String toStringNoCharset() {
+        if (noCharset == null) {
+            synchronized (this) {
+                if (noCharset == null) {
+                    StringBuilder result = new StringBuilder();
+                    result.append(type);
+                    result.append('/');
+                    result.append(subtype);
+                    for (Map.Entry<String, String> entry : parameters.entrySet()) {
+                        if (entry.getKey().equalsIgnoreCase("charset")) {
+                            continue;
+                        }
+                        result.append(';');
+                        // Workaround for Adobe Read 9 plug-in on IE bug
+                        // Can be removed after 26 June 2013 (EOL of Reader 9)
+                        // See BZ 53814
+                        result.append(' ');
+                        result.append(entry.getKey());
+                        result.append('=');
+                        result.append(entry.getValue());
+                    }
+
+                    noCharset = result.toString();
+                }
+            }
+        }
+        return noCharset;
+    }
 }

Modified: tomcat/trunk/java/org/apache/tomcat/util/http/parser/MediaTypeCache.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/http/parser/MediaTypeCache.java?rev=1405415&r1=1405414&r2=1405415&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/http/parser/MediaTypeCache.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/http/parser/MediaTypeCache.java Sat Nov  3 20:46:02 2012
@@ -16,6 +16,7 @@
  */
 package org.apache.tomcat.util.http.parser;
 
+import java.io.IOException;
 import java.io.StringReader;
 
 import org.apache.tomcat.util.collections.ConcurrentCache;
@@ -40,21 +41,24 @@ public class MediaTypeCache {
      * @return      The results are provided as a two element String array. The
      *                  first element is the media type less the charset and
      *                  the second element is the charset
-     *
-     * @throws ParseException if the input cannot be parsed
      */
-    public String[] parse(String input) throws ParseException {
+    public String[] parse(String input) {
         String[] result = cache.get(input);
 
         if (result != null) {
             return result;
         }
 
-        HttpParser hp = new HttpParser(new StringReader(input));
-        AstMediaType m = hp.MediaType();
-
-        result = new String[] {m.toStringNoCharset(), m.getCharset()};
-        cache.put(input, result);
+        MediaType m = null;
+        try {
+            m = HttpParser.parseMediaType(new StringReader(input));
+        } catch (IOException e) {
+            // Ignore - return null
+        }
+        if (m != null) {
+            result = new String[] {m.toStringNoCharset(), m.getCharset()};
+            cache.put(input, result);
+        }
 
         return result;
     }

Modified: tomcat/trunk/test/org/apache/tomcat/util/http/parser/TestAuthorizationDigest.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/http/parser/TestAuthorizationDigest.java?rev=1405415&r1=1405414&r2=1405415&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/tomcat/util/http/parser/TestAuthorizationDigest.java (original)
+++ tomcat/trunk/test/org/apache/tomcat/util/http/parser/TestAuthorizationDigest.java Sat Nov  3 20:46:02 2012
@@ -38,7 +38,7 @@ public class TestAuthorizationDigest {
 
         StringReader input = new StringReader(header);
 
-        Map<String,String> result = HttpParser2.parseAuthorizationDigest(input);
+        Map<String,String> result = HttpParser.parseAuthorizationDigest(input);
 
         Assert.assertEquals("mthornton", result.get("username"));
         Assert.assertEquals("optrak.com", result.get("realm"));
@@ -69,7 +69,7 @@ public class TestAuthorizationDigest {
 
         StringReader input = new StringReader(header);
 
-        Map<String,String> result = HttpParser2.parseAuthorizationDigest(input);
+        Map<String,String> result = HttpParser.parseAuthorizationDigest(input);
 
         Assert.assertEquals("mthornton", result.get("username"));
         Assert.assertEquals("optrak.com", result.get("realm"));
@@ -93,7 +93,7 @@ public class TestAuthorizationDigest {
 
         StringReader input = new StringReader(header);
 
-        Map<String,String> result = HttpParser2.parseAuthorizationDigest(input);
+        Map<String,String> result = HttpParser.parseAuthorizationDigest(input);
 
         Assert.assertEquals("mthornton", result.get("username"));
         Assert.assertEquals("auth", result.get("qop"));
@@ -107,7 +107,7 @@ public class TestAuthorizationDigest {
 
         StringReader input = new StringReader(header);
 
-        Map<String,String> result = HttpParser2.parseAuthorizationDigest(input);
+        Map<String,String> result = HttpParser.parseAuthorizationDigest(input);
 
         Assert.assertEquals("mthornton", result.get("username"));
         Assert.assertEquals("auth", result.get("qop"));
@@ -120,7 +120,7 @@ public class TestAuthorizationDigest {
 
         StringReader input = new StringReader(header);
 
-        Map<String,String> result = HttpParser2.parseAuthorizationDigest(input);
+        Map<String,String> result = HttpParser.parseAuthorizationDigest(input);
 
         Assert.assertEquals("00000001", result.get("nc"));
     }
@@ -131,7 +131,7 @@ public class TestAuthorizationDigest {
 
         StringReader input = new StringReader(header);
 
-        Map<String,String> result = HttpParser2.parseAuthorizationDigest(input);
+        Map<String,String> result = HttpParser.parseAuthorizationDigest(input);
         Assert.assertNull(result);
     }
 
@@ -141,7 +141,7 @@ public class TestAuthorizationDigest {
 
         StringReader input = new StringReader(header);
 
-        Map<String,String> result = HttpParser2.parseAuthorizationDigest(input);
+        Map<String,String> result = HttpParser.parseAuthorizationDigest(input);
         Assert.assertNull(result);
     }
 
@@ -151,7 +151,7 @@ public class TestAuthorizationDigest {
 
         StringReader input = new StringReader(header);
 
-        Map<String,String> result = HttpParser2.parseAuthorizationDigest(input);
+        Map<String,String> result = HttpParser.parseAuthorizationDigest(input);
         Assert.assertNull(result);
     }
 

Modified: tomcat/trunk/test/org/apache/tomcat/util/http/parser/TestMediaType.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/http/parser/TestMediaType.java?rev=1405415&r1=1405414&r2=1405415&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/tomcat/util/http/parser/TestMediaType.java (original)
+++ tomcat/trunk/test/org/apache/tomcat/util/http/parser/TestMediaType.java Sat Nov  3 20:46:02 2012
@@ -16,6 +16,7 @@
  */
 package org.apache.tomcat.util.http.parser;
 
+import java.io.IOException;
 import java.io.StringReader;
 
 import static org.junit.Assert.assertEquals;
@@ -60,93 +61,90 @@ public class TestMediaType {
 
 
     @Test
-    public void testSimple() throws ParseException {
+    public void testSimple() throws IOException {
         doTest();
     }
 
 
     @Test
-    public void testSimpleWithToken() throws ParseException {
+    public void testSimpleWithToken() throws IOException {
         doTest(PARAM_TOKEN);
     }
 
 
     @Test
-    public void testSimpleWithQuotedString() throws ParseException {
+    public void testSimpleWithQuotedString() throws IOException {
         doTest(PARAM_QUOTED);
     }
 
 
     @Test
-    public void testSimpleWithEmptyQuotedString() throws ParseException {
+    public void testSimpleWithEmptyQuotedString() throws IOException {
         doTest(PARAM_EMPTY_QUOTED);
     }
 
 
     @Test
-    public void testSimpleWithComplesQuotedString() throws ParseException {
+    public void testSimpleWithComplesQuotedString() throws IOException {
         doTest(PARAM_COMPLEX_QUOTED);
     }
 
 
     @Test
-    public void testSimpleWithCharset() throws ParseException {
+    public void testSimpleWithCharset() throws IOException {
         doTest(PARAM_CHARSET);
     }
 
 
     @Test
-    public void testSimpleWithCharsetWhitespaceBefore() throws ParseException {
+    public void testSimpleWithCharsetWhitespaceBefore() throws IOException {
         doTest(PARAM_WS_CHARSET);
     }
 
 
     @Test
-    public void testSimpleWithCharsetWhitespaceAfter() throws ParseException {
+    public void testSimpleWithCharsetWhitespaceAfter() throws IOException {
         doTest(PARAM_CHARSET_WS);
     }
 
 
     @Test
-    public void testSimpleWithCharsetQuoted() throws ParseException {
+    public void testSimpleWithCharsetQuoted() throws IOException {
         doTest(PARAM_CHARSET_QUOTED);
     }
 
 
     @Test
-    public void testSimpleWithAll() throws ParseException {
+    public void testSimpleWithAll() throws IOException {
         doTest(PARAM_COMPLEX_QUOTED, PARAM_EMPTY_QUOTED, PARAM_QUOTED,
                 PARAM_TOKEN, PARAM_CHARSET);
     }
 
 
     @Test
-    public void testCharset() throws ParseException {
+    public void testCharset() throws IOException {
         StringBuilder sb = new StringBuilder();
         sb.append(TYPES);
         sb.append(PARAM_CHARSET);
         sb.append(PARAM_TOKEN);
 
         StringReader sr = new StringReader(sb.toString());
-        HttpParser hp = new HttpParser(sr);
-        AstMediaType m = hp.MediaType();
+        MediaType m = HttpParser.parseMediaType(sr);
 
-        assertEquals(sb.toString().replaceAll(" ", ""), m.toString());
+        assertEquals("foo/bar; charset=UTF-8; a=b", m.toString());
         assertEquals(CHARSET, m.getCharset());
-        assertEquals(TYPES.replaceAll(" ", "") + PARAM_TOKEN,
-                m.toStringNoCharset());
+        assertEquals("foo/bar; a=b", m.toStringNoCharset());
     }
 
 
     @Test
-    public void testCharsetQuoted() throws ParseException {
+    public void testCharsetQuoted() throws IOException {
         StringBuilder sb = new StringBuilder();
         sb.append(TYPES);
         sb.append(PARAM_CHARSET_QUOTED);
 
         StringReader sr = new StringReader(sb.toString());
-        HttpParser hp = new HttpParser(sr);
-        AstMediaType m = hp.MediaType();
+        MediaType m = HttpParser.parseMediaType(sr);
 
         assertEquals(CHARSET_WS, m.getCharset());
         assertEquals(TYPES.replaceAll(" ", ""),
@@ -155,88 +153,59 @@ public class TestMediaType {
 
 
     @Test
-    public void testBug52811() throws ParseException {
+    public void testBug52811() throws IOException {
         String input = "multipart/related;boundary=1_4F50BD36_CDF8C28;" +
                 "Start=\"<31671603.smil>\";" +
                 "Type=\"application/smil;charset=UTF-8\"";
 
         StringReader sr = new StringReader(input);
-        HttpParser hp = new HttpParser(sr);
-        AstMediaType m = hp.MediaType();
-
-        assertTrue(m.children.length == 5);
+        MediaType m = HttpParser.parseMediaType(sr);
 
         // Check the types
-        assertTrue(m.children[0] instanceof AstType);
-        assertTrue(m.children[1] instanceof AstSubType);
-        assertEquals("multipart", m.children[0].toString());
-        assertEquals("related", m.children[1].toString());
+        assertEquals("multipart", m.getType());
+        assertEquals("related", m.getSubtype());
 
         // Check the parameters
-        AstParameter p = (AstParameter) m.children[2];
-        assertTrue(p.children.length == 2);
-        assertTrue(p.children[0] instanceof AstAttribute);
-        assertTrue(p.children[1] instanceof AstValue);
-        assertEquals("boundary", p.children[0].toString());
-        assertEquals("1_4F50BD36_CDF8C28", p.children[1].toString());
-
-        p = (AstParameter) m.children[3];
-        assertTrue(p.children.length == 2);
-        assertTrue(p.children[0] instanceof AstAttribute);
-        assertTrue(p.children[1] instanceof AstValue);
-        assertEquals("Start", p.children[0].toString());
-        assertEquals("\"<31671603.smil>\"", p.children[1].toString());
-
-        p = (AstParameter) m.children[4];
-        assertTrue(p.children.length == 2);
-        assertTrue(p.children[0] instanceof AstAttribute);
-        assertTrue(p.children[1] instanceof AstValue);
-        assertEquals("Type", p.children[0].toString());
+        assertTrue(m.getParameterCount() == 3);
+
+        assertEquals("1_4F50BD36_CDF8C28", m.getParameterValue("boundary"));
+        assertEquals("\"<31671603.smil>\"", m.getParameterValue("Start"));
         assertEquals("\"application/smil;charset=UTF-8\"",
-                p.children[1].toString());
+                m.getParameterValue("Type"));
 
-        assertEquals(input, m.toString());
-        assertEquals(input, m.toStringNoCharset());
+        String expected = "multipart/related; boundary=1_4F50BD36_CDF8C28; " +
+                "Start=\"<31671603.smil>\"; " +
+                "Type=\"application/smil;charset=UTF-8\"";
+        assertEquals(expected, m.toString());
+        assertEquals(expected, m.toStringNoCharset());
         assertNull(m.getCharset());
     }
 
 
     @Test
-    public void testBug53353() throws ParseException {
+    public void testBug53353() throws IOException {
         String input = "text/html; UTF-8;charset=UTF-8";
 
         StringReader sr = new StringReader(input);
-        HttpParser hp = new HttpParser(sr);
-        AstMediaType m = hp.MediaType();
-
-        assertTrue(m.children.length == 4);
+        MediaType m = HttpParser.parseMediaType(sr);
 
         // Check the types
-        assertTrue(m.children[0] instanceof AstType);
-        assertTrue(m.children[1] instanceof AstSubType);
-        assertEquals("text", m.children[0].toString());
-        assertEquals("html", m.children[1].toString());
+        assertEquals("text", m.getType());
+        assertEquals("html", m.getSubtype());
 
         // Check the parameters
-        AstParameter p = (AstParameter) m.children[2];
-        assertTrue(p.children.length == 1);
-        assertTrue(p.children[0] instanceof AstAttribute);
-        assertEquals("UTF-8", p.children[0].toString());
-
-        p = (AstParameter) m.children[3];
-        assertTrue(p.children.length == 2);
-        assertTrue(p.children[0] instanceof AstAttribute);
-        assertTrue(p.children[1] instanceof AstValue);
-        assertEquals("charset", p.children[0].toString());
-        assertEquals("UTF-8", p.children[1].toString());
+        assertTrue(m.getParameterCount() == 2);
+
+        assertEquals("", m.getParameterValue("UTF-8"));
+        assertEquals("UTF-8", m.getCharset());
 
         // Note: Invalid input is filtered out
-        assertEquals("text/html;charset=UTF-8", m.toString());
+        assertEquals("text/html; charset=UTF-8", m.toString());
         assertEquals("UTF-8", m.getCharset());
     }
 
 
-    private void doTest(Parameter... parameters) throws ParseException {
+    private void doTest(Parameter... parameters) throws IOException {
         StringBuilder sb = new StringBuilder();
         sb.append(TYPES);
         for (Parameter p : parameters) {
@@ -244,27 +213,19 @@ public class TestMediaType {
         }
 
         StringReader sr = new StringReader(sb.toString());
-        HttpParser hp = new HttpParser(sr);
-        AstMediaType m = hp.MediaType();
+        MediaType m = HttpParser.parseMediaType(sr);
 
-        // Check all expected children are present
-        assertTrue(m.children.length == 2 + parameters.length);
+        // Check all expected parameters are present
+        assertTrue(m.getParameterCount() == parameters.length);
 
         // Check the types
-        assertTrue(m.children[0] instanceof AstType);
-        assertTrue(m.children[1] instanceof AstSubType);
-        assertEquals(TYPE.trim(), m.children[0].toString());
-        assertEquals(SUBTYPE.trim(), m.children[1].toString());
+        assertEquals(TYPE.trim(), m.getType());
+        assertEquals(SUBTYPE.trim(), m.getSubtype());
 
         // Check the parameters
         for (int i = 0; i <  parameters.length; i++) {
-            assertTrue(m.children[i + 2] instanceof AstParameter);
-            AstParameter p = (AstParameter) m.children[i + 2];
-            assertTrue(p.children.length == 2);
-            assertTrue(p.children[0] instanceof AstAttribute);
-            assertTrue(p.children[1] instanceof AstValue);
-            assertEquals(parameters[i].getName().trim(), p.children[0].toString());
-            assertEquals(parameters[i].getValue().trim(), p.children[1].toString());
+            assertEquals(parameters[i].getValue().trim(),
+                    m.getParameterValue(parameters[i].getName().trim()));
         }
     }
 



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Re: svn commit: r1405415 - in /tomcat/trunk: ./ java/org/apache/catalina/authenticator/ java/org/apache/catalina/connector/ java/org/apache/coyote/ java/org/apache/tomcat/util/http/parser/ test/org/apache/tomcat/util/http/parser/

Posted by Konstantin Kolinko <kn...@gmail.com>.
2012/11/4  <ma...@apache.org>:
> Author: markt
> Date: Sat Nov  3 20:46:02 2012
> New Revision: 1405415
>
> URL: http://svn.apache.org/viewvc?rev=1405415&view=rev
> Log:
> Move media-type parsing to the new parser and drop the JJTree based parser.
>
> Added:
>     tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser.java
>       - copied, changed from r1405399, tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser2.java
> Removed:
>     tomcat/trunk/java/org/apache/tomcat/util/http/parser/AstAttribute.java
>     tomcat/trunk/java/org/apache/tomcat/util/http/parser/AstMediaType.java
>     tomcat/trunk/java/org/apache/tomcat/util/http/parser/AstParameter.java
>     tomcat/trunk/java/org/apache/tomcat/util/http/parser/AstSubType.java
>     tomcat/trunk/java/org/apache/tomcat/util/http/parser/AstType.java
>     tomcat/trunk/java/org/apache/tomcat/util/http/parser/AstValue.java
>     tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser.jjt
>     tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser2.java
>     tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParserConstants.java
>     tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParserTokenManager.java
>     tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParserTreeConstants.java
>     tomcat/trunk/java/org/apache/tomcat/util/http/parser/JJTHttpParserState.java
>     tomcat/trunk/java/org/apache/tomcat/util/http/parser/Node.java
>     tomcat/trunk/java/org/apache/tomcat/util/http/parser/ParseException.java
>     tomcat/trunk/java/org/apache/tomcat/util/http/parser/SimpleCharStream.java
>     tomcat/trunk/java/org/apache/tomcat/util/http/parser/SimpleNode.java
>     tomcat/trunk/java/org/apache/tomcat/util/http/parser/Token.java
>     tomcat/trunk/java/org/apache/tomcat/util/http/parser/TokenMgrError.java
> Modified:
>     tomcat/trunk/build.xml
>     tomcat/trunk/java/org/apache/catalina/authenticator/DigestAuthenticator.java
>     tomcat/trunk/java/org/apache/catalina/connector/Response.java
>     tomcat/trunk/java/org/apache/coyote/Response.java
>     tomcat/trunk/java/org/apache/tomcat/util/http/parser/MediaType.java
>     tomcat/trunk/java/org/apache/tomcat/util/http/parser/MediaTypeCache.java
>     tomcat/trunk/test/org/apache/tomcat/util/http/parser/TestAuthorizationDigest.java
>     tomcat/trunk/test/org/apache/tomcat/util/http/parser/TestMediaType.java

> Copied: tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser.java (from r1405399, tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser2.java)

> @@ -198,60 +190,59 @@ public class HttpParser2 {
>              return null;
>          }
>
> -        skipLws(input);
> -
> -        Map<String,String> parameters = new HashMap<>();
> +        LinkedHashMap<String,String> parameters = new LinkedHashMap<>();
>
>          SkipConstantResult lookForSemiColon = skipConstant(input, ";");
>          if (lookForSemiColon == SkipConstantResult.NOT_FOUND) {
>              return null;
>          }
>          while (lookForSemiColon == SkipConstantResult.FOUND) {
> -            skipLws(input);
>              String attribute = readToken(input);
> -            skipLws(input);
>
> -            if (skipConstant(input, "=") != SkipConstantResult.FOUND) {
> -                return null;
> +            if (skipConstant(input, "=") == SkipConstantResult.FOUND) {
> +                String value = readTokenOrQuotedString(input, true);
> +                parameters.put(attribute, value);
> +            } else {
> +                parameters.put(attribute, "");
>              }
>
> -            skipLws(input);
> -            String value = readTokenOrQuotedString(input, true);
> -            skipLws(input);
> -
> -            parameters.put(attribute.toLowerCase(), value);

The above old code does attribute.toLowerCase(). The new code does not.

Looking into MediaType#MediaType(type,subtype,parameters) constructor, it calls
String cs = parameters.get("charset");

So it works with lowercase.
According to RFC2616 ch. 3.7 Media Types,
"The type, subtype, and parameter attribute names are case-insensitive."


> -
>              lookForSemiColon = skipConstant(input, ";");
>              if (lookForSemiColon == SkipConstantResult.NOT_FOUND) {
>                  return null;
>              }
>          }
>
> -        String charset = parameters.remove("charset");
> -        StringBuilder noCharSet = new StringBuilder();
> -        noCharSet.append(type);
> -        noCharSet.append('/');
> -        noCharSet.append(subtype);
> -        for (Map.Entry<String, String> entry : parameters.entrySet()) {
> -            noCharSet.append(';');
> -            // Workaround for Adobe Read 9 plug-in on IE bug
> -            // Can be removed after 26 June 2013 (EOL of Reader 9)
> -            // See BZ 53814
> -            noCharSet.append(' ');
> -            noCharSet.append(entry.getKey());
> -            noCharSet.append('=');
> -            noCharSet.append(entry.getValue());
> +        return new MediaType(type, subtype, parameters);
> +    }
> +

(...)

Best regards,
Konstantin Kolinko

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org