1069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project/* 2069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/message/BasicTokenIterator.java $ 3069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * $Revision: 602520 $ 4069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * $Date: 2007-12-08 09:42:26 -0800 (Sat, 08 Dec 2007) $ 5069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 6069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * ==================================================================== 7069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one 8069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * or more contributor license agreements. See the NOTICE file 9069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * distributed with this work for additional information 10069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * regarding copyright ownership. The ASF licenses this file 11069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * to you under the Apache License, Version 2.0 (the 12069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * "License"); you may not use this file except in compliance 13069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * with the License. You may obtain a copy of the License at 14069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 15069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 16069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 17069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Unless required by applicable law or agreed to in writing, 18069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * software distributed under the License is distributed on an 19069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 20069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * KIND, either express or implied. See the License for the 21069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * specific language governing permissions and limitations 22069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * under the License. 23069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * ==================================================================== 24069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 25069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * This software consists of voluntary contributions made by many 26069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * individuals on behalf of the Apache Software Foundation. For more 27069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * information on the Apache Software Foundation, please see 28069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <http://www.apache.org/>. 29069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 30069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 31069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 32069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectpackage org.apache.http.message; 33069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 34069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.util.NoSuchElementException; 35069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 36069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.HeaderIterator; 37069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.ParseException; 38069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.TokenIterator; 39069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 40069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project/** 41069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Basic implementation of a {@link TokenIterator}. 42069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * This implementation parses <tt>#token<tt> sequences as 43069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * defined by RFC 2616, section 2. 44069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * It extends that definition somewhat beyond US-ASCII. 45069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 46069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @version $Revision: 602520 $ 47d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath * 48d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath * @deprecated Please use {@link java.net.URL#openConnection} instead. 49d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath * Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a> 50d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath * for further details. 51069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 52d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath@Deprecated 53069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectpublic class BasicTokenIterator implements TokenIterator { 54069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 55069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** The HTTP separator characters. Defined in RFC 2616, section 2.2. */ 56069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // the order of the characters here is adjusted to put the 57069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // most likely candidates at the beginning of the collection 58069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public final static String HTTP_SEPARATORS = " ,;=()<>@:\\\"/[]?{}\t"; 59069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 60069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 61069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** The iterator from which to obtain the next header. */ 62069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project protected final HeaderIterator headerIt; 63069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 64069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 65069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The value of the current header. 66069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * This is the header value that includes {@link #currentToken}. 67069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Undefined if the iteration is over. 68069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 69069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project protected String currentHeader; 70069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 71069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 72069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The token to be returned by the next call to {@link #currentToken}. 73069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <code>null</code> if the iteration is over. 74069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 75069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project protected String currentToken; 76069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 77069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 78069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The position after {@link #currentToken} in {@link #currentHeader}. 79069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Undefined if the iteration is over. 80069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 81069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project protected int searchPos; 82069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 83069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 84069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 85069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Creates a new instance of {@link BasicTokenIterator}. 86069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 87069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param headerIterator the iterator for the headers to tokenize 88069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 89069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public BasicTokenIterator(final HeaderIterator headerIterator) { 90069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (headerIterator == null) { 91069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throw new IllegalArgumentException 92069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project ("Header iterator must not be null."); 93069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 94069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 95069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project this.headerIt = headerIterator; 96069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project this.searchPos = findNext(-1); 97069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 98069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 99069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 100069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // non-javadoc, see interface TokenIterator 101069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public boolean hasNext() { 102069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return (this.currentToken != null); 103069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 104069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 105069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 106069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 107069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Obtains the next token from this iteration. 108069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 109069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @return the next token in this iteration 110069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 111069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @throws NoSuchElementException if the iteration is already over 112069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @throws ParseException if an invalid header value is encountered 113069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 114069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public String nextToken() 115069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throws NoSuchElementException, ParseException { 116069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 117069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (this.currentToken == null) { 118069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throw new NoSuchElementException("Iteration already finished."); 119069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 120069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 121069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project final String result = this.currentToken; 122069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // updates currentToken, may trigger ParseException: 123069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project this.searchPos = findNext(this.searchPos); 124069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 125069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return result; 126069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 127069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 128069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 129069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 130069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Returns the next token. 131069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Same as {@link #nextToken}, but with generic return type. 132069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 133069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @return the next token in this iteration 134069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 135069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @throws NoSuchElementException if there are no more tokens 136069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @throws ParseException if an invalid header value is encountered 137069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 138069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public final Object next() 139069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throws NoSuchElementException, ParseException { 140069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return nextToken(); 141069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 142069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 143069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 144069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 145069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Removing tokens is not supported. 146069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 147069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @throws UnsupportedOperationException always 148069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 149069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public final void remove() 150069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throws UnsupportedOperationException { 151069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 152069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throw new UnsupportedOperationException 153069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project ("Removing tokens is not supported."); 154069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 155069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 156069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 157069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 158069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Determines the next token. 159069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * If found, the token is stored in {@link #currentToken}. 160069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The return value indicates the position after the token 161069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * in {@link #currentHeader}. If necessary, the next header 162069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * will be obtained from {@link #headerIt}. 163069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * If not found, {@link #currentToken} is set to <code>null</code>. 164069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 165069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param from the position in the current header at which to 166069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * start the search, -1 to search in the first header 167069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 168069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @return the position after the found token in the current header, or 169069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * negative if there was no next token 170069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 171069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @throws ParseException if an invalid header value is encountered 172069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 173069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project protected int findNext(int from) 174069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throws ParseException { 175069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 176069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (from < 0) { 177069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // called from the constructor, initialize the first header 178069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (!this.headerIt.hasNext()) { 179069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return -1; 180069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 181069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project this.currentHeader = this.headerIt.nextHeader().getValue(); 182069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project from = 0; 183069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 184069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // called after a token, make sure there is a separator 185069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project from = findTokenSeparator(from); 186069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 187069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 188069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project int start = findTokenStart(from); 189069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (start < 0) { 190069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project this.currentToken = null; 191069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return -1; // nothing found 192069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 193069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 194069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project int end = findTokenEnd(start); 195069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project this.currentToken = createToken(this.currentHeader, start, end); 196069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return end; 197069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 198069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 199069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 200069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 201069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Creates a new token to be returned. 202069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Called from {@link #findNext findNext} after the token is identified. 203069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The default implementation simply calls 204069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * {@link java.lang.String#substring String.substring}. 205069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <br/> 206069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * If header values are significantly longer than tokens, and some 207069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * tokens are permanently referenced by the application, there can 208069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * be problems with garbage collection. A substring will hold a 209069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * reference to the full characters of the original string and 210069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * therefore occupies more memory than might be expected. 211069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * To avoid this, override this method and create a new string 212069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * instead of a substring. 213069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 214069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param value the full header value from which to create a token 215069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param start the index of the first token character 216069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param end the index after the last token character 217069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 218069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @return a string representing the token identified by the arguments 219069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 220069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project protected String createToken(String value, int start, int end) { 221069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return value.substring(start, end); 222069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 223069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 224069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 225069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 226069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Determines the starting position of the next token. 227069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * This method will iterate over headers if necessary. 228069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 229069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param from the position in the current header at which to 230069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * start the search 231069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 232069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @return the position of the token start in the current header, 233069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * negative if no token start could be found 234069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 235069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project protected int findTokenStart(int from) { 236069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (from < 0) { 237069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throw new IllegalArgumentException 238069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project ("Search position must not be negative: " + from); 239069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 240069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 241069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project boolean found = false; 242069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project while (!found && (this.currentHeader != null)) { 243069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 244069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project final int to = this.currentHeader.length(); 245069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project while (!found && (from < to)) { 246069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 247069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project final char ch = this.currentHeader.charAt(from); 248069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isTokenSeparator(ch) || isWhitespace(ch)) { 249069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // whitspace and token separators are skipped 250069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project from++; 251069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else if (isTokenChar(this.currentHeader.charAt(from))) { 252069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // found the start of a token 253069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project found = true; 254069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 255069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throw new ParseException 256069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project ("Invalid character before token (pos " + from + 257069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "): " + this.currentHeader); 258069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 259069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 260069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (!found) { 261069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (this.headerIt.hasNext()) { 262069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project this.currentHeader = this.headerIt.nextHeader().getValue(); 263069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project from = 0; 264069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 265069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project this.currentHeader = null; 266069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 267069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 268069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } // while headers 269069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 270069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return found ? from : -1; 271069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 272069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 273069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 274069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 275069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Determines the position of the next token separator. 276069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Because of multi-header joining rules, the end of a 277069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * header value is a token separator. This method does 278069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * therefore not need to iterate over headers. 279069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 280069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param from the position in the current header at which to 281069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * start the search 282069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 283069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @return the position of a token separator in the current header, 284069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * or at the end 285069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 286069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @throws ParseException 287069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * if a new token is found before a token separator. 288069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * RFC 2616, section 2.1 explicitly requires a comma between 289069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * tokens for <tt>#</tt>. 290069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 291069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project protected int findTokenSeparator(int from) { 292069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (from < 0) { 293069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throw new IllegalArgumentException 294069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project ("Search position must not be negative: " + from); 295069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 296069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 297069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project boolean found = false; 298069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project final int to = this.currentHeader.length(); 299069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project while (!found && (from < to)) { 300069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project final char ch = this.currentHeader.charAt(from); 301069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isTokenSeparator(ch)) { 302069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project found = true; 303069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else if (isWhitespace(ch)) { 304069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project from++; 305069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else if (isTokenChar(ch)) { 306069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throw new ParseException 307069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project ("Tokens without separator (pos " + from + 308069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "): " + this.currentHeader); 309069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 310069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throw new ParseException 311069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project ("Invalid character after token (pos " + from + 312069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "): " + this.currentHeader); 313069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 314069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 315069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 316069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return from; 317069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 318069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 319069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 320069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 321069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Determines the ending position of the current token. 322069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * This method will not leave the current header value, 323069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * since the end of the header value is a token boundary. 324069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 325069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param from the position of the first character of the token 326069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 327069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @return the position after the last character of the token. 328069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The behavior is undefined if <code>from</code> does not 329069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * point to a token character in the current header value. 330069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 331069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project protected int findTokenEnd(int from) { 332069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (from < 0) { 333069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throw new IllegalArgumentException 334069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project ("Token start position must not be negative: " + from); 335069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 336069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 337069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project final int to = this.currentHeader.length(); 338069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project int end = from+1; 339069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project while ((end < to) && isTokenChar(this.currentHeader.charAt(end))) { 340069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project end++; 341069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 342069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 343069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return end; 344069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 345069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 346069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 347069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 348069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Checks whether a character is a token separator. 349069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * RFC 2616, section 2.1 defines comma as the separator for 350069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <tt>#token</tt> sequences. The end of a header value will 351069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * also separate tokens, but that is not a character check. 352069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 353069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param ch the character to check 354069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 355069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @return <code>true</code> if the character is a token separator, 356069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <code>false</code> otherwise 357069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 358069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project protected boolean isTokenSeparator(char ch) { 359069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return (ch == ','); 360069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 361069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 362069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 363069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 364069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Checks whether a character is a whitespace character. 365069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * RFC 2616, section 2.2 defines space and horizontal tab as whitespace. 366069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The optional preceeding line break is irrelevant, since header 367069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * continuation is handled transparently when parsing messages. 368069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 369069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param ch the character to check 370069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 371069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @return <code>true</code> if the character is whitespace, 372069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <code>false</code> otherwise 373069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 374069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project protected boolean isWhitespace(char ch) { 375069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 376069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // we do not use Character.isWhitspace(ch) here, since that allows 377069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // many control characters which are not whitespace as per RFC 2616 378069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return ((ch == '\t') || Character.isSpaceChar(ch)); 379069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 380069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 381069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 382069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 383069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Checks whether a character is a valid token character. 384069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Whitespace, control characters, and HTTP separators are not 385069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * valid token characters. The HTTP specification (RFC 2616, section 2.2) 386069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * defines tokens only for the US-ASCII character set, this 387069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * method extends the definition to other character sets. 388069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 389069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param ch the character to check 390069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 391069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @return <code>true</code> if the character is a valid token start, 392069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <code>false</code> otherwise 393069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 394069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project protected boolean isTokenChar(char ch) { 395069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 396069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // common sense extension of ALPHA + DIGIT 397069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (Character.isLetterOrDigit(ch)) 398069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return true; 399069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 400069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // common sense extension of CTL 401069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (Character.isISOControl(ch)) 402069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return false; 403069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 404069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // no common sense extension for this 405069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isHttpSeparator(ch)) 406069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return false; 407069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 408069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // RFC 2616, section 2.2 defines a token character as 409069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // "any CHAR except CTLs or separators". The controls 410069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // and separators are included in the checks above. 411069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // This will yield unexpected results for Unicode format characters. 412069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // If that is a problem, overwrite isHttpSeparator(char) to filter 413069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // out the false positives. 414069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return true; 415069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 416069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 417069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 418069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 419069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Checks whether a character is an HTTP separator. 420069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The implementation in this class checks only for the HTTP separators 421069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * defined in RFC 2616, section 2.2. If you need to detect other 422069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * separators beyond the US-ASCII character set, override this method. 423069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 424069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param ch the character to check 425069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 426069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @return <code>true</code> if the character is an HTTP separator 427069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 428069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project protected boolean isHttpSeparator(char ch) { 429069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return (HTTP_SEPARATORS.indexOf(ch) >= 0); 430069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 431069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 432069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 433069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project} // class BasicTokenIterator 434069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 435