mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHeaderValueFormatter.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 ch.boye.httpclientandroidlib.HeaderElement;
michael@0 31 import ch.boye.httpclientandroidlib.NameValuePair;
michael@0 32 import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
michael@0 33
michael@0 34 /**
michael@0 35 * Basic implementation for formatting header value elements.
michael@0 36 * Instances of this class are stateless and thread-safe.
michael@0 37 * Derived classes are expected to maintain these properties.
michael@0 38 *
michael@0 39 * @since 4.0
michael@0 40 */
michael@0 41 public class BasicHeaderValueFormatter implements HeaderValueFormatter {
michael@0 42
michael@0 43 /**
michael@0 44 * A default instance of this class, for use as default or fallback.
michael@0 45 * Note that {@link BasicHeaderValueFormatter} is not a singleton, there
michael@0 46 * can be many instances of the class itself and of derived classes.
michael@0 47 * The instance here provides non-customized, default behavior.
michael@0 48 */
michael@0 49 public final static
michael@0 50 BasicHeaderValueFormatter DEFAULT = new BasicHeaderValueFormatter();
michael@0 51
michael@0 52
michael@0 53 /**
michael@0 54 * Special characters that can be used as separators in HTTP parameters.
michael@0 55 * These special characters MUST be in a quoted string to be used within
michael@0 56 * a parameter value .
michael@0 57 */
michael@0 58 public final static String SEPARATORS = " ;,:@()<>\\\"/[]?={}\t";
michael@0 59
michael@0 60
michael@0 61 /**
michael@0 62 * Unsafe special characters that must be escaped using the backslash
michael@0 63 * character
michael@0 64 */
michael@0 65 public final static String UNSAFE_CHARS = "\"\\";
michael@0 66
michael@0 67
michael@0 68
michael@0 69 // public default constructor
michael@0 70
michael@0 71
michael@0 72
michael@0 73 /**
michael@0 74 * Formats an array of header elements.
michael@0 75 *
michael@0 76 * @param elems the header elements to format
michael@0 77 * @param quote <code>true</code> to always format with quoted values,
michael@0 78 * <code>false</code> to use quotes only when necessary
michael@0 79 * @param formatter the formatter to use, or <code>null</code>
michael@0 80 * for the {@link #DEFAULT default}
michael@0 81 *
michael@0 82 * @return the formatted header elements
michael@0 83 */
michael@0 84 public final static
michael@0 85 String formatElements(final HeaderElement[] elems,
michael@0 86 final boolean quote,
michael@0 87 HeaderValueFormatter formatter) {
michael@0 88 if (formatter == null)
michael@0 89 formatter = BasicHeaderValueFormatter.DEFAULT;
michael@0 90 return formatter.formatElements(null, elems, quote).toString();
michael@0 91 }
michael@0 92
michael@0 93
michael@0 94 // non-javadoc, see interface HeaderValueFormatter
michael@0 95 public CharArrayBuffer formatElements(CharArrayBuffer buffer,
michael@0 96 final HeaderElement[] elems,
michael@0 97 final boolean quote) {
michael@0 98 if (elems == null) {
michael@0 99 throw new IllegalArgumentException
michael@0 100 ("Header element array must not be null.");
michael@0 101 }
michael@0 102
michael@0 103 int len = estimateElementsLen(elems);
michael@0 104 if (buffer == null) {
michael@0 105 buffer = new CharArrayBuffer(len);
michael@0 106 } else {
michael@0 107 buffer.ensureCapacity(len);
michael@0 108 }
michael@0 109
michael@0 110 for (int i=0; i<elems.length; i++) {
michael@0 111 if (i > 0) {
michael@0 112 buffer.append(", ");
michael@0 113 }
michael@0 114 formatHeaderElement(buffer, elems[i], quote);
michael@0 115 }
michael@0 116
michael@0 117 return buffer;
michael@0 118 }
michael@0 119
michael@0 120
michael@0 121 /**
michael@0 122 * Estimates the length of formatted header elements.
michael@0 123 *
michael@0 124 * @param elems the header elements to format, or <code>null</code>
michael@0 125 *
michael@0 126 * @return a length estimate, in number of characters
michael@0 127 */
michael@0 128 protected int estimateElementsLen(final HeaderElement[] elems) {
michael@0 129 if ((elems == null) || (elems.length < 1))
michael@0 130 return 0;
michael@0 131
michael@0 132 int result = (elems.length-1) * 2; // elements separated by ", "
michael@0 133 for (int i=0; i<elems.length; i++) {
michael@0 134 result += estimateHeaderElementLen(elems[i]);
michael@0 135 }
michael@0 136
michael@0 137 return result;
michael@0 138 }
michael@0 139
michael@0 140
michael@0 141
michael@0 142 /**
michael@0 143 * Formats a header element.
michael@0 144 *
michael@0 145 * @param elem the header element to format
michael@0 146 * @param quote <code>true</code> to always format with quoted values,
michael@0 147 * <code>false</code> to use quotes only when necessary
michael@0 148 * @param formatter the formatter to use, or <code>null</code>
michael@0 149 * for the {@link #DEFAULT default}
michael@0 150 *
michael@0 151 * @return the formatted header element
michael@0 152 */
michael@0 153 public final static
michael@0 154 String formatHeaderElement(final HeaderElement elem,
michael@0 155 boolean quote,
michael@0 156 HeaderValueFormatter formatter) {
michael@0 157 if (formatter == null)
michael@0 158 formatter = BasicHeaderValueFormatter.DEFAULT;
michael@0 159 return formatter.formatHeaderElement(null, elem, quote).toString();
michael@0 160 }
michael@0 161
michael@0 162
michael@0 163 // non-javadoc, see interface HeaderValueFormatter
michael@0 164 public CharArrayBuffer formatHeaderElement(CharArrayBuffer buffer,
michael@0 165 final HeaderElement elem,
michael@0 166 final boolean quote) {
michael@0 167 if (elem == null) {
michael@0 168 throw new IllegalArgumentException
michael@0 169 ("Header element must not be null.");
michael@0 170 }
michael@0 171
michael@0 172 int len = estimateHeaderElementLen(elem);
michael@0 173 if (buffer == null) {
michael@0 174 buffer = new CharArrayBuffer(len);
michael@0 175 } else {
michael@0 176 buffer.ensureCapacity(len);
michael@0 177 }
michael@0 178
michael@0 179 buffer.append(elem.getName());
michael@0 180 final String value = elem.getValue();
michael@0 181 if (value != null) {
michael@0 182 buffer.append('=');
michael@0 183 doFormatValue(buffer, value, quote);
michael@0 184 }
michael@0 185
michael@0 186 final int parcnt = elem.getParameterCount();
michael@0 187 if (parcnt > 0) {
michael@0 188 for (int i=0; i<parcnt; i++) {
michael@0 189 buffer.append("; ");
michael@0 190 formatNameValuePair(buffer, elem.getParameter(i), quote);
michael@0 191 }
michael@0 192 }
michael@0 193
michael@0 194 return buffer;
michael@0 195 }
michael@0 196
michael@0 197
michael@0 198 /**
michael@0 199 * Estimates the length of a formatted header element.
michael@0 200 *
michael@0 201 * @param elem the header element to format, or <code>null</code>
michael@0 202 *
michael@0 203 * @return a length estimate, in number of characters
michael@0 204 */
michael@0 205 protected int estimateHeaderElementLen(final HeaderElement elem) {
michael@0 206 if (elem == null)
michael@0 207 return 0;
michael@0 208
michael@0 209 int result = elem.getName().length(); // name
michael@0 210 final String value = elem.getValue();
michael@0 211 if (value != null) {
michael@0 212 // assume quotes, but no escaped characters
michael@0 213 result += 3 + value.length(); // ="value"
michael@0 214 }
michael@0 215
michael@0 216 final int parcnt = elem.getParameterCount();
michael@0 217 if (parcnt > 0) {
michael@0 218 for (int i=0; i<parcnt; i++) {
michael@0 219 result += 2 + // ; <param>
michael@0 220 estimateNameValuePairLen(elem.getParameter(i));
michael@0 221 }
michael@0 222 }
michael@0 223
michael@0 224 return result;
michael@0 225 }
michael@0 226
michael@0 227
michael@0 228
michael@0 229
michael@0 230 /**
michael@0 231 * Formats a set of parameters.
michael@0 232 *
michael@0 233 * @param nvps the parameters to format
michael@0 234 * @param quote <code>true</code> to always format with quoted values,
michael@0 235 * <code>false</code> to use quotes only when necessary
michael@0 236 * @param formatter the formatter to use, or <code>null</code>
michael@0 237 * for the {@link #DEFAULT default}
michael@0 238 *
michael@0 239 * @return the formatted parameters
michael@0 240 */
michael@0 241 public final static
michael@0 242 String formatParameters(final NameValuePair[] nvps,
michael@0 243 final boolean quote,
michael@0 244 HeaderValueFormatter formatter) {
michael@0 245 if (formatter == null)
michael@0 246 formatter = BasicHeaderValueFormatter.DEFAULT;
michael@0 247 return formatter.formatParameters(null, nvps, quote).toString();
michael@0 248 }
michael@0 249
michael@0 250
michael@0 251 // non-javadoc, see interface HeaderValueFormatter
michael@0 252 public CharArrayBuffer formatParameters(CharArrayBuffer buffer,
michael@0 253 NameValuePair[] nvps,
michael@0 254 boolean quote) {
michael@0 255 if (nvps == null) {
michael@0 256 throw new IllegalArgumentException
michael@0 257 ("Parameters must not be null.");
michael@0 258 }
michael@0 259
michael@0 260 int len = estimateParametersLen(nvps);
michael@0 261 if (buffer == null) {
michael@0 262 buffer = new CharArrayBuffer(len);
michael@0 263 } else {
michael@0 264 buffer.ensureCapacity(len);
michael@0 265 }
michael@0 266
michael@0 267 for (int i = 0; i < nvps.length; i++) {
michael@0 268 if (i > 0) {
michael@0 269 buffer.append("; ");
michael@0 270 }
michael@0 271 formatNameValuePair(buffer, nvps[i], quote);
michael@0 272 }
michael@0 273
michael@0 274 return buffer;
michael@0 275 }
michael@0 276
michael@0 277
michael@0 278 /**
michael@0 279 * Estimates the length of formatted parameters.
michael@0 280 *
michael@0 281 * @param nvps the parameters to format, or <code>null</code>
michael@0 282 *
michael@0 283 * @return a length estimate, in number of characters
michael@0 284 */
michael@0 285 protected int estimateParametersLen(final NameValuePair[] nvps) {
michael@0 286 if ((nvps == null) || (nvps.length < 1))
michael@0 287 return 0;
michael@0 288
michael@0 289 int result = (nvps.length-1) * 2; // "; " between the parameters
michael@0 290 for (int i=0; i<nvps.length; i++) {
michael@0 291 result += estimateNameValuePairLen(nvps[i]);
michael@0 292 }
michael@0 293
michael@0 294 return result;
michael@0 295 }
michael@0 296
michael@0 297
michael@0 298 /**
michael@0 299 * Formats a name-value pair.
michael@0 300 *
michael@0 301 * @param nvp the name-value pair to format
michael@0 302 * @param quote <code>true</code> to always format with a quoted value,
michael@0 303 * <code>false</code> to use quotes only when necessary
michael@0 304 * @param formatter the formatter to use, or <code>null</code>
michael@0 305 * for the {@link #DEFAULT default}
michael@0 306 *
michael@0 307 * @return the formatted name-value pair
michael@0 308 */
michael@0 309 public final static
michael@0 310 String formatNameValuePair(final NameValuePair nvp,
michael@0 311 final boolean quote,
michael@0 312 HeaderValueFormatter formatter) {
michael@0 313 if (formatter == null)
michael@0 314 formatter = BasicHeaderValueFormatter.DEFAULT;
michael@0 315 return formatter.formatNameValuePair(null, nvp, quote).toString();
michael@0 316 }
michael@0 317
michael@0 318
michael@0 319 // non-javadoc, see interface HeaderValueFormatter
michael@0 320 public CharArrayBuffer formatNameValuePair(CharArrayBuffer buffer,
michael@0 321 final NameValuePair nvp,
michael@0 322 final boolean quote) {
michael@0 323 if (nvp == null) {
michael@0 324 throw new IllegalArgumentException
michael@0 325 ("NameValuePair must not be null.");
michael@0 326 }
michael@0 327
michael@0 328 int len = estimateNameValuePairLen(nvp);
michael@0 329 if (buffer == null) {
michael@0 330 buffer = new CharArrayBuffer(len);
michael@0 331 } else {
michael@0 332 buffer.ensureCapacity(len);
michael@0 333 }
michael@0 334
michael@0 335 buffer.append(nvp.getName());
michael@0 336 final String value = nvp.getValue();
michael@0 337 if (value != null) {
michael@0 338 buffer.append('=');
michael@0 339 doFormatValue(buffer, value, quote);
michael@0 340 }
michael@0 341
michael@0 342 return buffer;
michael@0 343 }
michael@0 344
michael@0 345
michael@0 346 /**
michael@0 347 * Estimates the length of a formatted name-value pair.
michael@0 348 *
michael@0 349 * @param nvp the name-value pair to format, or <code>null</code>
michael@0 350 *
michael@0 351 * @return a length estimate, in number of characters
michael@0 352 */
michael@0 353 protected int estimateNameValuePairLen(final NameValuePair nvp) {
michael@0 354 if (nvp == null)
michael@0 355 return 0;
michael@0 356
michael@0 357 int result = nvp.getName().length(); // name
michael@0 358 final String value = nvp.getValue();
michael@0 359 if (value != null) {
michael@0 360 // assume quotes, but no escaped characters
michael@0 361 result += 3 + value.length(); // ="value"
michael@0 362 }
michael@0 363 return result;
michael@0 364 }
michael@0 365
michael@0 366
michael@0 367 /**
michael@0 368 * Actually formats the value of a name-value pair.
michael@0 369 * This does not include a leading = character.
michael@0 370 * Called from {@link #formatNameValuePair formatNameValuePair}.
michael@0 371 *
michael@0 372 * @param buffer the buffer to append to, never <code>null</code>
michael@0 373 * @param value the value to append, never <code>null</code>
michael@0 374 * @param quote <code>true</code> to always format with quotes,
michael@0 375 * <code>false</code> to use quotes only when necessary
michael@0 376 */
michael@0 377 protected void doFormatValue(final CharArrayBuffer buffer,
michael@0 378 final String value,
michael@0 379 boolean quote) {
michael@0 380
michael@0 381 if (!quote) {
michael@0 382 for (int i = 0; (i < value.length()) && !quote; i++) {
michael@0 383 quote = isSeparator(value.charAt(i));
michael@0 384 }
michael@0 385 }
michael@0 386
michael@0 387 if (quote) {
michael@0 388 buffer.append('"');
michael@0 389 }
michael@0 390 for (int i = 0; i < value.length(); i++) {
michael@0 391 char ch = value.charAt(i);
michael@0 392 if (isUnsafe(ch)) {
michael@0 393 buffer.append('\\');
michael@0 394 }
michael@0 395 buffer.append(ch);
michael@0 396 }
michael@0 397 if (quote) {
michael@0 398 buffer.append('"');
michael@0 399 }
michael@0 400 }
michael@0 401
michael@0 402
michael@0 403 /**
michael@0 404 * Checks whether a character is a {@link #SEPARATORS separator}.
michael@0 405 *
michael@0 406 * @param ch the character to check
michael@0 407 *
michael@0 408 * @return <code>true</code> if the character is a separator,
michael@0 409 * <code>false</code> otherwise
michael@0 410 */
michael@0 411 protected boolean isSeparator(char ch) {
michael@0 412 return SEPARATORS.indexOf(ch) >= 0;
michael@0 413 }
michael@0 414
michael@0 415
michael@0 416 /**
michael@0 417 * Checks whether a character is {@link #UNSAFE_CHARS unsafe}.
michael@0 418 *
michael@0 419 * @param ch the character to check
michael@0 420 *
michael@0 421 * @return <code>true</code> if the character is unsafe,
michael@0 422 * <code>false</code> otherwise
michael@0 423 */
michael@0 424 protected boolean isUnsafe(char ch) {
michael@0 425 return UNSAFE_CHARS.indexOf(ch) >= 0;
michael@0 426 }
michael@0 427
michael@0 428
michael@0 429 } // class BasicHeaderValueFormatter

mercurial