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