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/11/05 18:03:40 UTC

svn commit: r592088 - in /jakarta/httpcomponents/httpcore/trunk/module-main/src: main/java/org/apache/http/message/ test/java/org/apache/http/message/

Author: olegk
Date: Mon Nov  5 09:03:39 2007
New Revision: 592088

URL: http://svn.apache.org/viewvc?rev=592088&view=rev
Log:
* BasicHeaderElementIterator now takes any arbitrary HeaderValueParser as an optional parameter
* Implemented lazy parsing of header elements

Modified:
    jakarta/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/message/BasicHeaderElementIterator.java
    jakarta/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/message/ParserCursor.java
    jakarta/httpcomponents/httpcore/trunk/module-main/src/test/java/org/apache/http/message/TestBasicHeaderElementIterator.java

Modified: jakarta/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/message/BasicHeaderElementIterator.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/message/BasicHeaderElementIterator.java?rev=592088&r1=592087&r2=592088&view=diff
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/message/BasicHeaderElementIterator.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/message/BasicHeaderElementIterator.java Mon Nov  5 09:03:39 2007
@@ -32,9 +32,13 @@
 package org.apache.http.message;
 
 import java.util.NoSuchElementException;
+
+import org.apache.http.FormattedHeader;
+import org.apache.http.Header;
 import org.apache.http.HeaderElement;
 import org.apache.http.HeaderElementIterator;
 import org.apache.http.HeaderIterator;
+import org.apache.http.util.CharArrayBuffer;
 
 /**
  * Basic implementation of a {@link HeaderElementIterator}.
@@ -42,64 +46,108 @@
  * @version $Revision$
  * 
  * @author Andrea Selva <selva.andre at gmail.com>
+ * @author Oleg Kalnichevski <oleg at ural.ru>
  */
 public class BasicHeaderElementIterator implements HeaderElementIterator {
     
     private final HeaderIterator headerIt;
-
-    private int currentElementIdx = -1;
-    
-    private HeaderElement[] currentElements = null;
+    private final HeaderValueParser parser;
     
     private HeaderElement currentElement = null;
+    private CharArrayBuffer buffer = null;
+    private ParserCursor cursor = null;
     
     /**
      * Creates a new instance of BasicHeaderElementIterator
      */
-    public BasicHeaderElementIterator(final HeaderIterator headerIterator) {
+    public BasicHeaderElementIterator(
+            final HeaderIterator headerIterator,
+            final HeaderValueParser parser) {
         if (headerIterator == null) {
             throw new IllegalArgumentException("Header iterator may not be null");
         }
+        if (parser == null) {
+            throw new IllegalArgumentException("Parser may not be null");
+        }
         this.headerIt = headerIterator;
-        
-        if (this.headerIt.hasNext()) {
-            this.currentElementIdx = 0;
-            this.currentElements = this.headerIt.nextHeader().getElements();
-            this.currentElement = findNext();
-        } 
+        this.parser = parser;
     }
 
+    
+    public BasicHeaderElementIterator(final HeaderIterator headerIterator) {
+        this(headerIterator, BasicHeaderValueParser.DEFAULT);
+    }
 
-    protected HeaderElement findNext() {
-        HeaderElement tmpHeader;
-        
-        if (this.currentElementIdx == this.currentElements.length) {
-            if (!this.headerIt.hasNext()) {
-                return null;
+    
+    private void bufferHeaderValue() {
+        this.cursor = null;
+        this.buffer = null;
+        while (this.headerIt.hasNext()) {
+            Header h = this.headerIt.nextHeader();
+            if (h instanceof FormattedHeader) {
+                this.buffer = ((FormattedHeader) h).getBuffer();
+                this.cursor = new ParserCursor(0, this.buffer.length());
+                this.cursor.updatePos(((FormattedHeader) h).getValuePos());
+                break;
+            } else {
+                String value = h.getValue();
+                if (value != null) {
+                    this.buffer = new CharArrayBuffer(value.length());
+                    this.buffer.append(value);
+                    this.cursor = new ParserCursor(0, this.buffer.length());
+                    break;
+                }
             }
-            this.currentElements = this.headerIt.nextHeader().getElements();
-            this.currentElementIdx = 0;
         }
+    }
 
-        tmpHeader = this.currentElements[this.currentElementIdx++];
-        return tmpHeader;
-         
+    private void parseNextElement() {
+        // loop while there are headers left to parse
+        while (this.headerIt.hasNext() || this.cursor != null) {
+            if (this.cursor == null || this.cursor.atEnd()) {
+                // get next header value
+                bufferHeaderValue();
+            }
+            // Anything buffered?
+            if (this.cursor != null) {
+                // loop while there is data in the buffer 
+                while (!this.cursor.atEnd()) {
+                    HeaderElement e = this.parser.parseHeaderElement(this.buffer, this.cursor);
+                    if (!(e.getName().length() == 0 && e.getValue() == null)) {
+                        // Found something
+                        this.currentElement = e;
+                        return;
+                    }
+                }
+                // if at the end of the buffer
+                if (this.cursor.atEnd()) {
+                    // discard it
+                    this.cursor = null;
+                    this.buffer = null;
+                }
+            }
+        }
     }
     
     public boolean hasNext() {
-        return (this.currentElement != null);
+        if (this.currentElement == null) {
+            parseNextElement();
+        }
+        return this.currentElement != null;
     }
 
     public HeaderElement nextElement() throws NoSuchElementException {
-
-        final HeaderElement current = this.currentElement;
-        if (current == null) {
-            throw new NoSuchElementException("Iteration already finished.");
+        if (this.currentElement == null) {
+            parseNextElement();
         }
 
-        this.currentElement = findNext();
+        if (this.currentElement == null) {
+            throw new NoSuchElementException("No more header elements available");
+        }
 
-        return current;
+        HeaderElement element = this.currentElement;
+        this.currentElement = null;
+        return element;
     }
 
     public final Object next() throws NoSuchElementException {

Modified: jakarta/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/message/ParserCursor.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/message/ParserCursor.java?rev=592088&r1=592087&r2=592088&view=diff
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/message/ParserCursor.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/message/ParserCursor.java Mon Nov  5 09:03:39 2007
@@ -58,7 +58,7 @@
         }
         this.lowerBound = lowerBound;
         this.upperBound = upperBound;
-        this.pos = 0;
+        this.pos = lowerBound;
     }
 
     public int getLowerBound() {

Modified: jakarta/httpcomponents/httpcore/trunk/module-main/src/test/java/org/apache/http/message/TestBasicHeaderElementIterator.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-main/src/test/java/org/apache/http/message/TestBasicHeaderElementIterator.java?rev=592088&r1=592087&r2=592088&view=diff
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-main/src/test/java/org/apache/http/message/TestBasicHeaderElementIterator.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-main/src/test/java/org/apache/http/message/TestBasicHeaderElementIterator.java Mon Nov  5 09:03:39 2007
@@ -1,5 +1,7 @@
 package org.apache.http.message;
 
+import java.util.NoSuchElementException;
+
 import junit.framework.Test;
 import junit.framework.TestCase;
 import junit.framework.TestSuite;
@@ -43,14 +45,34 @@
         };
        
         HeaderElementIterator hei = 
-                new BasicHeaderElementIterator(new BasicHeaderIterator(headers, "Name"));
+                new BasicHeaderElementIterator(
+                        new BasicHeaderIterator(headers, "Name"));
         
+        assertTrue(hei.hasNext());
         HeaderElement elem = (HeaderElement) hei.next();
         assertEquals("The two header values must be equal", 
                 "value0", elem.getName());
+        
+        assertTrue(hei.hasNext());
         elem = (HeaderElement)hei.next();
         assertEquals("The two header values must be equal", 
                 "value1", elem.getName());
+
+        assertFalse(hei.hasNext());
+        try {
+            hei.next();
+            fail("NoSuchElementException should have been thrown");
+        } catch (NoSuchElementException ex) {
+            // expected
+        }
+
+        assertFalse(hei.hasNext());
+        try {
+            hei.next();
+            fail("NoSuchElementException should have been thrown");
+        } catch (NoSuchElementException ex) {
+            // expected
+        }
     }
     
     public void testMultiHeaderSameLine() {
@@ -79,6 +101,34 @@
                 "cookie2", elem.getName());
         assertEquals("The two header values must be equal", 
                 "2", elem.getValue());
+    }
+    
+    public void testFringeCases() {
+        Header[] headers = new Header[]{
+                new BasicHeader("Name", null),
+                new BasicHeader("Name", "    "),
+                new BasicHeader("Name", ",,,")
+        };
+       
+        HeaderElementIterator hei = 
+                new BasicHeaderElementIterator(
+                        new BasicHeaderIterator(headers, "Name"));
+        
+        assertFalse(hei.hasNext());
+        try {
+            hei.next();
+            fail("NoSuchElementException should have been thrown");
+        } catch (NoSuchElementException ex) {
+            // expected
+        }
+
+        assertFalse(hei.hasNext());
+        try {
+            hei.next();
+            fail("NoSuchElementException should have been thrown");
+        } catch (NoSuchElementException ex) {
+            // expected
+        }
     }
     
 }