mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHeaderValueParser.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

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

mercurial