1 /* 2 * $Header: /u/cvs/Projects/EnhydraOrg/enhydra3x/Enhydra/modules/Tomcat/src/share/org/apache/tomcat/util/MimeHeaderField.java,v 1.2.2.2 2000/03/24 00:54:46 peterj Exp $ 3 * $Revision: 1.2.2.2 $ 4 * $Date: 2000/03/24 00:54:46 $ 5 * 6 * ==================================================================== 7 * 8 * The Apache Software License, Version 1.1 9 * 10 * Copyright (c) 1999 The Apache Software Foundation. All rights 11 * reserved. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 20 * 2. Redistributions in binary form must reproduce the above copyright 21 * notice, this list of conditions and the following disclaimer in 22 * the documentation and/or other materials provided with the 23 * distribution. 24 * 25 * 3. The end-user documentation included with the redistribution, if 26 * any, must include the following acknowlegement: 27 * "This product includes software developed by the 28 * Apache Software Foundation (http://www.apache.org/)." 29 * Alternately, this acknowlegement may appear in the software itself, 30 * if and wherever such third-party acknowlegements normally appear. 31 * 32 * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software 33 * Foundation" must not be used to endorse or promote products derived 34 * from this software without prior written permission. For written 35 * permission, please contact apache@apache.org. 36 * 37 * 5. Products derived from this software may not be called "Apache" 38 * nor may "Apache" appear in their names without prior written 39 * permission of the Apache Group. 40 * 41 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 42 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 43 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 44 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 45 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 46 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 47 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 48 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 49 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 50 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 51 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 52 * SUCH DAMAGE. 53 * ==================================================================== 54 * 55 * This software consists of voluntary contributions made by many 56 * individuals on behalf of the Apache Software Foundation. For more 57 * information on the Apache Software Foundation, please see 58 * <http://www.apache.org/>. 59 * 60 * [Additional notices, if required by prior licensing conditions] 61 * 62 */ 63 64 65 package org.apache.tomcat.util; 66 67 import javax.servlet; 68 import java.io.IOException; 69 import java.io.OutputStream; 70 71 /** 72 * This class is used to represent a MIME header field. 73 * 74 * @author dac@eng.sun.com 75 * @author James Todd [gonzo@eng.sun.com] 76 */ 77 78 public class MimeHeaderField { 79 80 private StringManager stringManager = null; 81 // StringManager.getManager(Constants.Package); 82 83 private StringManager getSM() { 84 if (stringManager == null) { 85 stringManager = StringManager.getManager(Constants.Package); 86 } 87 return stringManager; 88 } 89 90 /** 91 * The header field name. 92 */ 93 94 protected final MessageString name = new MessageString(); 95 96 /** 97 * The header field value. 98 */ 99 100 protected final MessageString value = new MessageString(); 101 102 /** 103 * The header field integer value. 104 */ 105 106 protected int intValue; 107 108 /** 109 * The header field Date value. 110 */ 111 112 // protected final HttpDate dateValue = new HttpDate(0); 113 protected HttpDate dateValue = null; 114 115 private HttpDate dateValue() { 116 if (dateValue == null) { 117 dateValue = new HttpDate(0); 118 } 119 return dateValue; 120 } 121 122 /** 123 * The header field value type. 124 */ 125 126 protected int type = T_NULL; 127 128 protected static final int T_NULL = 0; 129 protected static final int T_STR = 1; 130 protected static final int T_INT = 2; 131 protected static final int T_DATE = 3; 132 133 private static final byte[] charval = { 134 (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', 135 (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9' 136 }; 137 138 /** 139 * Creates a new, uninitialized header field. 140 */ 141 142 public MimeHeaderField() { 143 } 144 145 /** 146 * Resets the header field to an uninitialized state. 147 */ 148 149 public void reset() { 150 name.reset(); 151 value.reset(); 152 type = T_NULL; 153 } 154 155 /** 156 * Sets the header field name to the specified string. 157 * @param s the header field name String 158 */ 159 160 public void setName(String s) { 161 name.setString(s); 162 } 163 164 /** 165 * Sets the header field name to the specified subarray of bytes. 166 * @param b the header field name bytes 167 * @param off the start offset of the bytes 168 * @param len the length of the bytes 169 */ 170 171 public void setName(byte[] b, int off, int len) { 172 name.setBytes(b, off, len); 173 } 174 175 /** 176 * Sets the header field value to the specified string. 177 * @param s the header field value String 178 */ 179 180 public void setValue(String s) { 181 value.setString(s); 182 type = T_STR; 183 } 184 185 /** 186 * Sets the header field value to the specified subarray of bytes. 187 * @param b the header field value bytes 188 * @param off the start offset of the bytes 189 * @param len the length of the bytes 190 */ 191 192 public void setValue(byte[] b, int off, int len) { 193 value.setBytes(b, off, len); 194 type = T_STR; 195 } 196 197 /** 198 * Sets the header field to the specified integer value. 199 * @param i the header field integer value 200 */ 201 202 public void setIntValue(int i) { 203 intValue = i; 204 type = T_INT; 205 } 206 207 /** 208 * Sets the header field date value to the specified time. 209 * @param t the time in milliseconds since the epoch 210 */ 211 212 public void setDateValue(long t) { 213 dateValue().setTime(t); 214 type = T_DATE; 215 } 216 217 /** 218 * Sets the header field date value to the current time. 219 */ 220 221 public void setDateValue() { 222 dateValue().setTime(); 223 type = T_DATE; 224 } 225 226 /** 227 * Returns the header field name as a String. 228 */ 229 230 public String getName() { 231 return name.toString(); 232 } 233 234 /** 235 * Returns the header field value as a String, or null if not set. 236 */ 237 238 public String getValue() { 239 switch (type) { 240 case T_STR: 241 return value.toString(); 242 case T_INT: 243 return String.valueOf(intValue); 244 case T_DATE: 245 return dateValue().toString(); 246 default: 247 return null; 248 } 249 } 250 251 /** 252 * Returns the integer value of the header field. 253 * @exception NumberFormatException if the integer format was invalid 254 */ 255 256 public int getIntValue() 257 throws NumberFormatException { 258 switch (type) { 259 case T_INT: 260 return intValue; 261 case T_STR: 262 return value.toInteger(); 263 default: 264 String msg = getSM().getString("mimeHeaderField.int.nfe"); 265 266 throw new NumberFormatException(msg); 267 } 268 } 269 270 /** 271 * Returns the date value of the header field. 272 * @return the header date value in number of milliseconds since the epoch 273 * @exception IllegalArgumentException if the date format was invalid 274 */ 275 276 public long getDateValue() 277 throws IllegalArgumentException { 278 switch (type) { 279 case T_DATE: 280 return dateValue().getTime(); 281 case T_STR: 282 return value.toDate(dateValue()); 283 default: 284 String msg = getSM().getString("mimeHeaderField.date.iae"); 285 286 throw new IllegalArgumentException(msg); 287 } 288 } 289 290 /** 291 * Place a byte representation of target into the byte array buf. 292 * @param target - the integer to convert. Must be in the range [0..2^31]. 293 * @return the number of bytes added to buf 294 */ 295 296 private int intGetBytes(int target, byte buf[], int offset) { 297 int power = 1000000000; // magnitude of highest digit we can handle 298 int this_digit; 299 int bytes_emitted = 0; 300 301 // special case target is zero 302 if (target == 0) { 303 buf[offset] = charval[0]; 304 305 return (1); 306 } 307 308 // iterate until there are no more digits to emit 309 while (power > 0) { 310 this_digit = target / power; 311 312 if (this_digit != 0 || bytes_emitted > 0) { 313 // emit this digit 314 buf[offset + bytes_emitted++] = charval[this_digit]; 315 } 316 317 target = target % power; 318 power = power / 10; 319 } 320 321 return bytes_emitted; 322 } 323 324 /** 325 * Put the bytes for this header into buf starting at offset buf_offset. 326 * @return the length of what was added 327 */ 328 329 public int getBytes(byte buf[], int buf_offset) { 330 int len; 331 int start_pt = buf_offset; 332 333 buf_offset += name.getBytes(buf, buf_offset); 334 buf[buf_offset++] = (byte) ':'; 335 buf[buf_offset++] = (byte) ' '; 336 337 switch (type) { 338 case T_STR: 339 buf_offset += value.getBytes(buf, buf_offset); 340 break; 341 case T_INT: 342 buf_offset += intGetBytes(intValue, buf, buf_offset); 343 break; 344 case T_DATE: 345 buf_offset += dateValue().getBytes(buf, buf_offset, 346 HttpDate.DATELEN); 347 break; 348 } 349 350 buf[buf_offset++] = (byte) '\r'; 351 buf[buf_offset++] = (byte) '\n'; 352 353 return buf_offset - start_pt; 354 } 355 356 /** 357 * Parses a header field from a subarray of bytes. 358 * @param b the bytes to parse 359 * @param off the start offset of the bytes 360 * @param len the length of the bytes 361 * @exception IllegalArgumentException if the header format was invalid 362 */ 363 364 public void parse(byte[] b, int off, int len) 365 throws IllegalArgumentException { 366 int start = off; 367 byte c; 368 369 while ((c = b[off++]) != ':' && c != ' ') { 370 if (c == '\n') { 371 String msg = getSM().getString("mimeHeaderField.header.iae"); 372 373 throw new IllegalArgumentException(msg); 374 } 375 } 376 377 setName(b, start, off - start - 1); 378 379 while (c == ' ') { 380 c = b[off++]; 381 } 382 383 if (c != ':') { 384 String msg = getSM().getString("mimeHeaderField.header.iae"); 385 386 throw new IllegalArgumentException(msg); 387 } 388 389 while ((c = b[off++]) == ' '); 390 391 setValue(b, off - 1, len - (off - start - 1)); 392 } 393 394 /** 395 * Writes this header field to the specified servlet output stream. 396 */ 397 398 public void write(ServletOutputStream out) 399 throws IOException { 400 name.write(out); 401 out.print(": "); 402 403 switch (type) { 404 case T_STR: 405 value.write(out); 406 out.println(); 407 break; 408 case T_INT: 409 out.println(intValue); 410 break; 411 case T_DATE: 412 dateValue().write(out); 413 out.println(); 414 break; 415 default: 416 out.println(); 417 } 418 } 419 420 /** 421 * Returns true if the header field has the specified name. Character 422 * case is ignored in the comparison. 423 * @param s the string to compare 424 */ 425 426 public boolean nameEquals(String s) { 427 return name.equalsIgnoreCase(s); 428 } 429 430 /** 431 * Returns true if the header field has the specified name. Character 432 * case is ignored in the comparison. 433 * @param b the bytes to compare 434 * @param off the start offset of the bytes 435 * @param len the length of the bytes 436 */ 437 438 public boolean nameEquals(byte[] b, int off, int len) { 439 return name.equalsIgnoreCase(b, off, len); 440 } 441 442 /** 443 * Returns a string representation of the header field. 444 */ 445 446 public String toString() { 447 StringBuffer sb = new StringBuffer(); 448 449 sb.append(name.toString()); 450 sb.append(": "); 451 452 switch (type) { 453 case T_STR: 454 sb.append(value.toString()); 455 break; 456 case T_INT: 457 sb.append(intValue); 458 break; 459 case T_DATE: 460 sb.append(dateValue().toString()); 461 break; 462 } 463 return sb.toString(); 464 } 465 }