View Javadoc

1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.http.message;
29  
30  import java.util.NoSuchElementException;
31  
32  import org.apache.http.FormattedHeader;
33  import org.apache.http.Header;
34  import org.apache.http.HeaderElement;
35  import org.apache.http.HeaderElementIterator;
36  import org.apache.http.HeaderIterator;
37  import org.apache.http.annotation.NotThreadSafe;
38  import org.apache.http.util.Args;
39  import org.apache.http.util.CharArrayBuffer;
40  
41  /**
42   * Basic implementation of a {@link HeaderElementIterator}.
43   *
44   * @since 4.0
45   */
46  @NotThreadSafe
47  public class BasicHeaderElementIterator implements HeaderElementIterator {
48  
49      private final HeaderIterator headerIt;
50      private final HeaderValueParser parser;
51  
52      private HeaderElement currentElement = null;
53      private CharArrayBuffer buffer = null;
54      private ParserCursor cursor = null;
55  
56      /**
57       * Creates a new instance of BasicHeaderElementIterator
58       */
59      public BasicHeaderElementIterator(
60              final HeaderIterator headerIterator,
61              final HeaderValueParser parser) {
62          this.headerIt = Args.notNull(headerIterator, "Header iterator");
63          this.parser = Args.notNull(parser, "Parser");
64      }
65  
66  
67      public BasicHeaderElementIterator(final HeaderIterator headerIterator) {
68          this(headerIterator, BasicHeaderValueParser.INSTANCE);
69      }
70  
71  
72      private void bufferHeaderValue() {
73          this.cursor = null;
74          this.buffer = null;
75          while (this.headerIt.hasNext()) {
76              final Header h = this.headerIt.nextHeader();
77              if (h instanceof FormattedHeader) {
78                  this.buffer = ((FormattedHeader) h).getBuffer();
79                  this.cursor = new ParserCursor(0, this.buffer.length());
80                  this.cursor.updatePos(((FormattedHeader) h).getValuePos());
81                  break;
82              } else {
83                  final String value = h.getValue();
84                  if (value != null) {
85                      this.buffer = new CharArrayBuffer(value.length());
86                      this.buffer.append(value);
87                      this.cursor = new ParserCursor(0, this.buffer.length());
88                      break;
89                  }
90              }
91          }
92      }
93  
94      private void parseNextElement() {
95          // loop while there are headers left to parse
96          while (this.headerIt.hasNext() || this.cursor != null) {
97              if (this.cursor == null || this.cursor.atEnd()) {
98                  // get next header value
99                  bufferHeaderValue();
100             }
101             // Anything buffered?
102             if (this.cursor != null) {
103                 // loop while there is data in the buffer
104                 while (!this.cursor.atEnd()) {
105                     final HeaderElement e = this.parser.parseHeaderElement(this.buffer, this.cursor);
106                     if (!(e.getName().length() == 0 && e.getValue() == null)) {
107                         // Found something
108                         this.currentElement = e;
109                         return;
110                     }
111                 }
112                 // if at the end of the buffer
113                 if (this.cursor.atEnd()) {
114                     // discard it
115                     this.cursor = null;
116                     this.buffer = null;
117                 }
118             }
119         }
120     }
121 
122     @Override
123     public boolean hasNext() {
124         if (this.currentElement == null) {
125             parseNextElement();
126         }
127         return this.currentElement != null;
128     }
129 
130     @Override
131     public HeaderElement nextElement() throws NoSuchElementException {
132         if (this.currentElement == null) {
133             parseNextElement();
134         }
135 
136         if (this.currentElement == null) {
137             throw new NoSuchElementException("No more header elements available");
138         }
139 
140         final HeaderElement element = this.currentElement;
141         this.currentElement = null;
142         return element;
143     }
144 
145     @Override
146     public final Object next() throws NoSuchElementException {
147         return nextElement();
148     }
149 
150     @Override
151     public void remove() throws UnsupportedOperationException {
152         throw new UnsupportedOperationException("Remove not supported");
153     }
154 
155 }