001/* 002 * ==================================================================== 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, 014 * software distributed under the License is distributed on an 015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 016 * KIND, either express or implied. See the License for the 017 * specific language governing permissions and limitations 018 * under the License. 019 * ==================================================================== 020 * 021 * This software consists of voluntary contributions made by many 022 * individuals on behalf of the Apache Software Foundation. For more 023 * information on the Apache Software Foundation, please see 024 * <http://www.apache.org/>. 025 * 026 */ 027 028package org.apache.http.message; 029 030import java.util.NoSuchElementException; 031 032import org.apache.http.Header; 033import org.apache.http.HeaderIterator; 034import org.apache.http.util.Args; 035 036/** 037 * Basic implementation of a {@link HeaderIterator}. 038 * 039 * @since 4.0 040 */ 041public class BasicHeaderIterator implements HeaderIterator { 042 043 /** 044 * An array of headers to iterate over. 045 * Not all elements of this array are necessarily part of the iteration. 046 * This array will never be modified by the iterator. 047 * Derived implementations are expected to adhere to this restriction. 048 */ 049 protected final Header[] allHeaders; 050 051 052 /** 053 * The position of the next header in {@link #allHeaders allHeaders}. 054 * Negative if the iteration is over. 055 */ 056 protected int currentIndex; 057 058 059 /** 060 * The header name to filter by. 061 * {@code null} to iterate over all headers in the array. 062 */ 063 protected String headerName; 064 065 066 067 /** 068 * Creates a new header iterator. 069 * 070 * @param headers an array of headers over which to iterate 071 * @param name the name of the headers over which to iterate, or 072 * {@code null} for any 073 */ 074 public BasicHeaderIterator(final Header[] headers, final String name) { 075 super(); 076 this.allHeaders = Args.notNull(headers, "Header array"); 077 this.headerName = name; 078 this.currentIndex = findNext(-1); 079 } 080 081 082 /** 083 * Determines the index of the next header. 084 * 085 * @param pos one less than the index to consider first, 086 * -1 to search for the first header 087 * 088 * @return the index of the next header that matches the filter name, 089 * or negative if there are no more headers 090 */ 091 protected int findNext(final int pos) { 092 int from = pos; 093 if (from < -1) { 094 return -1; 095 } 096 097 final int to = this.allHeaders.length-1; 098 boolean found = false; 099 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}