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