You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2007/10/27 21:09:20 UTC

svn commit: r589184 - in /jakarta/httpcomponents/httpcore/branches/parser_refactoring/module-main/src: main/java/org/apache/http/message/ test/java/org/apache/http/message/

Author: olegk
Date: Sat Oct 27 12:09:20 2007
New Revision: 589184

URL: http://svn.apache.org/viewvc?rev=589184&view=rev
Log:
HTTPCORE-126: Improved HTTP message parsing
* Removed optional delimiters parameter
* Ported NameValuePair[] parsing code to the new API

Modified:
    jakarta/httpcomponents/httpcore/branches/parser_refactoring/module-main/src/main/java/org/apache/http/message/BasicHeaderValueParser.java
    jakarta/httpcomponents/httpcore/branches/parser_refactoring/module-main/src/main/java/org/apache/http/message/HeaderValueParser.java
    jakarta/httpcomponents/httpcore/branches/parser_refactoring/module-main/src/test/java/org/apache/http/message/TestBasicHeaderValueParser.java

Modified: jakarta/httpcomponents/httpcore/branches/parser_refactoring/module-main/src/main/java/org/apache/http/message/BasicHeaderValueParser.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/branches/parser_refactoring/module-main/src/main/java/org/apache/http/message/BasicHeaderValueParser.java?rev=589184&r1=589183&r2=589184&view=diff
==============================================================================
--- jakarta/httpcomponents/httpcore/branches/parser_refactoring/module-main/src/main/java/org/apache/http/message/BasicHeaderValueParser.java (original)
+++ jakarta/httpcomponents/httpcore/branches/parser_refactoring/module-main/src/main/java/org/apache/http/message/BasicHeaderValueParser.java Sat Oct 27 12:09:20 2007
@@ -71,7 +71,9 @@
     public final static
         BasicHeaderValueParser DEFAULT = new BasicHeaderValueParser();
 
-
+    private char PARAM_DELIMITER                = ';';
+    private char ELEM_DELIMITER                 = ',';
+    
     // public default constructor
 
 
@@ -201,7 +203,10 @@
         if (indexFrom > indexTo) {
             throw new IndexOutOfBoundsException();
         }
-        NameValuePair[] nvps = parseParameters(buffer, indexFrom, indexTo);
+        ParserCursor cursor = new ParserCursor(indexFrom, indexTo);
+        cursor.updatePos(indexFrom);
+        
+        NameValuePair[] nvps = parseParameters(buffer, cursor);
         return createHeaderElement(nvps);
     }
 
@@ -242,58 +247,49 @@
 
         CharArrayBuffer buffer = new CharArrayBuffer(value.length());
         buffer.append(value);
-        return parser.parseParameters(buffer, 0, buffer.length());
+        ParserCursor cursor = new ParserCursor(0, value.length());
+        return parser.parseParameters(buffer, cursor);
     }
 
 
 
     // non-javadoc, see interface HeaderValueParser
     public NameValuePair[] parseParameters(final CharArrayBuffer buffer,
-                                           final int indexFrom,
-                                           final int indexTo) {
+                                           final ParserCursor cursor) {
 
         if (buffer == null) {
-            throw new IllegalArgumentException
-                ("Char array buffer may not be null");
+            throw new IllegalArgumentException("Char array buffer may not be null");
         }
-        if (indexFrom < 0) {
-            throw new IndexOutOfBoundsException();
+        if (cursor == null) {
+            throw new IllegalArgumentException("Parser cursor may not be null");
         }
-        if (indexTo > buffer.length()) {
-            throw new IndexOutOfBoundsException();
+        
+        int pos = cursor.getPos();
+        int indexTo = cursor.getUpperBound();
+        
+        while (pos < indexTo) {
+            char ch = buffer.charAt(pos);
+            if (HTTP.isWhitespace(ch)) {
+                pos++;
+            } else {
+                break;
+            }
         }
-        if (indexFrom > indexTo) {
-            throw new IndexOutOfBoundsException();
+        cursor.updatePos(pos);
+        if (cursor.atEnd()) {
+            return new NameValuePair[] {};
         }
+        
         List params = new ArrayList(); 
-        int cur = indexFrom;
-        int from = indexFrom;
-        boolean qouted = false;
-        boolean escaped = false;
-        while (cur < indexTo) {
-            char ch = buffer.charAt(cur);
-            if (ch == '"' && !escaped) {
-                qouted = !qouted;
-            }
-            NameValuePair param = null;
-            if (!qouted && ch == ';') {
-                param = parseNameValuePair(buffer, from, cur);
-                from = cur + 1;
-            } else if (cur == indexTo - 1) {
-                param = parseNameValuePair(buffer, from, indexTo);
-            }
-            if (param != null && !(param.getName().length() == 0 &&
-                                   param.getValue() == null)
-                ) {
-                params.add(param);
-            }
-            if (escaped) {
-                escaped = false;
-            } else {
-                escaped = qouted && ch == '\\';
+        while (!cursor.atEnd()) {
+            NameValuePair param = parseNameValuePair(buffer, cursor);
+            params.add(param);
+            char ch = buffer.charAt(cursor.getPos() - 1);
+            if (ch == ELEM_DELIMITER) {
+                break;
             }
-            cur++;
         }
+        
         return (NameValuePair[])
             params.toArray(new NameValuePair[params.size()]);
     }
@@ -322,46 +318,13 @@
         CharArrayBuffer buffer = new CharArrayBuffer(value.length());
         buffer.append(value);
         ParserCursor cursor = new ParserCursor(0, value.length());
-        return parser.parseNameValuePair(buffer, cursor, new char[] {});
+        return parser.parseNameValuePair(buffer, cursor);
     }
 
 
-    /**
-     * Parses a name=value specification, where the = and value are optional.
-     *
-     * @param buffer    the buffer holding the name-value pair to parse
-     *
-     * @return  the name-value pair, where the value is <code>null</code>
-     *          if no value is specified
-     */
-    public NameValuePair parseNameValuePair(final CharArrayBuffer buffer,
-                                            final int indexFrom,
-                                            final int indexTo) {
-
-        if (buffer == null) {
-            throw new IllegalArgumentException
-                ("Char array buffer may not be null");
-        }
-        ParserCursor cursor = new ParserCursor(indexFrom, indexTo);
-        cursor.updatePos(indexFrom);
-        return parseNameValuePair(buffer, cursor, new char[] {});
-    }
-
-    /**
-     * Parses a name=value specification, where the = and value are optional.
-     *
-     * @param buffer    the buffer holding the name-value pair to parse
-     * @param cursor    the parser cursor containing the current position and 
-     *                  the bounds within the buffer for the parsing operation
-     * @param delimiters array of delimiters that can optionally terminate
-     *                  the parsing operation
-     *
-     * @return  the name-value pair, where the value is <code>null</code>
-     *          if no value is specified
-     */
+    // non-javadoc, see interface HeaderValueParser
     public NameValuePair parseNameValuePair(final CharArrayBuffer buffer,
-                                            final ParserCursor cursor,
-                                            final char[] delimiters) {
+                                            final ParserCursor cursor) {
 
         if (buffer == null) {
             throw new IllegalArgumentException("Char array buffer may not be null");
@@ -369,9 +332,6 @@
         if (cursor == null) {
             throw new IllegalArgumentException("Parser cursor may not be null");
         }
-        if (delimiters == null) {
-            throw new IllegalArgumentException("Delimiters may not be null");
-        }
 
         boolean terminated = false;
         
@@ -386,7 +346,7 @@
             if (ch == '=') {
                 break;
             }
-            if (isOneOf(delimiters, ch)) {
+            if (ch == PARAM_DELIMITER || ch == ELEM_DELIMITER) {
                 terminated = true;
                 break;
             }
@@ -417,7 +377,8 @@
             if (ch == '"' && !escaped) {
                 qouted = !qouted;
             }
-            if (!qouted && !escaped && isOneOf(delimiters, ch)) {
+            if (!qouted && !escaped && 
+                    (ch == PARAM_DELIMITER || ch == ELEM_DELIMITER)) {
                 terminated = true;
                 break;
             }
@@ -453,15 +414,6 @@
         return createNameValuePair(name, value);
     }
 
-    private static boolean isOneOf(final char[] chs, char ch) {
-        for (int i = 0; i < chs.length; i++) {
-            if (chs[i] == ch) {
-                return true;
-            }
-        }
-        return false;
-    }
-    
     /**
      * Creates a name-value pair.
      * Called from {@link #parseNameValuePair}.

Modified: jakarta/httpcomponents/httpcore/branches/parser_refactoring/module-main/src/main/java/org/apache/http/message/HeaderValueParser.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/branches/parser_refactoring/module-main/src/main/java/org/apache/http/message/HeaderValueParser.java?rev=589184&r1=589183&r2=589184&view=diff
==============================================================================
--- jakarta/httpcomponents/httpcore/branches/parser_refactoring/module-main/src/main/java/org/apache/http/message/HeaderValueParser.java (original)
+++ jakarta/httpcomponents/httpcore/branches/parser_refactoring/module-main/src/main/java/org/apache/http/message/HeaderValueParser.java Sat Oct 27 12:09:20 2007
@@ -186,16 +186,18 @@
      * </pre> 
      *
      * @param buffer    buffer holding the name-value list to parse
+     * @param cursor    the parser cursor containing the current position and 
+     *                  the bounds within the buffer for the parsing operation
+     * @param delimiters array of delimiters that can optionally terminate
+     *                  the parsing operation
      *
      * @return  an array holding all items of the name-value list
      *
      * @throws ParseException        in case of a parse error
      */
-    NameValuePair[] parseParameters(CharArrayBuffer buffer,
-                                    int indexFrom,
-                                    int indexTo)
-        throws ParseException
-        ;
+    NameValuePair[] parseParameters(
+            CharArrayBuffer buffer,
+            ParserCursor cursor) throws ParseException;
 
 
     /**
@@ -204,16 +206,13 @@
      * @param buffer    the buffer holding the name-value pair to parse
      * @param cursor    the parser cursor containing the current position and 
      *                  the bounds within the buffer for the parsing operation
-     * @param delimiters array of delimiters that can optionally terminate
-     *                  the parsing operation
      *
      * @return  the name-value pair, where the value is <code>null</code>
      *          if no value is specified
      */
     NameValuePair parseNameValuePair(
             CharArrayBuffer buffer,
-            ParserCursor cursor,
-            char[] delimiters) throws ParseException;
+            ParserCursor cursor) throws ParseException;
     
 }
 

Modified: jakarta/httpcomponents/httpcore/branches/parser_refactoring/module-main/src/test/java/org/apache/http/message/TestBasicHeaderValueParser.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/branches/parser_refactoring/module-main/src/test/java/org/apache/http/message/TestBasicHeaderValueParser.java?rev=589184&r1=589183&r2=589184&view=diff
==============================================================================
--- jakarta/httpcomponents/httpcore/branches/parser_refactoring/module-main/src/test/java/org/apache/http/message/TestBasicHeaderValueParser.java (original)
+++ jakarta/httpcomponents/httpcore/branches/parser_refactoring/module-main/src/test/java/org/apache/http/message/TestBasicHeaderValueParser.java Sat Oct 27 12:09:20 2007
@@ -199,14 +199,13 @@
     public void testNVParseUsingCursor() {
         
         HeaderValueParser parser = BasicHeaderValueParser.DEFAULT;
-        char[] delimiters = new char[] {';', ','};
         
         String s = "test";
         CharArrayBuffer buffer = new CharArrayBuffer(16);
         buffer.append(s);
         ParserCursor cursor = new ParserCursor(0, s.length());
         
-        NameValuePair param = parser.parseNameValuePair(buffer, cursor, delimiters);
+        NameValuePair param = parser.parseNameValuePair(buffer, cursor);
         assertEquals("test", param.getName());
         assertEquals(null, param.getValue());
         assertEquals(s.length(), cursor.getPos());
@@ -217,7 +216,7 @@
         buffer.append(s);
         cursor = new ParserCursor(0, s.length());
         
-        param = parser.parseNameValuePair(buffer, cursor, delimiters);
+        param = parser.parseNameValuePair(buffer, cursor);
         assertEquals("test", param.getName());
         assertEquals(null, param.getValue());
         assertEquals(s.length(), cursor.getPos());
@@ -228,7 +227,7 @@
         buffer.append(s);
         cursor = new ParserCursor(0, s.length());
         
-        param = parser.parseNameValuePair(buffer, cursor, delimiters);
+        param = parser.parseNameValuePair(buffer, cursor);
         assertEquals("test", param.getName());
         assertEquals(null, param.getValue());
         assertEquals(s.length() - 2, cursor.getPos());
@@ -239,7 +238,7 @@
         buffer.append(s);
         cursor = new ParserCursor(0, s.length());
         
-        param = parser.parseNameValuePair(buffer, cursor, delimiters);
+        param = parser.parseNameValuePair(buffer, cursor);
         assertEquals("test", param.getName());
         assertEquals("stuff", param.getValue());
         assertEquals(s.length(), cursor.getPos());
@@ -250,7 +249,7 @@
         buffer.append(s);
         cursor = new ParserCursor(0, s.length());
         
-        param = parser.parseNameValuePair(buffer, cursor, delimiters);
+        param = parser.parseNameValuePair(buffer, cursor);
         assertEquals("test", param.getName());
         assertEquals("stuff", param.getValue());
         assertEquals(s.length(), cursor.getPos());
@@ -261,7 +260,7 @@
         buffer.append(s);
         cursor = new ParserCursor(0, s.length());
         
-        param = parser.parseNameValuePair(buffer, cursor, delimiters);
+        param = parser.parseNameValuePair(buffer, cursor);
         assertEquals("test", param.getName());
         assertEquals("stuff", param.getValue());
         assertEquals(s.length() - 4, cursor.getPos());
@@ -272,7 +271,7 @@
         buffer.append(s);
         cursor = new ParserCursor(0, s.length());
         
-        param = parser.parseNameValuePair(buffer, cursor, delimiters);
+        param = parser.parseNameValuePair(buffer, cursor);
         assertEquals("test", param.getName());
         assertEquals("stuff", param.getValue());
         
@@ -281,7 +280,7 @@
         buffer.append(s);
         cursor = new ParserCursor(0, s.length());
         
-        param = parser.parseNameValuePair(buffer, cursor, delimiters);
+        param = parser.parseNameValuePair(buffer, cursor);
         assertEquals("test", param.getName());
         assertEquals("  stuff\\\"", param.getValue());
         
@@ -290,7 +289,7 @@
         buffer.append(s);
         cursor = new ParserCursor(0, s.length());
         
-        param = parser.parseNameValuePair(buffer, cursor, delimiters);
+        param = parser.parseNameValuePair(buffer, cursor);
         assertEquals("test", param.getName());
         assertEquals(null, param.getValue());
 
@@ -299,7 +298,7 @@
         buffer.append(s);
         cursor = new ParserCursor(0, s.length());
         
-        param = parser.parseNameValuePair(buffer, cursor, delimiters);
+        param = parser.parseNameValuePair(buffer, cursor);
         assertEquals("", param.getName());
         assertEquals(null, param.getValue());
 
@@ -308,7 +307,7 @@
         buffer.append(s);
         cursor = new ParserCursor(0, s.length());
         
-        param = parser.parseNameValuePair(buffer, cursor, delimiters);
+        param = parser.parseNameValuePair(buffer, cursor);
         assertEquals("", param.getName());
         assertEquals("stuff", param.getValue());
     }
@@ -356,6 +355,53 @@
         assertEquals("stuff", param.getValue());
     }
 
+    public void testNVParseAllWithCursor() {
+        HeaderValueParser parser = BasicHeaderValueParser.DEFAULT;
+        
+        String s = 
+            "test; test1 =  stuff   ; test2 =  \"stuff; stuff\"; test3=\"stuff";
+        CharArrayBuffer buffer = new CharArrayBuffer(16);
+        buffer.append(s);
+        ParserCursor cursor = new ParserCursor(0, s.length());
+        
+        NameValuePair[] params = parser.parseParameters(buffer, cursor);
+        assertEquals("test", params[0].getName());
+        assertEquals(null, params[0].getValue());
+        assertEquals("test1", params[1].getName());
+        assertEquals("stuff", params[1].getValue());
+        assertEquals("test2", params[2].getName());
+        assertEquals("stuff; stuff", params[2].getValue());
+        assertEquals("test3", params[3].getName());
+        assertEquals("\"stuff", params[3].getValue());
+        assertEquals(s.length(), cursor.getPos());
+        assertTrue(cursor.atEnd());
+
+        s = 
+            "test; test1 =  stuff   ; test2 =  \"stuff; stuff\"; test3=\"stuff\",123";
+        buffer = new CharArrayBuffer(16);
+        buffer.append(s);
+        cursor = new ParserCursor(0, s.length());
+        
+        params = parser.parseParameters(buffer, cursor);
+        assertEquals("test", params[0].getName());
+        assertEquals(null, params[0].getValue());
+        assertEquals("test1", params[1].getName());
+        assertEquals("stuff", params[1].getValue());
+        assertEquals("test2", params[2].getName());
+        assertEquals("stuff; stuff", params[2].getValue());
+        assertEquals("test3", params[3].getName());
+        assertEquals("stuff", params[3].getValue());
+        assertEquals(s.length() - 3, cursor.getPos());
+        assertFalse(cursor.atEnd());
+
+        s = "  ";
+        buffer = new CharArrayBuffer(16);
+        buffer.append(s);
+        cursor = new ParserCursor(0, s.length());
+        params = parser.parseParameters(buffer, cursor);
+        assertEquals(0, params.length);
+    }
+
     public void testNVParseAll() {
         String s = 
           "test; test1 =  stuff   ; test2 =  \"stuff; stuff\"; test3=\"stuff";
@@ -387,73 +433,6 @@
         assertEquals("\\\\", params[1].getValue());
         assertEquals("test3", params[2].getName());
         assertEquals("stuff; stuff", params[2].getValue());
-    }
-
-    public void testNVParseInvalidInput() throws Exception {
-        CharArrayBuffer buffer = new CharArrayBuffer(32);
-        buffer.append("name = value");
-
-        try {
-            BasicHeaderValueParser.parseParameters(null, null);
-            fail("IllegalArgumentException should have been thrown");
-        } catch (IllegalArgumentException ex) {
-            // expected
-        }
-        try {
-            BasicHeaderValueParser.DEFAULT.parseParameters(null, 0, 0);
-            fail("IllegalArgumentException should have been thrown");
-        } catch (IllegalArgumentException ex) {
-            // expected
-        }
-        try {
-            BasicHeaderValueParser.DEFAULT.parseParameters(buffer, -1, 0);
-            fail("IllegalArgumentException should have been thrown");
-        } catch (IndexOutOfBoundsException ex) {
-            // expected
-        }
-        try {
-            BasicHeaderValueParser.DEFAULT.parseParameters(buffer, 0, 1000);
-            fail("IllegalArgumentException should have been thrown");
-        } catch (IndexOutOfBoundsException ex) {
-            // expected
-        }
-        try {
-            BasicHeaderValueParser.DEFAULT.parseParameters(buffer, 2, 1);
-            fail("IllegalArgumentException should have been thrown");
-        } catch (IndexOutOfBoundsException ex) {
-            // expected
-        }
-
-        try {
-            BasicHeaderValueParser.parseNameValuePair(null, null);
-            fail("IllegalArgumentException should have been thrown");
-        } catch (IllegalArgumentException ex) {
-            // expected
-        }
-        try {
-            BasicHeaderValueParser.DEFAULT.parseNameValuePair(null, 0, 0);
-            fail("IllegalArgumentException should have been thrown");
-        } catch (IllegalArgumentException ex) {
-            // expected
-        }
-        try {
-            BasicHeaderValueParser.DEFAULT.parseNameValuePair(buffer, -1, 0);
-            fail("IllegalArgumentException should have been thrown");
-        } catch (IndexOutOfBoundsException ex) {
-            // expected
-        }
-        try {
-            BasicHeaderValueParser.DEFAULT.parseNameValuePair(buffer, 0, 1000);
-            fail("IllegalArgumentException should have been thrown");
-        } catch (IndexOutOfBoundsException ex) {
-            // expected
-        }
-        try {
-            BasicHeaderValueParser.DEFAULT.parseNameValuePair(buffer, 2, 1);
-            fail("IllegalArgumentException should have been thrown");
-        } catch (IndexOutOfBoundsException ex) {
-            // expected
-        }
     }
 
 }