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.FormattedHeader; 033import org.apache.http.Header; 034import org.apache.http.HeaderElement; 035import org.apache.http.HeaderElementIterator; 036import org.apache.http.HeaderIterator; 037import org.apache.http.util.Args; 038import org.apache.http.util.CharArrayBuffer; 039 040/** 041 * Basic implementation of a {@link HeaderElementIterator}. 042 * 043 * @since 4.0 044 */ 045public class BasicHeaderElementIterator implements HeaderElementIterator { 046 047 private final HeaderIterator headerIt; 048 private final HeaderValueParser parser; 049 050 private HeaderElement currentElement = null; 051 private CharArrayBuffer buffer = null; 052 private ParserCursor cursor = null; 053 054 /** 055 * Creates a new instance of BasicHeaderElementIterator 056 */ 057 public BasicHeaderElementIterator( 058 final HeaderIterator headerIterator, 059 final HeaderValueParser parser) { 060 this.headerIt = Args.notNull(headerIterator, "Header iterator"); 061 this.parser = Args.notNull(parser, "Parser"); 062 } 063 064 065 public BasicHeaderElementIterator(final HeaderIterator headerIterator) { 066 this(headerIterator, BasicHeaderValueParser.INSTANCE); 067 } 068 069 070 private void bufferHeaderValue() { 071 this.cursor = null; 072 this.buffer = null; 073 while (this.headerIt.hasNext()) { 074 final Header h = this.headerIt.nextHeader(); 075 if (h instanceof FormattedHeader) { 076 this.buffer = ((FormattedHeader) h).getBuffer(); 077 this.cursor = new ParserCursor(0, this.buffer.length()); 078 this.cursor.updatePos(((FormattedHeader) h).getValuePos()); 079 break; 080 } else { 081 final String value = h.getValue(); 082 if (value != null) { 083 this.buffer = new CharArrayBuffer(value.length()); 084 this.buffer.append(value); 085 this.cursor = new ParserCursor(0, this.buffer.length()); 086 break; 087 } 088 } 089 } 090 } 091 092 private void parseNextElement() { 093 // loop while there are headers left to parse 094 while (this.headerIt.hasNext() || this.cursor != null) { 095 if (this.cursor == null || this.cursor.atEnd()) { 096 // get next header value 097 bufferHeaderValue(); 098 } 099 // Anything buffered? 100 if (this.cursor != null) { 101 // loop while there is data in the buffer 102 while (!this.cursor.atEnd()) { 103 final HeaderElement e = this.parser.parseHeaderElement(this.buffer, this.cursor); 104 if (!(e.getName().length() == 0 && e.getValue() == null)) { 105 // Found something 106 this.currentElement = e; 107 return; 108 } 109 } 110 // if at the end of the buffer 111 if (this.cursor.atEnd()) { 112 // discard it 113 this.cursor = null; 114 this.buffer = null; 115 } 116 } 117 } 118 } 119 120 @Override 121 public boolean hasNext() { 122 if (this.currentElement == null) { 123 parseNextElement(); 124 } 125 return this.currentElement != null; 126 } 127 128 @Override 129 public HeaderElement nextElement() throws NoSuchElementException { 130 if (this.currentElement == null) { 131 parseNextElement(); 132 } 133 134 if (this.currentElement == null) { 135 throw new NoSuchElementException("No more header elements available"); 136 } 137 138 final HeaderElement element = this.currentElement; 139 this.currentElement = null; 140 return element; 141 } 142 143 @Override 144 public final Object next() throws NoSuchElementException { 145 return nextElement(); 146 } 147 148 @Override 149 public void remove() throws UnsupportedOperationException { 150 throw new UnsupportedOperationException("Remove not supported"); 151 } 152 153}