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