Quadcap Embeddable Server

com/quadcap/io/HeaderEnumeration.java

Go to the documentation of this file.
00001 package com.quadcap.io; 00002 00003 /* Copyright 1997 - 2003 Quadcap Software. All rights reserved. 00004 * 00005 * This software is distributed under the Quadcap Free Software License. 00006 * This software may be used or modified for any purpose, personal or 00007 * commercial. Open Source redistributions are permitted. Commercial 00008 * redistribution of larger works derived from, or works which bundle 00009 * this software requires a "Commercial Redistribution License"; see 00010 * http://www.quadcap.com/purchase. 00011 * 00012 * Redistributions qualify as "Open Source" under one of the following terms: 00013 * 00014 * Redistributions are made at no charge beyond the reasonable cost of 00015 * materials and delivery. 00016 * 00017 * Redistributions are accompanied by a copy of the Source Code or by an 00018 * irrevocable offer to provide a copy of the Source Code for up to three 00019 * years at the cost of materials and delivery. Such redistributions 00020 * must allow further use, modification, and redistribution of the Source 00021 * Code under substantially the same terms as this license. 00022 * 00023 * Redistributions of source code must retain the copyright notices as they 00024 * appear in each source code file, these license terms, and the 00025 * disclaimer/limitation of liability set forth as paragraph 6 below. 00026 * 00027 * Redistributions in binary form must reproduce this Copyright Notice, 00028 * these license terms, and the disclaimer/limitation of liability set 00029 * forth as paragraph 6 below, in the documentation and/or other materials 00030 * provided with the distribution. 00031 * 00032 * The Software is provided on an "AS IS" basis. No warranty is 00033 * provided that the Software is free of defects, or fit for a 00034 * particular purpose. 00035 * 00036 * Limitation of Liability. Quadcap Software shall not be liable 00037 * for any damages suffered by the Licensee or any third party resulting 00038 * from use of the Software. 00039 */ 00040 00041 import java.util.Enumeration; 00042 import java.util.Map; 00043 import java.util.NoSuchElementException; 00044 00045 import java.io.IOException; 00046 import java.io.InputStream; 00047 import java.io.PushbackInputStream; 00048 00049 import com.quadcap.util.Debug; 00050 00051 /** 00052 * Return an enumeration of the headers of an RFC-822 style message. 00053 * This implementation assumes that the headers have already been separated 00054 * from the body, so that the input stream passed to the HeaderEnumeration 00055 * constructor returns only the header portion of the message. 00056 * 00057 * <p><i>XXX It would be pretty easy to have this class detect the 00058 * CRLF, CRLF sequence that ends the headers, as well....</i> 00059 * 00060 * @author Stan Bailes 00061 */ 00062 public class HeaderEnumeration implements Enumeration { 00063 String next; 00064 PushbackInputStream is; 00065 StringBuffer sb = new StringBuffer(); 00066 00067 static final byte CR = 0x0d; 00068 static final byte LF = 0x0a; 00069 00070 public HeaderEnumeration(InputStream is) { 00071 this.is = new PushbackInputStream(is); 00072 } 00073 00074 /** 00075 * Tests if this enumeration contains more elements. 00076 * 00077 * @return <code>true</code> if this enumeration contains more elements; 00078 * <code>false</code> otherwise. 00079 */ 00080 public boolean hasMoreElements() { 00081 if (next == null) getNext(); 00082 return (next != null); 00083 } 00084 00085 /** 00086 * Returns the next element of this enumeration. 00087 * 00088 * @return the next element of this enumeration. 00089 * @exception NoSuchElementException if no more elements exist. 00090 */ 00091 public Object nextElement() { 00092 if (next == null) getNext(); 00093 if (next == null) throw new NoSuchElementException("no more elements"); 00094 Object ret = next; 00095 next = null; 00096 return ret; 00097 } 00098 00099 /** 00100 * Run the state machine to produce the next header. 00101 */ 00102 void getNext() { 00103 sb.setLength(0); 00104 00105 int c; 00106 int state = 0; 00107 00108 try { 00109 while ((c = is.read()) >= 0) { 00110 switch (state) { 00111 case 0: 00112 if (c == CR) { 00113 state = 1; 00114 } else { 00115 sb.append((char)c); 00116 } 00117 break; 00118 case 1: 00119 if (c == LF) { 00120 state = 2; 00121 } else if (c != CR) { 00122 sb.append((char)c); 00123 state = 0; 00124 } 00125 break; 00126 case 2: 00127 state = 0; 00128 if (c == ' ' || c == '\t') { 00129 sb.append(' '); 00130 } else { 00131 is.unread(c); 00132 next = sb.toString(); 00133 sb.setLength(0); 00134 return; 00135 } 00136 break; 00137 } 00138 } 00139 if (state == 2 && sb.toString().trim().length() > 0) { 00140 next = sb.toString().trim(); 00141 sb.setLength(0); 00142 } 00143 } catch (IOException e) { 00144 Debug.print(e); 00145 } 00146 } 00147 00148 /** 00149 * Helper function to build map for header (name -> value). 00150 * 00151 * @exception IOException may be thrown. 00152 */ 00153 public void getHeaderMap(Map headerMap) throws IOException { 00154 while (hasMoreElements()) { 00155 String header = (String)nextElement(); 00156 int idx = header.indexOf(':'); 00157 if (idx >= 0) { 00158 String headerName = header.substring(0, idx).trim(); 00159 String headerVal = header.substring(idx+1).trim(); 00160 headerMap.put(headerName.toLowerCase(), headerVal); 00161 } else { 00162 throw new IOException("Bad header: '" + header + "'"); 00163 } 00164 } 00165 } 00166 00167 }