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.Header;
33  import org.apache.http.HeaderIterator;
34  import org.apache.http.annotation.NotThreadSafe;
35  
36  /**
37   * Basic implementation of a {@link HeaderIterator}.
38   *
39   * @since 4.0
40   */
41  @NotThreadSafe
42  public class BasicHeaderIterator implements HeaderIterator {
43  
44      /**
45       * An array of headers to iterate over.
46       * Not all elements of this array are necessarily part of the iteration.
47       * This array will never be modified by the iterator.
48       * Derived implementations are expected to adhere to this restriction.
49       */
50      protected final Header[] allHeaders;
51  
52  
53      /**
54       * The position of the next header in {@link #allHeaders allHeaders}.
55       * Negative if the iteration is over.
56       */
57      protected int currentIndex;
58  
59  
60      /**
61       * The header name to filter by.
62       * <code>null</code> to iterate over all headers in the array.
63       */
64      protected String headerName;
65  
66  
67  
68      /**
69       * Creates a new header iterator.
70       *
71       * @param headers   an array of headers over which to iterate
72       * @param name      the name of the headers over which to iterate, or
73       *                  <code>null</code> for any
74       */
75      public BasicHeaderIterator(Header[] headers, String name) {
76          if (headers == null) {
77              throw new IllegalArgumentException
78                  ("Header array must not be null.");
79          }
80  
81          this.allHeaders = headers;
82          this.headerName = name;
83          this.currentIndex = findNext(-1);
84      }
85  
86  
87      /**
88       * Determines the index of the next header.
89       *
90       * @param from      one less than the index to consider first,
91       *                  -1 to search for the first header
92       *
93       * @return  the index of the next header that matches the filter name,
94       *          or negative if there are no more headers
95       */
96      protected int findNext(int from) {
97          if (from < -1)
98              return -1;
99  
100         final int to = this.allHeaders.length-1;
101         boolean found = false;
102         while (!found && (from < to)) {
103             from++;
104             found = filterHeader(from);
105         }
106         return found ? from : -1;
107     }
108 
109 
110     /**
111      * Checks whether a header is part of the iteration.
112      *
113      * @param index     the index of the header to check
114      *
115      * @return  <code>true</code> if the header should be part of the
116      *          iteration, <code>false</code> to skip
117      */
118     protected boolean filterHeader(int index) {
119         return (this.headerName == null) ||
120             this.headerName.equalsIgnoreCase(this.allHeaders[index].getName());
121     }
122 
123 
124     // non-javadoc, see interface HeaderIterator
125     public boolean hasNext() {
126         return (this.currentIndex >= 0);
127     }
128 
129 
130     /**
131      * Obtains the next header from this iteration.
132      *
133      * @return  the next header in this iteration
134      *
135      * @throws NoSuchElementException   if there are no more headers
136      */
137     public Header nextHeader()
138         throws NoSuchElementException {
139 
140         final int current = this.currentIndex;
141         if (current < 0) {
142             throw new NoSuchElementException("Iteration already finished.");
143         }
144 
145         this.currentIndex = findNext(current);
146 
147         return this.allHeaders[current];
148     }
149 
150 
151     /**
152      * Returns the next header.
153      * Same as {@link #nextHeader nextHeader}, but not type-safe.
154      *
155      * @return  the next header in this iteration
156      *
157      * @throws NoSuchElementException   if there are no more headers
158      */
159     public final Object next()
160         throws NoSuchElementException {
161         return nextHeader();
162     }
163 
164 
165     /**
166      * Removing headers is not supported.
167      *
168      * @throws UnsupportedOperationException    always
169      */
170     public void remove()
171         throws UnsupportedOperationException {
172 
173         throw new UnsupportedOperationException
174             ("Removing headers is not supported.");
175     }
176 }