1 /* 2 * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/message/BasicHeaderValueParser.java $ 3 * $Revision: 595670 $ 4 * $Date: 2007-11-16 06:15:01 -0800 (Fri, 16 Nov 2007) $ 5 * 6 * ==================================================================== 7 * Licensed to the Apache Software Foundation (ASF) under one 8 * or more contributor license agreements. See the NOTICE file 9 * distributed with this work for additional information 10 * regarding copyright ownership. The ASF licenses this file 11 * to you under the Apache License, Version 2.0 (the 12 * "License"); you may not use this file except in compliance 13 * with the License. You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, 18 * software distributed under the License is distributed on an 19 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 20 * KIND, either express or implied. See the License for the 21 * specific language governing permissions and limitations 22 * under the License. 23 * ==================================================================== 24 * 25 * This software consists of voluntary contributions made by many 26 * individuals on behalf of the Apache Software Foundation. For more 27 * information on the Apache Software Foundation, please see 28 * <http://www.apache.org/>. 29 * 30 */ 31 32 package org.apache.http.message; 33 34 35 import java.util.List; 36 import java.util.ArrayList; 37 38 import org.apache.http.HeaderElement; 39 import org.apache.http.NameValuePair; 40 import org.apache.http.ParseException; 41 import org.apache.http.protocol.HTTP; 42 import org.apache.http.util.CharArrayBuffer; 43 44 45 46 /** 47 * Basic implementation for parsing header values into elements. 48 * Instances of this class are stateless and thread-safe. 49 * Derived classes are expected to maintain these properties. 50 * 51 * @author <a href="mailto:bcholmes@interlog.com">B.C. Holmes</a> 52 * @author <a href="mailto:jericho@thinkfree.com">Park, Sung-Gu</a> 53 * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a> 54 * @author <a href="mailto:oleg at ural.com">Oleg Kalnichevski</a> 55 * @author and others 56 * 57 * 58 * <!-- empty lines above to avoid 'svn diff' context problems --> 59 * @version $Revision: 595670 $ 60 * 61 * @since 4.0 62 * 63 * @deprecated Please use {@link java.net.URL#openConnection} instead. 64 * Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a> 65 * for further details. 66 */ 67 @Deprecated 68 public class BasicHeaderValueParser implements HeaderValueParser { 69 70 /** 71 * A default instance of this class, for use as default or fallback. 72 * Note that {@link BasicHeaderValueParser} is not a singleton, there 73 * can be many instances of the class itself and of derived classes. 74 * The instance here provides non-customized, default behavior. 75 */ 76 public final static 77 BasicHeaderValueParser DEFAULT = new BasicHeaderValueParser(); 78 79 private final static char PARAM_DELIMITER = ';'; 80 private final static char ELEM_DELIMITER = ','; 81 private final static char[] ALL_DELIMITERS = new char[] { 82 PARAM_DELIMITER, 83 ELEM_DELIMITER 84 }; 85 86 // public default constructor 87 88 89 /** 90 * Parses elements with the given parser. 91 * 92 * @param value the header value to parse 93 * @param parser the parser to use, or <code>null</code> for default 94 * 95 * @return array holding the header elements, never <code>null</code> 96 */ 97 public final static parseElements(final String value, HeaderValueParser parser)98 HeaderElement[] parseElements(final String value, 99 HeaderValueParser parser) 100 throws ParseException { 101 102 if (value == null) { 103 throw new IllegalArgumentException 104 ("Value to parse may not be null"); 105 } 106 107 if (parser == null) 108 parser = BasicHeaderValueParser.DEFAULT; 109 110 CharArrayBuffer buffer = new CharArrayBuffer(value.length()); 111 buffer.append(value); 112 ParserCursor cursor = new ParserCursor(0, value.length()); 113 return parser.parseElements(buffer, cursor); 114 } 115 116 117 // non-javadoc, see interface HeaderValueParser parseElements(final CharArrayBuffer buffer, final ParserCursor cursor)118 public HeaderElement[] parseElements(final CharArrayBuffer buffer, 119 final ParserCursor cursor) { 120 121 if (buffer == null) { 122 throw new IllegalArgumentException("Char array buffer may not be null"); 123 } 124 if (cursor == null) { 125 throw new IllegalArgumentException("Parser cursor may not be null"); 126 } 127 128 List elements = new ArrayList(); 129 while (!cursor.atEnd()) { 130 HeaderElement element = parseHeaderElement(buffer, cursor); 131 if (!(element.getName().length() == 0 && element.getValue() == null)) { 132 elements.add(element); 133 } 134 } 135 return (HeaderElement[]) 136 elements.toArray(new HeaderElement[elements.size()]); 137 } 138 139 140 /** 141 * Parses an element with the given parser. 142 * 143 * @param value the header element to parse 144 * @param parser the parser to use, or <code>null</code> for default 145 * 146 * @return the parsed header element 147 */ 148 public final static parseHeaderElement(final String value, HeaderValueParser parser)149 HeaderElement parseHeaderElement(final String value, 150 HeaderValueParser parser) 151 throws ParseException { 152 153 if (value == null) { 154 throw new IllegalArgumentException 155 ("Value to parse may not be null"); 156 } 157 158 if (parser == null) 159 parser = BasicHeaderValueParser.DEFAULT; 160 161 CharArrayBuffer buffer = new CharArrayBuffer(value.length()); 162 buffer.append(value); 163 ParserCursor cursor = new ParserCursor(0, value.length()); 164 return parser.parseHeaderElement(buffer, cursor); 165 } 166 167 168 // non-javadoc, see interface HeaderValueParser parseHeaderElement(final CharArrayBuffer buffer, final ParserCursor cursor)169 public HeaderElement parseHeaderElement(final CharArrayBuffer buffer, 170 final ParserCursor cursor) { 171 172 if (buffer == null) { 173 throw new IllegalArgumentException("Char array buffer may not be null"); 174 } 175 if (cursor == null) { 176 throw new IllegalArgumentException("Parser cursor may not be null"); 177 } 178 179 NameValuePair nvp = parseNameValuePair(buffer, cursor); 180 NameValuePair[] params = null; 181 if (!cursor.atEnd()) { 182 char ch = buffer.charAt(cursor.getPos() - 1); 183 if (ch != ELEM_DELIMITER) { 184 params = parseParameters(buffer, cursor); 185 } 186 } 187 return createHeaderElement(nvp.getName(), nvp.getValue(), params); 188 } 189 190 191 /** 192 * Creates a header element. 193 * Called from {@link #parseHeaderElement}. 194 * 195 * @return a header element representing the argument 196 */ createHeaderElement( final String name, final String value, final NameValuePair[] params)197 protected HeaderElement createHeaderElement( 198 final String name, 199 final String value, 200 final NameValuePair[] params) { 201 return new BasicHeaderElement(name, value, params); 202 } 203 204 205 /** 206 * Parses parameters with the given parser. 207 * 208 * @param value the parameter list to parse 209 * @param parser the parser to use, or <code>null</code> for default 210 * 211 * @return array holding the parameters, never <code>null</code> 212 */ 213 public final static parseParameters(final String value, HeaderValueParser parser)214 NameValuePair[] parseParameters(final String value, 215 HeaderValueParser parser) 216 throws ParseException { 217 218 if (value == null) { 219 throw new IllegalArgumentException 220 ("Value to parse may not be null"); 221 } 222 223 if (parser == null) 224 parser = BasicHeaderValueParser.DEFAULT; 225 226 CharArrayBuffer buffer = new CharArrayBuffer(value.length()); 227 buffer.append(value); 228 ParserCursor cursor = new ParserCursor(0, value.length()); 229 return parser.parseParameters(buffer, cursor); 230 } 231 232 233 234 // non-javadoc, see interface HeaderValueParser parseParameters(final CharArrayBuffer buffer, final ParserCursor cursor)235 public NameValuePair[] parseParameters(final CharArrayBuffer buffer, 236 final ParserCursor cursor) { 237 238 if (buffer == null) { 239 throw new IllegalArgumentException("Char array buffer may not be null"); 240 } 241 if (cursor == null) { 242 throw new IllegalArgumentException("Parser cursor may not be null"); 243 } 244 245 int pos = cursor.getPos(); 246 int indexTo = cursor.getUpperBound(); 247 248 while (pos < indexTo) { 249 char ch = buffer.charAt(pos); 250 if (HTTP.isWhitespace(ch)) { 251 pos++; 252 } else { 253 break; 254 } 255 } 256 cursor.updatePos(pos); 257 if (cursor.atEnd()) { 258 return new NameValuePair[] {}; 259 } 260 261 List params = new ArrayList(); 262 while (!cursor.atEnd()) { 263 NameValuePair param = parseNameValuePair(buffer, cursor); 264 params.add(param); 265 char ch = buffer.charAt(cursor.getPos() - 1); 266 if (ch == ELEM_DELIMITER) { 267 break; 268 } 269 } 270 271 return (NameValuePair[]) 272 params.toArray(new NameValuePair[params.size()]); 273 } 274 275 /** 276 * Parses a name-value-pair with the given parser. 277 * 278 * @param value the NVP to parse 279 * @param parser the parser to use, or <code>null</code> for default 280 * 281 * @return the parsed name-value pair 282 */ 283 public final static parseNameValuePair(final String value, HeaderValueParser parser)284 NameValuePair parseNameValuePair(final String value, 285 HeaderValueParser parser) 286 throws ParseException { 287 288 if (value == null) { 289 throw new IllegalArgumentException 290 ("Value to parse may not be null"); 291 } 292 293 if (parser == null) 294 parser = BasicHeaderValueParser.DEFAULT; 295 296 CharArrayBuffer buffer = new CharArrayBuffer(value.length()); 297 buffer.append(value); 298 ParserCursor cursor = new ParserCursor(0, value.length()); 299 return parser.parseNameValuePair(buffer, cursor); 300 } 301 302 303 // non-javadoc, see interface HeaderValueParser parseNameValuePair(final CharArrayBuffer buffer, final ParserCursor cursor)304 public NameValuePair parseNameValuePair(final CharArrayBuffer buffer, 305 final ParserCursor cursor) { 306 return parseNameValuePair(buffer, cursor, ALL_DELIMITERS); 307 } 308 isOneOf(final char ch, final char[] chs)309 private static boolean isOneOf(final char ch, final char[] chs) { 310 if (chs != null) { 311 for (int i = 0; i < chs.length; i++) { 312 if (ch == chs[i]) { 313 return true; 314 } 315 } 316 } 317 return false; 318 } 319 parseNameValuePair(final CharArrayBuffer buffer, final ParserCursor cursor, final char[] delimiters)320 public NameValuePair parseNameValuePair(final CharArrayBuffer buffer, 321 final ParserCursor cursor, 322 final char[] delimiters) { 323 324 if (buffer == null) { 325 throw new IllegalArgumentException("Char array buffer may not be null"); 326 } 327 if (cursor == null) { 328 throw new IllegalArgumentException("Parser cursor may not be null"); 329 } 330 331 boolean terminated = false; 332 333 int pos = cursor.getPos(); 334 int indexFrom = cursor.getPos(); 335 int indexTo = cursor.getUpperBound(); 336 337 // Find name 338 String name = null; 339 while (pos < indexTo) { 340 char ch = buffer.charAt(pos); 341 if (ch == '=') { 342 break; 343 } 344 if (isOneOf(ch, delimiters)) { 345 terminated = true; 346 break; 347 } 348 pos++; 349 } 350 351 if (pos == indexTo) { 352 terminated = true; 353 name = buffer.substringTrimmed(indexFrom, indexTo); 354 } else { 355 name = buffer.substringTrimmed(indexFrom, pos); 356 pos++; 357 } 358 359 if (terminated) { 360 cursor.updatePos(pos); 361 return createNameValuePair(name, null); 362 } 363 364 // Find value 365 String value = null; 366 int i1 = pos; 367 368 boolean qouted = false; 369 boolean escaped = false; 370 while (pos < indexTo) { 371 char ch = buffer.charAt(pos); 372 if (ch == '"' && !escaped) { 373 qouted = !qouted; 374 } 375 if (!qouted && !escaped && isOneOf(ch, delimiters)) { 376 terminated = true; 377 break; 378 } 379 if (escaped) { 380 escaped = false; 381 } else { 382 escaped = qouted && ch == '\\'; 383 } 384 pos++; 385 } 386 387 int i2 = pos; 388 // Trim leading white spaces 389 while (i1 < i2 && (HTTP.isWhitespace(buffer.charAt(i1)))) { 390 i1++; 391 } 392 // Trim trailing white spaces 393 while ((i2 > i1) && (HTTP.isWhitespace(buffer.charAt(i2 - 1)))) { 394 i2--; 395 } 396 // Strip away quotes if necessary 397 if (((i2 - i1) >= 2) 398 && (buffer.charAt(i1) == '"') 399 && (buffer.charAt(i2 - 1) == '"')) { 400 i1++; 401 i2--; 402 } 403 value = buffer.substring(i1, i2); 404 if (terminated) { 405 pos++; 406 } 407 cursor.updatePos(pos); 408 return createNameValuePair(name, value); 409 } 410 411 /** 412 * Creates a name-value pair. 413 * Called from {@link #parseNameValuePair}. 414 * 415 * @param name the name 416 * @param value the value, or <code>null</code> 417 * 418 * @return a name-value pair representing the arguments 419 */ createNameValuePair(final String name, final String value)420 protected NameValuePair createNameValuePair(final String name, final String value) { 421 return new BasicNameValuePair(name, value); 422 } 423 424 } 425 426