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 }