comparison src/org/eclipse/jetty/http/HttpFields.java @ 831:86338c0029a9

simplify HttpFields
author Franklin Schmidt <fschmidt@gmail.com>
date Fri, 16 Sep 2016 00:26:23 -0600
parents 8e9db0bbf4f9
children fa6158f29c45
comparison
equal deleted inserted replaced
830:7c737c376bc3 831:86338c0029a9
45 import org.eclipse.jetty.io.BufferDateCache; 45 import org.eclipse.jetty.io.BufferDateCache;
46 import org.eclipse.jetty.io.BufferUtil; 46 import org.eclipse.jetty.io.BufferUtil;
47 import org.eclipse.jetty.io.ByteArrayBuffer; 47 import org.eclipse.jetty.io.ByteArrayBuffer;
48 import org.eclipse.jetty.util.LazyList; 48 import org.eclipse.jetty.util.LazyList;
49 import org.eclipse.jetty.util.QuotedStringTokenizer; 49 import org.eclipse.jetty.util.QuotedStringTokenizer;
50 import org.eclipse.jetty.util.StringMap;
51 import org.eclipse.jetty.util.StringUtil; 50 import org.eclipse.jetty.util.StringUtil;
52 import org.slf4j.Logger; 51 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory; 52 import org.slf4j.LoggerFactory;
54 53
55 /* ------------------------------------------------------------ */ 54 /* ------------------------------------------------------------ */
61 * 60 *
62 * 61 *
63 */ 62 */
64 public class HttpFields 63 public class HttpFields
65 { 64 {
66 private static final Logger LOG = LoggerFactory.getLogger(HttpFields.class); 65 private static final Logger LOG = LoggerFactory.getLogger(HttpFields.class);
67 66
68 /* ------------------------------------------------------------ */ 67 /* ------------------------------------------------------------ */
69 public static final String __COOKIE_DELIM="\"\\\n\r\t\f\b%+ ;="; 68 public static final String __COOKIE_DELIM="\"\\\n\r\t\f\b%+ ;=";
70 public static final TimeZone __GMT = TimeZone.getTimeZone("GMT"); 69 public static final TimeZone __GMT = TimeZone.getTimeZone("GMT");
71 public static final BufferDateCache __dateCache = new BufferDateCache("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US); 70 public static final BufferDateCache __dateCache = new BufferDateCache("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
72 71
73 /* -------------------------------------------------------------- */ 72 /* -------------------------------------------------------------- */
74 static 73 static
75 { 74 {
76 __GMT.setID("GMT"); 75 __GMT.setID("GMT");
77 __dateCache.setTimeZone(__GMT); 76 __dateCache.setTimeZone(__GMT);
78 } 77 }
79 78
80 /* ------------------------------------------------------------ */ 79 /* ------------------------------------------------------------ */
81 public final static String __separators = ", \t"; 80 private static final String[] DAYS =
82 81 { "Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
83 /* ------------------------------------------------------------ */ 82 private static final String[] MONTHS =
84 private static final String[] DAYS = 83 { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Jan"};
85 { "Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; 84
86 private static final String[] MONTHS = 85
87 { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Jan"}; 86 /* ------------------------------------------------------------ */
88 87 private static class DateGenerator
89 88 {
90 /* ------------------------------------------------------------ */ 89 private final StringBuilder buf = new StringBuilder(32);
91 private static class DateGenerator 90 private final GregorianCalendar gc = new GregorianCalendar(__GMT);
92 { 91
93 private final StringBuilder buf = new StringBuilder(32); 92 /**
94 private final GregorianCalendar gc = new GregorianCalendar(__GMT); 93 * Format HTTP date "EEE, dd MMM yyyy HH:mm:ss 'GMT'"
95 94 */
96 /** 95 public String formatDate(long date)
97 * Format HTTP date "EEE, dd MMM yyyy HH:mm:ss 'GMT'" 96 {
98 */ 97 buf.setLength(0);
99 public String formatDate(long date) 98 gc.setTimeInMillis(date);
100 { 99
101 buf.setLength(0); 100 int day_of_week = gc.get(Calendar.DAY_OF_WEEK);
102 gc.setTimeInMillis(date); 101 int day_of_month = gc.get(Calendar.DAY_OF_MONTH);
103 102 int month = gc.get(Calendar.MONTH);
104 int day_of_week = gc.get(Calendar.DAY_OF_WEEK); 103 int year = gc.get(Calendar.YEAR);
105 int day_of_month = gc.get(Calendar.DAY_OF_MONTH); 104 int century = year / 100;
106 int month = gc.get(Calendar.MONTH); 105 year = year % 100;
107 int year = gc.get(Calendar.YEAR); 106
108 int century = year / 100; 107 int hours = gc.get(Calendar.HOUR_OF_DAY);
109 year = year % 100; 108 int minutes = gc.get(Calendar.MINUTE);
110 109 int seconds = gc.get(Calendar.SECOND);
111 int hours = gc.get(Calendar.HOUR_OF_DAY); 110
112 int minutes = gc.get(Calendar.MINUTE); 111 buf.append(DAYS[day_of_week]);
113 int seconds = gc.get(Calendar.SECOND); 112 buf.append(',');
114 113 buf.append(' ');
115 buf.append(DAYS[day_of_week]); 114 StringUtil.append2digits(buf, day_of_month);
116 buf.append(','); 115
117 buf.append(' '); 116 buf.append(' ');
118 StringUtil.append2digits(buf, day_of_month); 117 buf.append(MONTHS[month]);
119 118 buf.append(' ');
120 buf.append(' '); 119 StringUtil.append2digits(buf, century);
121 buf.append(MONTHS[month]); 120 StringUtil.append2digits(buf, year);
122 buf.append(' '); 121
123 StringUtil.append2digits(buf, century); 122 buf.append(' ');
124 StringUtil.append2digits(buf, year); 123 StringUtil.append2digits(buf, hours);
125 124 buf.append(':');
126 buf.append(' '); 125 StringUtil.append2digits(buf, minutes);
127 StringUtil.append2digits(buf, hours); 126 buf.append(':');
128 buf.append(':'); 127 StringUtil.append2digits(buf, seconds);
129 StringUtil.append2digits(buf, minutes); 128 buf.append(" GMT");
130 buf.append(':'); 129 return buf.toString();
131 StringUtil.append2digits(buf, seconds); 130 }
132 buf.append(" GMT"); 131
133 return buf.toString(); 132 /* ------------------------------------------------------------ */
134 } 133 /**
135 134 * Format "EEE, dd-MMM-yy HH:mm:ss 'GMT'" for cookies
136 /* ------------------------------------------------------------ */ 135 */
137 /** 136 public void formatCookieDate(StringBuilder buf, long date)
138 * Format "EEE, dd-MMM-yy HH:mm:ss 'GMT'" for cookies 137 {
139 */ 138 gc.setTimeInMillis(date);
140 public void formatCookieDate(StringBuilder buf, long date) 139
141 { 140 int day_of_week = gc.get(Calendar.DAY_OF_WEEK);
142 gc.setTimeInMillis(date); 141 int day_of_month = gc.get(Calendar.DAY_OF_MONTH);
143 142 int month = gc.get(Calendar.MONTH);
144 int day_of_week = gc.get(Calendar.DAY_OF_WEEK); 143 int year = gc.get(Calendar.YEAR);
145 int day_of_month = gc.get(Calendar.DAY_OF_MONTH); 144 year = year % 10000;
146 int month = gc.get(Calendar.MONTH); 145
147 int year = gc.get(Calendar.YEAR); 146 int epoch = (int) ((date / 1000) % (60 * 60 * 24));
148 year = year % 10000; 147 int seconds = epoch % 60;
149 148 epoch = epoch / 60;
150 int epoch = (int) ((date / 1000) % (60 * 60 * 24)); 149 int minutes = epoch % 60;
151 int seconds = epoch % 60; 150 int hours = epoch / 60;
152 epoch = epoch / 60; 151
153 int minutes = epoch % 60; 152 buf.append(DAYS[day_of_week]);
154 int hours = epoch / 60; 153 buf.append(',');
155 154 buf.append(' ');
156 buf.append(DAYS[day_of_week]); 155 StringUtil.append2digits(buf, day_of_month);
157 buf.append(','); 156
158 buf.append(' '); 157 buf.append('-');
159 StringUtil.append2digits(buf, day_of_month); 158 buf.append(MONTHS[month]);
160 159 buf.append('-');
161 buf.append('-'); 160 StringUtil.append2digits(buf, year/100);
162 buf.append(MONTHS[month]); 161 StringUtil.append2digits(buf, year%100);
163 buf.append('-'); 162
164 StringUtil.append2digits(buf, year/100); 163 buf.append(' ');
165 StringUtil.append2digits(buf, year%100); 164 StringUtil.append2digits(buf, hours);
166 165 buf.append(':');
167 buf.append(' '); 166 StringUtil.append2digits(buf, minutes);
168 StringUtil.append2digits(buf, hours); 167 buf.append(':');
169 buf.append(':'); 168 StringUtil.append2digits(buf, seconds);
170 StringUtil.append2digits(buf, minutes); 169 buf.append(" GMT");
171 buf.append(':'); 170 }
172 StringUtil.append2digits(buf, seconds); 171 }
173 buf.append(" GMT"); 172
174 } 173 /* ------------------------------------------------------------ */
175 } 174 private static final ThreadLocal<DateGenerator> __dateGenerator =new ThreadLocal<DateGenerator>()
176 175 {
177 /* ------------------------------------------------------------ */ 176 @Override
178 private static final ThreadLocal<DateGenerator> __dateGenerator =new ThreadLocal<DateGenerator>() 177 protected DateGenerator initialValue()
179 { 178 {
180 @Override 179 return new DateGenerator();
181 protected DateGenerator initialValue() 180 }
182 { 181 };
183 return new DateGenerator(); 182
184 } 183 /* ------------------------------------------------------------ */
185 }; 184 /**
186 185 * Format HTTP date "EEE, dd MMM yyyy HH:mm:ss 'GMT'"
187 /* ------------------------------------------------------------ */ 186 */
188 /** 187 public static String formatDate(long date)
189 * Format HTTP date "EEE, dd MMM yyyy HH:mm:ss 'GMT'" 188 {
190 */ 189 return __dateGenerator.get().formatDate(date);
191 public static String formatDate(long date) 190 }
192 { 191
193 return __dateGenerator.get().formatDate(date); 192 /* ------------------------------------------------------------ */
194 } 193 /**
195 194 * Format "EEE, dd-MMM-yyyy HH:mm:ss 'GMT'" for cookies
196 /* ------------------------------------------------------------ */ 195 */
197 /** 196 public static void formatCookieDate(StringBuilder buf, long date)
198 * Format "EEE, dd-MMM-yyyy HH:mm:ss 'GMT'" for cookies 197 {
199 */ 198 __dateGenerator.get().formatCookieDate(buf,date);
200 public static void formatCookieDate(StringBuilder buf, long date) 199 }
201 { 200
202 __dateGenerator.get().formatCookieDate(buf,date); 201 /* ------------------------------------------------------------ */
203 } 202 /**
204 203 * Format "EEE, dd-MMM-yyyy HH:mm:ss 'GMT'" for cookies
205 /* ------------------------------------------------------------ */ 204 */
206 /** 205 public static String formatCookieDate(long date)
207 * Format "EEE, dd-MMM-yyyy HH:mm:ss 'GMT'" for cookies 206 {
208 */ 207 StringBuilder buf = new StringBuilder(28);
209 public static String formatCookieDate(long date) 208 formatCookieDate(buf, date);
210 { 209 return buf.toString();
211 StringBuilder buf = new StringBuilder(28); 210 }
212 formatCookieDate(buf, date); 211
213 return buf.toString(); 212 /* ------------------------------------------------------------ */
214 } 213 private final static String __dateReceiveFmt[] =
215 214 {
216 /* ------------------------------------------------------------ */ 215 "EEE, dd MMM yyyy HH:mm:ss zzz",
217 private final static String __dateReceiveFmt[] = 216 "EEE, dd-MMM-yy HH:mm:ss",
218 { 217 "EEE MMM dd HH:mm:ss yyyy",
219 "EEE, dd MMM yyyy HH:mm:ss zzz", 218
220 "EEE, dd-MMM-yy HH:mm:ss", 219 "EEE, dd MMM yyyy HH:mm:ss", "EEE dd MMM yyyy HH:mm:ss zzz",
221 "EEE MMM dd HH:mm:ss yyyy", 220 "EEE dd MMM yyyy HH:mm:ss", "EEE MMM dd yyyy HH:mm:ss zzz", "EEE MMM dd yyyy HH:mm:ss",
222 221 "EEE MMM-dd-yyyy HH:mm:ss zzz", "EEE MMM-dd-yyyy HH:mm:ss", "dd MMM yyyy HH:mm:ss zzz",
223 "EEE, dd MMM yyyy HH:mm:ss", "EEE dd MMM yyyy HH:mm:ss zzz", 222 "dd MMM yyyy HH:mm:ss", "dd-MMM-yy HH:mm:ss zzz", "dd-MMM-yy HH:mm:ss", "MMM dd HH:mm:ss yyyy zzz",
224 "EEE dd MMM yyyy HH:mm:ss", "EEE MMM dd yyyy HH:mm:ss zzz", "EEE MMM dd yyyy HH:mm:ss", 223 "MMM dd HH:mm:ss yyyy", "EEE MMM dd HH:mm:ss yyyy zzz",
225 "EEE MMM-dd-yyyy HH:mm:ss zzz", "EEE MMM-dd-yyyy HH:mm:ss", "dd MMM yyyy HH:mm:ss zzz", 224 "EEE, MMM dd HH:mm:ss yyyy zzz", "EEE, MMM dd HH:mm:ss yyyy", "EEE, dd-MMM-yy HH:mm:ss zzz",
226 "dd MMM yyyy HH:mm:ss", "dd-MMM-yy HH:mm:ss zzz", "dd-MMM-yy HH:mm:ss", "MMM dd HH:mm:ss yyyy zzz", 225 "EEE dd-MMM-yy HH:mm:ss zzz", "EEE dd-MMM-yy HH:mm:ss",
227 "MMM dd HH:mm:ss yyyy", "EEE MMM dd HH:mm:ss yyyy zzz", 226 };
228 "EEE, MMM dd HH:mm:ss yyyy zzz", "EEE, MMM dd HH:mm:ss yyyy", "EEE, dd-MMM-yy HH:mm:ss zzz", 227
229 "EEE dd-MMM-yy HH:mm:ss zzz", "EEE dd-MMM-yy HH:mm:ss", 228 /* ------------------------------------------------------------ */
230 }; 229 private static class DateParser
231 230 {
232 /* ------------------------------------------------------------ */ 231 final SimpleDateFormat _dateReceive[]= new SimpleDateFormat[__dateReceiveFmt.length];
233 private static class DateParser
234 {
235 final SimpleDateFormat _dateReceive[]= new SimpleDateFormat[__dateReceiveFmt.length];
236 232
237 long parse(final String dateVal) 233 long parse(final String dateVal)
238 { 234 {
239 for (int i = 0; i < _dateReceive.length; i++) 235 for (int i = 0; i < _dateReceive.length; i++)
240 { 236 {
241 if (_dateReceive[i] == null) 237 if (_dateReceive[i] == null)
242 { 238 {
243 _dateReceive[i] = new SimpleDateFormat(__dateReceiveFmt[i], Locale.US); 239 _dateReceive[i] = new SimpleDateFormat(__dateReceiveFmt[i], Locale.US);
244 _dateReceive[i].setTimeZone(__GMT); 240 _dateReceive[i].setTimeZone(__GMT);
245 } 241 }
246 242
247 try 243 try
248 { 244 {
249 Date date = (Date) _dateReceive[i].parseObject(dateVal); 245 Date date = (Date) _dateReceive[i].parseObject(dateVal);
250 return date.getTime(); 246 return date.getTime();
251 } 247 }
252 catch (java.lang.Exception e) 248 catch (java.lang.Exception e)
253 { 249 {
254 // LOG.ignore(e); 250 // LOG.ignore(e);
255 } 251 }
256 } 252 }
257 253
258 if (dateVal.endsWith(" GMT")) 254 if (dateVal.endsWith(" GMT"))
259 { 255 {
260 final String val = dateVal.substring(0, dateVal.length() - 4); 256 final String val = dateVal.substring(0, dateVal.length() - 4);
261 257
262 for (int i = 0; i < _dateReceive.length; i++) 258 for (int i = 0; i < _dateReceive.length; i++)
263 { 259 {
264 try 260 try
265 { 261 {
266 Date date = (Date) _dateReceive[i].parseObject(val); 262 Date date = (Date) _dateReceive[i].parseObject(val);
267 return date.getTime(); 263 return date.getTime();
268 } 264 }
269 catch (java.lang.Exception e) 265 catch (java.lang.Exception e)
270 { 266 {
271 // LOG.ignore(e); 267 // LOG.ignore(e);
272 } 268 }
273 } 269 }
274 } 270 }
275 return -1; 271 return -1;
276 } 272 }
277 } 273 }
278 274
279 /* ------------------------------------------------------------ */ 275 /* ------------------------------------------------------------ */
280 public static long parseDate(String date) 276 public static long parseDate(String date)
281 { 277 {
282 return __dateParser.get().parse(date); 278 return __dateParser.get().parse(date);
283 } 279 }
284 280
285 /* ------------------------------------------------------------ */ 281 /* ------------------------------------------------------------ */
286 private static final ThreadLocal<DateParser> __dateParser =new ThreadLocal<DateParser>() 282 private static final ThreadLocal<DateParser> __dateParser =new ThreadLocal<DateParser>()
287 { 283 {
288 @Override 284 @Override
289 protected DateParser initialValue() 285 protected DateParser initialValue()
290 { 286 {
291 return new DateParser(); 287 return new DateParser();
292 } 288 }
293 }; 289 };
294 290
295 /* -------------------------------------------------------------- */ 291 /* -------------------------------------------------------------- */
296 public final static String __01Jan1970=formatDate(0); 292 public final static String __01Jan1970=formatDate(0);
297 public final static Buffer __01Jan1970_BUFFER=new ByteArrayBuffer(__01Jan1970); 293 public final static Buffer __01Jan1970_BUFFER=new ByteArrayBuffer(__01Jan1970);
298 public final static String __01Jan1970_COOKIE = formatCookieDate(0).trim(); 294 public final static String __01Jan1970_COOKIE = formatCookieDate(0).trim();
299 295
300 /* -------------------------------------------------------------- */ 296 /* -------------------------------------------------------------- */
301 private final ArrayList<Field> _fields = new ArrayList<Field>(20); 297 private final ArrayList<Field> _fields = new ArrayList<Field>(20);
302 private final HashMap<Buffer,Field> _names = new HashMap<Buffer,Field>(32); 298 private final HashMap<Buffer,Field> _names = new HashMap<Buffer,Field>(32);
303 299
304 /* ------------------------------------------------------------ */ 300 /* ------------------------------------------------------------ */
305 /** 301 /**
306 * Constructor. 302 * Constructor.
307 */ 303 */
308 public HttpFields() 304 public HttpFields()
309 { 305 {
310 } 306 }
311 307
312 // TODO externalize this cache so it can be configurable 308 // TODO externalize this cache so it can be configurable
313 private static ConcurrentMap<String, Buffer> __cache = new ConcurrentHashMap<String, Buffer>(); 309 private static ConcurrentMap<String, Buffer> __cache = new ConcurrentHashMap<String, Buffer>();
314 private static int __cacheSize = Integer.getInteger("org.eclipse.jetty.http.HttpFields.CACHE",2000); 310 private static int __cacheSize = Integer.getInteger("org.eclipse.jetty.http.HttpFields.CACHE",2000);
315 311
316 /* -------------------------------------------------------------- */ 312 /* -------------------------------------------------------------- */
317 private Buffer convertValue(String value) 313 private Buffer convertValue(String value)
318 { 314 {
319 Buffer buffer = __cache.get(value); 315 Buffer buffer = __cache.get(value);
320 if (buffer!=null) 316 if (buffer!=null)
321 return buffer; 317 return buffer;
322 318
323 try 319 try
324 { 320 {
325 buffer = new ByteArrayBuffer(value,StringUtil.__ISO_8859_1); 321 buffer = new ByteArrayBuffer(value,StringUtil.__ISO_8859_1);
326 322
327 if (__cacheSize>0) 323 if (__cacheSize>0)
328 { 324 {
329 if (__cache.size()>__cacheSize) 325 if (__cache.size()>__cacheSize)
330 __cache.clear(); 326 __cache.clear();
331 Buffer b=__cache.putIfAbsent(value,buffer); 327 Buffer b=__cache.putIfAbsent(value,buffer);
332 if (b!=null) 328 if (b!=null)
333 buffer=b; 329 buffer=b;
334 } 330 }
335 331
336 return buffer; 332 return buffer;
337 } 333 }
338 catch (UnsupportedEncodingException e) 334 catch (UnsupportedEncodingException e)
339 { 335 {
340 throw new RuntimeException(e); 336 throw new RuntimeException(e);
341 } 337 }
342 } 338 }
343 339
344 /* -------------------------------------------------------------- */ 340 /* -------------------------------------------------------------- */
345 /** 341 /**
346 * Get Collection of header names. 342 * Get Collection of header names.
347 */ 343 */
348 public Collection<String> getFieldNamesCollection() 344 public Collection<String> getFieldNamesCollection()
349 { 345 {
350 final List<String> list = new ArrayList<String>(_fields.size()); 346 final List<String> list = new ArrayList<String>(_fields.size());
351 347
352 for (Field f : _fields) 348 for (Field f : _fields)
353 { 349 {
354 if (f!=null) 350 if (f!=null)
355 list.add(BufferUtil.to8859_1_String(f._name)); 351 list.add(BufferUtil.to8859_1_String(f._name));
356 } 352 }
357 return list; 353 return list;
358 } 354 }
359 355
360 /* -------------------------------------------------------------- */ 356 /* -------------------------------------------------------------- */
361 /** 357 /**
362 * Get enumeration of header _names. Returns an enumeration of strings representing the header 358 * Get enumeration of header _names. Returns an enumeration of strings representing the header
363 * _names for this request. 359 * _names for this request.
364 */ 360 */
365 public Enumeration<String> getFieldNames() 361 public Enumeration<String> getFieldNames()
366 { 362 {
367 final Enumeration<?> buffers = Collections.enumeration(_names.keySet()); 363 final Enumeration<?> buffers = Collections.enumeration(_names.keySet());
368 return new Enumeration<String>() 364 return new Enumeration<String>()
369 { 365 {
370 public String nextElement() 366 public String nextElement()
371 { 367 {
372 return buffers.nextElement().toString(); 368 return buffers.nextElement().toString();
373 } 369 }
374 370
375 public boolean hasMoreElements() 371 public boolean hasMoreElements()
376 { 372 {
377 return buffers.hasMoreElements(); 373 return buffers.hasMoreElements();
378 } 374 }
379 }; 375 };
380 } 376 }
381 377
382 /* ------------------------------------------------------------ */ 378 /* ------------------------------------------------------------ */
383 public int size() 379 public int size()
384 { 380 {
385 return _fields.size(); 381 return _fields.size();
386 } 382 }
387 383
388 /* ------------------------------------------------------------ */ 384 /* ------------------------------------------------------------ */
389 /** 385 /**
390 * Get a Field by index. 386 * Get a Field by index.
391 * @return A Field value or null if the Field value has not been set 387 * @return A Field value or null if the Field value has not been set
392 * 388 *
393 */ 389 */
394 public Field getField(int i) 390 public Field getField(int i)
395 { 391 {
396 return _fields.get(i); 392 return _fields.get(i);
397 } 393 }
398 394
399 /* ------------------------------------------------------------ */ 395 /* ------------------------------------------------------------ */
400 private Field getField(String name) 396 private Field getField(String name)
401 { 397 {
402 return _names.get(HttpHeaders.CACHE.lookup(name)); 398 return _names.get(HttpHeaders.CACHE.lookup(name));
403 } 399 }
404 400
405 /* ------------------------------------------------------------ */ 401 /* ------------------------------------------------------------ */
406 private Field getField(Buffer name) 402 private Field getField(Buffer name)
407 { 403 {
408 return _names.get(HttpHeaders.CACHE.lookup(name)); 404 return _names.get(HttpHeaders.CACHE.lookup(name));
409 } 405 }
410 406
411 /* ------------------------------------------------------------ */ 407 /* ------------------------------------------------------------ */
412 public boolean containsKey(Buffer name) 408 public boolean containsKey(Buffer name)
413 { 409 {
414 return _names.containsKey(HttpHeaders.CACHE.lookup(name)); 410 return _names.containsKey(HttpHeaders.CACHE.lookup(name));
415 } 411 }
416 412
417 /* ------------------------------------------------------------ */ 413 /* ------------------------------------------------------------ */
418 public boolean containsKey(String name) 414 public boolean containsKey(String name)
419 { 415 {
420 return _names.containsKey(HttpHeaders.CACHE.lookup(name)); 416 return _names.containsKey(HttpHeaders.CACHE.lookup(name));
421 } 417 }
422 418
423 /* -------------------------------------------------------------- */ 419 /* -------------------------------------------------------------- */
424 /** 420 /**
425 * @return the value of a field, or null if not found. For multiple fields of the same name, 421 * @return the value of a field, or null if not found. For multiple fields of the same name,
426 * only the first is returned. 422 * only the first is returned.
427 * @param name the case-insensitive field name 423 * @param name the case-insensitive field name
428 */ 424 */
429 public String getStringField(String name) 425 public String getStringField(String name)
430 { 426 {
431 Field field = getField(name); 427 Field field = getField(name);
432 return field==null?null:field.getValue(); 428 return field==null?null:field.getValue();
433 } 429 }
434 430
435 /* -------------------------------------------------------------- */ 431 /* -------------------------------------------------------------- */
436 /** 432 /**
437 * @return the value of a field, or null if not found. For multiple fields of the same name, 433 * @return the value of a field, or null if not found. For multiple fields of the same name,
438 * only the first is returned. 434 * only the first is returned.
439 * @param name the case-insensitive field name 435 * @param name the case-insensitive field name
440 */ 436 */
441 public String getStringField(Buffer name) 437 public String getStringField(Buffer name)
442 { 438 {
443 Field field = getField(name); 439 Field field = getField(name);
444 return field==null?null:field.getValue(); 440 return field==null?null:field.getValue();
445 } 441 }
446 442
447 /* -------------------------------------------------------------- */ 443 /* -------------------------------------------------------------- */
448 /** 444 /**
449 * @return the value of a field, or null if not found. For multiple fields of the same name, 445 * @return the value of a field, or null if not found. For multiple fields of the same name,
450 * only the first is returned. 446 * only the first is returned.
451 * @param name the case-insensitive field name 447 * @param name the case-insensitive field name
452 */ 448 */
453 public Buffer get(Buffer name) 449 public Buffer get(Buffer name)
454 { 450 {
455 Field field = getField(name); 451 Field field = getField(name);
456 return field==null?null:field._value; 452 return field==null?null:field._value;
457 } 453 }
458 454
459 455
460 /* -------------------------------------------------------------- */ 456 /* -------------------------------------------------------------- */
461 /** 457 /**
462 * Get multi headers 458 * Get multi headers
463 * 459 *
464 * @return Enumeration of the values, or null if no such header. 460 * @return Enumeration of the values, or null if no such header.
465 * @param name the case-insensitive field name 461 * @param name the case-insensitive field name
466 */ 462 */
467 public Collection<String> getValuesCollection(String name) 463 public Collection<String> getValuesCollection(String name)
468 { 464 {
469 Field field = getField(name); 465 Field field = getField(name);
470 if (field==null) 466 if (field==null)
471 return null; 467 return null;
472 468
473 final List<String> list = new ArrayList<String>(); 469 final List<String> list = new ArrayList<String>();
474 470
475 while(field!=null) 471 while(field!=null)
476 { 472 {
477 list.add(field.getValue()); 473 list.add(field.getValue());
478 field=field._next; 474 field=field._next;
479 } 475 }
480 return list; 476 return list;
481 } 477 }
482 478
483 /* -------------------------------------------------------------- */ 479 /* -------------------------------------------------------------- */
484 /** 480 /**
485 * Get multi headers 481 * Get multi headers
486 * 482 *
487 * @return Enumeration of the values 483 * @return Enumeration of the values
488 * @param name the case-insensitive field name 484 * @param name the case-insensitive field name
489 */ 485 */
490 public Enumeration<String> getValues(String name) 486 public Enumeration<String> getValues(String name)
491 { 487 {
492 final Field field = getField(name); 488 final Field field = getField(name);
493 if (field == null) 489 if (field == null)
494 { 490 {
495 List<String> empty=Collections.emptyList(); 491 List<String> empty=Collections.emptyList();
496 return Collections.enumeration(empty); 492 return Collections.enumeration(empty);
497 } 493 }
498 494
499 return new Enumeration<String>() 495 return new Enumeration<String>()
500 { 496 {
501 Field f = field; 497 Field f = field;
502 498
503 public boolean hasMoreElements() 499 public boolean hasMoreElements()
504 { 500 {
505 return f != null; 501 return f != null;
506 } 502 }
507 503
508 public String nextElement() throws NoSuchElementException 504 public String nextElement() throws NoSuchElementException
509 { 505 {
510 if (f == null) throw new NoSuchElementException(); 506 if (f == null) throw new NoSuchElementException();
511 Field n = f; 507 Field n = f;
512 f = f._next; 508 f = f._next;
513 return n.getValue(); 509 return n.getValue();
514 } 510 }
515 }; 511 };
516 } 512 }
517 513
518 /* -------------------------------------------------------------- */ 514 /* -------------------------------------------------------------- */
519 /** 515 /**
520 * Get multi headers 516 * Get multi headers
521 * 517 *
522 * @return Enumeration of the value Strings 518 * @return Enumeration of the value Strings
523 * @param name the case-insensitive field name 519 * @param name the case-insensitive field name
524 */ 520 */
525 public Enumeration<String> getValues(Buffer name) 521 public Enumeration<String> getValues(Buffer name)
526 { 522 {
527 final Field field = getField(name); 523 final Field field = getField(name);
528 if (field == null) 524 if (field == null)
529 { 525 {
530 List<String> empty=Collections.emptyList(); 526 List<String> empty=Collections.emptyList();
531 return Collections.enumeration(empty); 527 return Collections.enumeration(empty);
532 } 528 }
533 529
534 return new Enumeration<String>() 530 return new Enumeration<String>()
535 { 531 {
536 Field f = field; 532 Field f = field;
537 533
538 public boolean hasMoreElements() 534 public boolean hasMoreElements()
539 { 535 {
540 return f != null; 536 return f != null;
541 } 537 }
542 538
543 public String nextElement() throws NoSuchElementException 539 public String nextElement() throws NoSuchElementException
544 { 540 {
545 if (f == null) throw new NoSuchElementException(); 541 if (f == null) throw new NoSuchElementException();
546 Field n = f; 542 Field n = f;
547 f = f._next; 543 f = f._next;
548 return n.getValue(); 544 return n.getValue();
549 } 545 }
550 }; 546 };
551 } 547 }
552 548
553 /* -------------------------------------------------------------- */ 549 /* -------------------------------------------------------------- */
554 /** 550 /**
555 * Get multi field values with separator. The multiple values can be represented as separate 551 * Get multi field values with separator. The multiple values can be represented as separate
556 * headers of the same name, or by a single header using the separator(s), or a combination of 552 * headers of the same name, or by a single header using the separator(s), or a combination of
557 * both. Separators may be quoted. 553 * both. Separators may be quoted.
558 * 554 *
559 * @param name the case-insensitive field name 555 * @param name the case-insensitive field name
560 * @param separators String of separators. 556 * @param separators String of separators.
561 * @return Enumeration of the values, or null if no such header. 557 * @return Enumeration of the values, or null if no such header.
562 */ 558 */
563 public Enumeration<String> getValues(String name, final String separators) 559 public Enumeration<String> getValues(String name, final String separators)
564 { 560 {
565 final Enumeration<String> e = getValues(name); 561 final Enumeration<String> e = getValues(name);
566 if (e == null) 562 if (e == null)
567 return null; 563 return null;
568 return new Enumeration<String>() 564 return new Enumeration<String>()
569 { 565 {
570 QuotedStringTokenizer tok = null; 566 QuotedStringTokenizer tok = null;
571 567
572 public boolean hasMoreElements() 568 public boolean hasMoreElements()
573 { 569 {
574 if (tok != null && tok.hasMoreElements()) return true; 570 if (tok != null && tok.hasMoreElements()) return true;
575 while (e.hasMoreElements()) 571 while (e.hasMoreElements())
576 { 572 {
577 String value = e.nextElement(); 573 String value = e.nextElement();
578 tok = new QuotedStringTokenizer(value, separators, false, false); 574 tok = new QuotedStringTokenizer(value, separators, false, false);
579 if (tok.hasMoreElements()) return true; 575 if (tok.hasMoreElements()) return true;
580 } 576 }
581 tok = null; 577 tok = null;
582 return false; 578 return false;
583 } 579 }
584 580
585 public String nextElement() throws NoSuchElementException 581 public String nextElement() throws NoSuchElementException
586 { 582 {
587 if (!hasMoreElements()) throw new NoSuchElementException(); 583 if (!hasMoreElements()) throw new NoSuchElementException();
588 String next = (String) tok.nextElement(); 584 String next = (String) tok.nextElement();
589 if (next != null) next = next.trim(); 585 if (next != null) next = next.trim();
590 return next; 586 return next;
591 } 587 }
592 }; 588 };
593 } 589 }
594 590
595 591
596 /* -------------------------------------------------------------- */ 592 /* -------------------------------------------------------------- */
597 /** 593 /**
598 * Set a field. 594 * Set a field.
599 * 595 *
600 * @param name the name of the field 596 * @param name the name of the field
601 * @param value the value of the field. If null the field is cleared. 597 * @param value the value of the field. If null the field is cleared.
602 */ 598 */
603 public void put(String name, String value) 599 public void put(String name, String value)
604 { 600 {
605 if (value==null) 601 if (value==null)
606 remove(name); 602 remove(name);
607 else 603 else
608 { 604 {
609 Buffer n = HttpHeaders.CACHE.lookup(name); 605 Buffer n = HttpHeaders.CACHE.lookup(name);
610 Buffer v = convertValue(value); 606 Buffer v = convertValue(value);
611 put(n, v); 607 put(n, v);
612 } 608 }
613 } 609 }
614 610
615 /* -------------------------------------------------------------- */ 611 /* -------------------------------------------------------------- */
616 /** 612 /**
617 * Set a field. 613 * Set a field.
618 * 614 *
619 * @param name the name of the field 615 * @param name the name of the field
620 * @param value the value of the field. If null the field is cleared. 616 * @param value the value of the field. If null the field is cleared.
621 */ 617 */
622 public void put(Buffer name, String value) 618 public void put(Buffer name, String value)
623 { 619 {
624 Buffer n = HttpHeaders.CACHE.lookup(name); 620 Buffer n = HttpHeaders.CACHE.lookup(name);
625 Buffer v = convertValue(value); 621 Buffer v = convertValue(value);
626 put(n, v); 622 put(n, v);
627 } 623 }
628 624
629 /* -------------------------------------------------------------- */ 625 /* -------------------------------------------------------------- */
630 /** 626 /**
631 * Set a field. 627 * Set a field.
632 * 628 *
633 * @param name the name of the field 629 * @param name the name of the field
634 * @param value the value of the field. If null the field is cleared. 630 * @param value the value of the field. If null the field is cleared.
635 */ 631 */
636 public void put(Buffer name, Buffer value) 632 public void put(Buffer name, Buffer value)
637 { 633 {
638 remove(name); 634 remove(name);
639 if (value == null) 635 if (value == null)
640 return; 636 return;
641 637
642 if (!(name instanceof BufferCache.CachedBuffer)) 638 if (!(name instanceof BufferCache.CachedBuffer))
643 name = HttpHeaders.CACHE.lookup(name); 639 name = HttpHeaders.CACHE.lookup(name);
644 if (!(value instanceof CachedBuffer)) 640 if (!(value instanceof CachedBuffer))
645 value= HttpHeaderValues.CACHE.lookup(value).asImmutableBuffer(); 641 value= HttpHeaderValues.CACHE.lookup(value).asImmutableBuffer();
646 642
647 // new value; 643 // new value;
648 Field field = new Field(name, value); 644 Field field = new Field(name, value);
649 _fields.add(field); 645 _fields.add(field);
650 _names.put(name, field); 646 _names.put(name, field);
651 } 647 }
652 648
653 /* -------------------------------------------------------------- */ 649 /* -------------------------------------------------------------- */
654 /** 650 /**
655 * Set a field. 651 * Set a field.
656 * 652 *
657 * @param name the name of the field 653 * @param name the name of the field
658 * @param list the List value of the field. If null the field is cleared. 654 * @param list the List value of the field. If null the field is cleared.
659 */ 655 */
660 public void put(String name, List<?> list) 656 public void put(String name, List<?> list)
661 { 657 {
662 if (list == null || list.size() == 0) 658 if (list == null || list.size() == 0)
663 { 659 {
664 remove(name); 660 remove(name);
665 return; 661 return;
666 } 662 }
667 Buffer n = HttpHeaders.CACHE.lookup(name); 663 Buffer n = HttpHeaders.CACHE.lookup(name);
668 664
669 Object v = list.get(0); 665 Object v = list.get(0);
670 if (v != null) 666 if (v != null)
671 put(n, HttpHeaderValues.CACHE.lookup(v.toString())); 667 put(n, HttpHeaderValues.CACHE.lookup(v.toString()));
672 else 668 else
673 remove(n); 669 remove(n);
674 670
675 if (list.size() > 1) 671 if (list.size() > 1)
676 { 672 {
677 java.util.Iterator<?> iter = list.iterator(); 673 java.util.Iterator<?> iter = list.iterator();
678 iter.next(); 674 iter.next();
679 while (iter.hasNext()) 675 while (iter.hasNext())
680 { 676 {
681 v = iter.next(); 677 v = iter.next();
682 if (v != null) put(n, HttpHeaderValues.CACHE.lookup(v.toString())); 678 if (v != null) put(n, HttpHeaderValues.CACHE.lookup(v.toString()));
683 } 679 }
684 } 680 }
685 } 681 }
686 682
687 /* -------------------------------------------------------------- */ 683 /* -------------------------------------------------------------- */
688 /** 684 /**
689 * Add to or set a field. If the field is allowed to have multiple values, add will add multiple 685 * Add to or set a field. If the field is allowed to have multiple values, add will add multiple
690 * headers of the same name. 686 * headers of the same name.
691 * 687 *
692 * @param name the name of the field 688 * @param name the name of the field
693 * @param value the value of the field. 689 * @param value the value of the field.
694 * @exception IllegalArgumentException If the name is a single valued field and already has a 690 * @exception IllegalArgumentException If the name is a single valued field and already has a
695 * value. 691 * value.
696 */ 692 */
697 public void add(String name, String value) throws IllegalArgumentException 693 public void add(String name, String value) throws IllegalArgumentException
698 { 694 {
699 if (value==null) 695 if (value==null)
700 return; 696 return;
701 Buffer n = HttpHeaders.CACHE.lookup(name); 697 Buffer n = HttpHeaders.CACHE.lookup(name);
702 Buffer v = convertValue(value); 698 Buffer v = convertValue(value);
703 add(n, v); 699 add(n, v);
704 } 700 }
705 701
706 /* -------------------------------------------------------------- */ 702 /* -------------------------------------------------------------- */
707 /** 703 /**
708 * Add to or set a field. If the field is allowed to have multiple values, add will add multiple 704 * Add to or set a field. If the field is allowed to have multiple values, add will add multiple
709 * headers of the same name. 705 * headers of the same name.
710 * 706 *
711 * @param name the name of the field 707 * @param name the name of the field
712 * @param value the value of the field. 708 * @param value the value of the field.
713 * @exception IllegalArgumentException If the name is a single valued field and already has a 709 * @exception IllegalArgumentException If the name is a single valued field and already has a
714 * value. 710 * value.
715 */ 711 */
716 public void add(Buffer name, Buffer value) throws IllegalArgumentException 712 public void add(Buffer name, Buffer value) throws IllegalArgumentException
717 { 713 {
718 if (value == null) throw new IllegalArgumentException("null value"); 714 if (value == null) throw new IllegalArgumentException("null value");
719 715
720 if (!(name instanceof CachedBuffer)) 716 if (!(name instanceof CachedBuffer))
721 name = HttpHeaders.CACHE.lookup(name); 717 name = HttpHeaders.CACHE.lookup(name);
722 name=name.asImmutableBuffer(); 718 name=name.asImmutableBuffer();
723 719
724 if (!(value instanceof CachedBuffer) && HttpHeaderValues.hasKnownValues(HttpHeaders.CACHE.getOrdinal(name))) 720 if (!(value instanceof CachedBuffer) && HttpHeaderValues.hasKnownValues(HttpHeaders.CACHE.getOrdinal(name)))
725 value= HttpHeaderValues.CACHE.lookup(value); 721 value= HttpHeaderValues.CACHE.lookup(value);
726 value=value.asImmutableBuffer(); 722 value=value.asImmutableBuffer();
727 723
728 Field field = _names.get(name); 724 Field field = _names.get(name);
729 Field last = null; 725 Field last = null;
730 while (field != null) 726 while (field != null)
731 { 727 {
732 last = field; 728 last = field;
733 field = field._next; 729 field = field._next;
734 } 730 }
735 731
736 // create the field 732 // create the field
737 field = new Field(name, value); 733 field = new Field(name, value);
738 _fields.add(field); 734 _fields.add(field);
739 735
740 // look for chain to add too 736 // look for chain to add too
741 if (last != null) 737 if (last != null)
742 last._next = field; 738 last._next = field;
743 else 739 else
744 _names.put(name, field); 740 _names.put(name, field);
745 } 741 }
746 742
747 /* ------------------------------------------------------------ */ 743 /* ------------------------------------------------------------ */
748 /** 744 /**
749 * Remove a field. 745 * Remove a field.
750 * 746 *
751 * @param name 747 * @param name
752 */ 748 */
753 public void remove(String name) 749 public void remove(String name)
754 { 750 {
755 remove(HttpHeaders.CACHE.lookup(name)); 751 remove(HttpHeaders.CACHE.lookup(name));
756 } 752 }
757 753
758 /* ------------------------------------------------------------ */ 754 /* ------------------------------------------------------------ */
759 /** 755 /**
760 * Remove a field. 756 * Remove a field.
761 * 757 *
762 * @param name 758 * @param name
763 */ 759 */
764 public void remove(Buffer name) 760 public void remove(Buffer name)
765 { 761 {
766 if (!(name instanceof BufferCache.CachedBuffer)) 762 if (!(name instanceof BufferCache.CachedBuffer))
767 name = HttpHeaders.CACHE.lookup(name); 763 name = HttpHeaders.CACHE.lookup(name);
768 Field field = _names.remove(name); 764 Field field = _names.remove(name);
769 while (field != null) 765 while (field != null)
770 { 766 {
771 _fields.remove(field); 767 _fields.remove(field);
772 field = field._next; 768 field = field._next;
773 } 769 }
774 } 770 }
775 771
776 /* -------------------------------------------------------------- */ 772 /* -------------------------------------------------------------- */
777 /** 773 /**
778 * Get a header as an long value. Returns the value of an integer field or -1 if not found. The 774 * Get a header as an long value. Returns the value of an integer field or -1 if not found. The
779 * case of the field name is ignored. 775 * case of the field name is ignored.
780 * 776 *
781 * @param name the case-insensitive field name 777 * @param name the case-insensitive field name
782 * @exception NumberFormatException If bad long found 778 * @exception NumberFormatException If bad long found
783 */ 779 */
784 public long getLongField(String name) throws NumberFormatException 780 public long getLongField(String name) throws NumberFormatException
785 { 781 {
786 Field field = getField(name); 782 Field field = getField(name);
787 return field==null?-1L:field.getLongValue(); 783 return field==null?-1L:field.getLongValue();
788 } 784 }
789 785
790 /* -------------------------------------------------------------- */ 786 /* -------------------------------------------------------------- */
791 /** 787 /**
792 * Get a header as an long value. Returns the value of an integer field or -1 if not found. The 788 * Get a header as an long value. Returns the value of an integer field or -1 if not found. The
793 * case of the field name is ignored. 789 * case of the field name is ignored.
794 * 790 *
795 * @param name the case-insensitive field name 791 * @param name the case-insensitive field name
796 * @exception NumberFormatException If bad long found 792 * @exception NumberFormatException If bad long found
797 */ 793 */
798 public long getLongField(Buffer name) throws NumberFormatException 794 public long getLongField(Buffer name) throws NumberFormatException
799 { 795 {
800 Field field = getField(name); 796 Field field = getField(name);
801 return field==null?-1L:field.getLongValue(); 797 return field==null?-1L:field.getLongValue();
802 } 798 }
803 799
804 /* -------------------------------------------------------------- */ 800 /* -------------------------------------------------------------- */
805 /** 801 /**
806 * Get a header as a date value. Returns the value of a date field, or -1 if not found. The case 802 * Get a header as a date value. Returns the value of a date field, or -1 if not found. The case
807 * of the field name is ignored. 803 * of the field name is ignored.
808 * 804 *
809 * @param name the case-insensitive field name 805 * @param name the case-insensitive field name
810 */ 806 */
811 public long getDateField(String name) 807 public long getDateField(String name)
812 { 808 {
813 Field field = getField(name); 809 Field field = getField(name);
814 if (field == null) 810 if (field == null)
815 return -1; 811 return -1;
816 812
817 String val = valueParameters(BufferUtil.to8859_1_String(field._value), null); 813 String val = valueParameters(BufferUtil.to8859_1_String(field._value), null);
818 if (val == null) 814 if (val == null)
819 return -1; 815 return -1;
820 816
821 final long date = __dateParser.get().parse(val); 817 final long date = __dateParser.get().parse(val);
822 if (date==-1) 818 if (date==-1)
823 throw new IllegalArgumentException("Cannot convert date: " + val); 819 throw new IllegalArgumentException("Cannot convert date: " + val);
824 return date; 820 return date;
825 } 821 }
826 822
827 /* -------------------------------------------------------------- */ 823 /* -------------------------------------------------------------- */
828 /** 824 /**
829 * Sets the value of an long field. 825 * Sets the value of an long field.
830 * 826 *
831 * @param name the field name 827 * @param name the field name
832 * @param value the field long value 828 * @param value the field long value
833 */ 829 */
834 public void putLongField(Buffer name, long value) 830 public void putLongField(Buffer name, long value)
835 { 831 {
836 Buffer v = BufferUtil.toBuffer(value); 832 Buffer v = BufferUtil.toBuffer(value);
837 put(name, v); 833 put(name, v);
838 } 834 }
839 835
840 /* -------------------------------------------------------------- */ 836 /* -------------------------------------------------------------- */
841 /** 837 /**
842 * Sets the value of an long field. 838 * Sets the value of an long field.
843 * 839 *
844 * @param name the field name 840 * @param name the field name
845 * @param value the field long value 841 * @param value the field long value
846 */ 842 */
847 public void putLongField(String name, long value) 843 public void putLongField(String name, long value)
848 { 844 {
849 Buffer n = HttpHeaders.CACHE.lookup(name); 845 Buffer n = HttpHeaders.CACHE.lookup(name);
850 Buffer v = BufferUtil.toBuffer(value); 846 Buffer v = BufferUtil.toBuffer(value);
851 put(n, v); 847 put(n, v);
852 } 848 }
853 849
854 /* -------------------------------------------------------------- */ 850 /* -------------------------------------------------------------- */
855 /** 851 /**
856 * Sets the value of an long field. 852 * Sets the value of an long field.
857 * 853 *
858 * @param name the field name 854 * @param name the field name
859 * @param value the field long value 855 * @param value the field long value
860 */ 856 */
861 public void addLongField(String name, long value) 857 public void addLongField(String name, long value)
862 { 858 {
863 Buffer n = HttpHeaders.CACHE.lookup(name); 859 Buffer n = HttpHeaders.CACHE.lookup(name);
864 Buffer v = BufferUtil.toBuffer(value); 860 Buffer v = BufferUtil.toBuffer(value);
865 add(n, v); 861 add(n, v);
866 } 862 }
867 863
868 /* -------------------------------------------------------------- */ 864 /* -------------------------------------------------------------- */
869 /** 865 /**
870 * Sets the value of an long field. 866 * Sets the value of an long field.
871 * 867 *
872 * @param name the field name 868 * @param name the field name
873 * @param value the field long value 869 * @param value the field long value
874 */ 870 */
875 public void addLongField(Buffer name, long value) 871 public void addLongField(Buffer name, long value)
876 { 872 {
877 Buffer v = BufferUtil.toBuffer(value); 873 Buffer v = BufferUtil.toBuffer(value);
878 add(name, v); 874 add(name, v);
879 } 875 }
880 876
881 /* -------------------------------------------------------------- */ 877 /* -------------------------------------------------------------- */
882 /** 878 /**
883 * Sets the value of a date field. 879 * Sets the value of a date field.
884 * 880 *
885 * @param name the field name 881 * @param name the field name
886 * @param date the field date value 882 * @param date the field date value
887 */ 883 */
888 public void putDateField(Buffer name, long date) 884 public void putDateField(Buffer name, long date)
889 { 885 {
890 String d=formatDate(date); 886 String d=formatDate(date);
891 Buffer v = new ByteArrayBuffer(d); 887 Buffer v = new ByteArrayBuffer(d);
892 put(name, v); 888 put(name, v);
893 } 889 }
894 890
895 /* -------------------------------------------------------------- */ 891 /* -------------------------------------------------------------- */
896 /** 892 /**
897 * Sets the value of a date field. 893 * Sets the value of a date field.
898 * 894 *
899 * @param name the field name 895 * @param name the field name
900 * @param date the field date value 896 * @param date the field date value
901 */ 897 */
902 public void putDateField(String name, long date) 898 public void putDateField(String name, long date)
903 { 899 {
904 Buffer n = HttpHeaders.CACHE.lookup(name); 900 Buffer n = HttpHeaders.CACHE.lookup(name);
905 putDateField(n,date); 901 putDateField(n,date);
906 } 902 }
907 903
908 /* -------------------------------------------------------------- */ 904 /* -------------------------------------------------------------- */
909 /** 905 /**
910 * Sets the value of a date field. 906 * Sets the value of a date field.
911 * 907 *
912 * @param name the field name 908 * @param name the field name
913 * @param date the field date value 909 * @param date the field date value
914 */ 910 */
915 public void addDateField(String name, long date) 911 public void addDateField(String name, long date)
916 { 912 {
917 String d=formatDate(date); 913 String d=formatDate(date);
918 Buffer n = HttpHeaders.CACHE.lookup(name); 914 Buffer n = HttpHeaders.CACHE.lookup(name);
919 Buffer v = new ByteArrayBuffer(d); 915 Buffer v = new ByteArrayBuffer(d);
920 add(n, v); 916 add(n, v);
921 } 917 }
922 918
923 /* ------------------------------------------------------------ */ 919 /* ------------------------------------------------------------ */
924 /** 920 /**
925 * Format a set cookie value 921 * Format a set cookie value
926 * 922 *
927 * @param cookie The cookie. 923 * @param cookie The cookie.
928 */ 924 */
929 public void addSetCookie(HttpCookie cookie) 925 public void addSetCookie(HttpCookie cookie)
930 { 926 {
931 addSetCookie( 927 addSetCookie(
932 cookie.getName(), 928 cookie.getName(),
933 cookie.getValue(), 929 cookie.getValue(),
934 cookie.getDomain(), 930 cookie.getDomain(),
935 cookie.getPath(), 931 cookie.getPath(),
936 cookie.getMaxAge(), 932 cookie.getMaxAge(),
937 cookie.getComment(), 933 cookie.getComment(),
938 cookie.isSecure(), 934 cookie.isSecure(),
939 cookie.isHttpOnly(), 935 cookie.isHttpOnly(),
940 cookie.getVersion()); 936 cookie.getVersion());
941 } 937 }
942 938
943 /** 939 /**
944 * Format a set cookie value 940 * Format a set cookie value
945 * 941 *
946 * @param name the name 942 * @param name the name
947 * @param value the value 943 * @param value the value
948 * @param domain the domain 944 * @param domain the domain
949 * @param path the path 945 * @param path the path
950 * @param maxAge the maximum age 946 * @param maxAge the maximum age
951 * @param comment the comment (only present on versions > 0) 947 * @param comment the comment (only present on versions > 0)
952 * @param isSecure true if secure cookie 948 * @param isSecure true if secure cookie
953 * @param isHttpOnly true if for http only 949 * @param isHttpOnly true if for http only
954 * @param version version of cookie logic to use (0 == default behavior) 950 * @param version version of cookie logic to use (0 == default behavior)
955 */ 951 */
956 public void addSetCookie( 952 public void addSetCookie(
957 final String name, 953 final String name,
958 final String value, 954 final String value,
959 final String domain, 955 final String domain,
960 final String path, 956 final String path,
961 final long maxAge, 957 final long maxAge,
962 final String comment, 958 final String comment,
963 final boolean isSecure, 959 final boolean isSecure,
964 final boolean isHttpOnly, 960 final boolean isHttpOnly,
965 int version) 961 int version)
966 { 962 {
967 String delim=__COOKIE_DELIM; 963 String delim=__COOKIE_DELIM;
968 964
969 // Check arguments 965 // Check arguments
970 if (name == null || name.length() == 0) 966 if (name == null || name.length() == 0)
971 throw new IllegalArgumentException("Bad cookie name"); 967 throw new IllegalArgumentException("Bad cookie name");
972 968
973 // Format value and params 969 // Format value and params
974 StringBuilder buf = new StringBuilder(128); 970 StringBuilder buf = new StringBuilder(128);
975 String name_value_params; 971 String name_value_params;
976 QuotedStringTokenizer.quoteIfNeeded(buf, name, delim); 972 QuotedStringTokenizer.quoteIfNeeded(buf, name, delim);
977 buf.append('='); 973 buf.append('=');
978 String start=buf.toString(); 974 String start=buf.toString();
979 boolean hasDomain = false; 975 boolean hasDomain = false;
980 boolean hasPath = false; 976 boolean hasPath = false;
981 977
982 if (value != null && value.length() > 0) 978 if (value != null && value.length() > 0)
983 QuotedStringTokenizer.quoteIfNeeded(buf, value, delim); 979 QuotedStringTokenizer.quoteIfNeeded(buf, value, delim);
984 980
985 if (comment != null && comment.length() > 0) 981 if (comment != null && comment.length() > 0)
986 { 982 {
987 buf.append(";Comment="); 983 buf.append(";Comment=");
988 QuotedStringTokenizer.quoteIfNeeded(buf, comment, delim); 984 QuotedStringTokenizer.quoteIfNeeded(buf, comment, delim);
989 } 985 }
990 986
991 if (path != null && path.length() > 0) 987 if (path != null && path.length() > 0)
992 { 988 {
993 hasPath = true; 989 hasPath = true;
994 buf.append(";Path="); 990 buf.append(";Path=");
995 if (path.trim().startsWith("\"")) 991 if (path.trim().startsWith("\""))
996 buf.append(path); 992 buf.append(path);
997 else 993 else
998 QuotedStringTokenizer.quoteIfNeeded(buf,path,delim); 994 QuotedStringTokenizer.quoteIfNeeded(buf,path,delim);
999 } 995 }
1000 if (domain != null && domain.length() > 0) 996 if (domain != null && domain.length() > 0)
1001 { 997 {
1002 hasDomain = true; 998 hasDomain = true;
1003 buf.append(";Domain="); 999 buf.append(";Domain=");
1004 QuotedStringTokenizer.quoteIfNeeded(buf,domain.toLowerCase(Locale.ENGLISH),delim); 1000 QuotedStringTokenizer.quoteIfNeeded(buf,domain.toLowerCase(Locale.ENGLISH),delim);
1005 } 1001 }
1006 1002
1007 if (maxAge >= 0) 1003 if (maxAge >= 0)
1008 { 1004 {
1009 // Always add the expires param as some browsers still don't handle max-age 1005 // Always add the expires param as some browsers still don't handle max-age
1010 buf.append(";Expires="); 1006 buf.append(";Expires=");
1011 if (maxAge == 0) 1007 if (maxAge == 0)
1012 buf.append(__01Jan1970_COOKIE); 1008 buf.append(__01Jan1970_COOKIE);
1013 else 1009 else
1014 formatCookieDate(buf, System.currentTimeMillis() + 1000L * maxAge); 1010 formatCookieDate(buf, System.currentTimeMillis() + 1000L * maxAge);
1015 1011
1016 if (version >0) 1012 if (version >0)
1017 { 1013 {
1018 buf.append(";Max-Age="); 1014 buf.append(";Max-Age=");
1019 buf.append(maxAge); 1015 buf.append(maxAge);
1020 } 1016 }
1021 } 1017 }
1022 1018
1023 if (isSecure) 1019 if (isSecure)
1024 buf.append(";Secure"); 1020 buf.append(";Secure");
1025 if (isHttpOnly) 1021 if (isHttpOnly)
1026 buf.append(";HttpOnly"); 1022 buf.append(";HttpOnly");
1027 1023
1028 name_value_params = buf.toString(); 1024 name_value_params = buf.toString();
1029 1025
1030 // remove existing set-cookie of same name 1026 // remove existing set-cookie of same name
1031 Field field = getField(HttpHeaders.SET_COOKIE); 1027 Field field = getField(HttpHeaders.SET_COOKIE);
1032 Field last=null; 1028 Field last=null;
1033 while (field!=null) 1029 while (field!=null)
1034 { 1030 {
1035 String val = (field._value == null ? null : field._value.toString()); 1031 String val = (field._value == null ? null : field._value.toString());
1036 if (val!=null && val.startsWith(start)) 1032 if (val!=null && val.startsWith(start))
1037 { 1033 {
1038 //existing cookie has same name, does it also match domain and path? 1034 //existing cookie has same name, does it also match domain and path?
1039 if (((!hasDomain && !val.contains("Domain")) || (hasDomain && val.contains("Domain="+domain))) && 1035 if (((!hasDomain && !val.contains("Domain")) || (hasDomain && val.contains("Domain="+domain))) &&
1040 ((!hasPath && !val.contains("Path")) || (hasPath && val.contains("Path="+path)))) 1036 ((!hasPath && !val.contains("Path")) || (hasPath && val.contains("Path="+path))))
1041 { 1037 {
1042 _fields.remove(field); 1038 _fields.remove(field);
1043 if (last==null) 1039 if (last==null)
1044 _names.put(HttpHeaders.SET_COOKIE_BUFFER,field._next); 1040 _names.put(HttpHeaders.SET_COOKIE_BUFFER,field._next);
1045 else 1041 else
1046 last._next=field._next; 1042 last._next=field._next;
1047 break; 1043 break;
1048 } 1044 }
1049 } 1045 }
1050 last=field; 1046 last=field;
1051 field=field._next; 1047 field=field._next;
1052 } 1048 }
1053 1049
1054 add(HttpHeaders.SET_COOKIE_BUFFER, new ByteArrayBuffer(name_value_params)); 1050 add(HttpHeaders.SET_COOKIE_BUFFER, new ByteArrayBuffer(name_value_params));
1055 1051
1056 // Expire responses with set-cookie headers so they do not get cached. 1052 // Expire responses with set-cookie headers so they do not get cached.
1057 put(HttpHeaders.EXPIRES_BUFFER, __01Jan1970_BUFFER); 1053 put(HttpHeaders.EXPIRES_BUFFER, __01Jan1970_BUFFER);
1058 } 1054 }
1059 1055
1060 /* -------------------------------------------------------------- */ 1056 /* -------------------------------------------------------------- */
1061 public void putTo(Buffer buffer) throws IOException 1057 public void putTo(Buffer buffer) throws IOException
1062 { 1058 {
1063 for (int i = 0; i < _fields.size(); i++) 1059 for (int i = 0; i < _fields.size(); i++)
1064 { 1060 {
1065 Field field = _fields.get(i); 1061 Field field = _fields.get(i);
1066 if (field != null) 1062 if (field != null)
1067 field.putTo(buffer); 1063 field.putTo(buffer);
1068 } 1064 }
1069 BufferUtil.putCRLF(buffer); 1065 BufferUtil.putCRLF(buffer);
1070 } 1066 }
1071 1067
1072 /* -------------------------------------------------------------- */ 1068 /* -------------------------------------------------------------- */
1073 public String toString() 1069 public String toString()
1074 { 1070 {
1075 try 1071 try
1076 { 1072 {
1077 StringBuffer buffer = new StringBuffer(); 1073 StringBuffer buffer = new StringBuffer();
1078 for (int i = 0; i < _fields.size(); i++) 1074 for (int i = 0; i < _fields.size(); i++)
1079 { 1075 {
1080 Field field = (Field) _fields.get(i); 1076 Field field = (Field) _fields.get(i);
1081 if (field != null) 1077 if (field != null)
1082 { 1078 {
1083 String tmp = field.getName(); 1079 String tmp = field.getName();
1084 if (tmp != null) buffer.append(tmp); 1080 if (tmp != null) buffer.append(tmp);
1085 buffer.append(": "); 1081 buffer.append(": ");
1086 tmp = field.getValue(); 1082 tmp = field.getValue();
1087 if (tmp != null) buffer.append(tmp); 1083 if (tmp != null) buffer.append(tmp);
1088 buffer.append("\r\n"); 1084 buffer.append("\r\n");
1089 } 1085 }
1090 } 1086 }
1091 buffer.append("\r\n"); 1087 buffer.append("\r\n");
1092 return buffer.toString(); 1088 return buffer.toString();
1093 } 1089 }
1094 catch (Exception e) 1090 catch (Exception e)
1095 { 1091 {
1096 LOG.warn("",e); 1092 LOG.warn("",e);
1097 return e.toString(); 1093 return e.toString();
1098 } 1094 }
1099 } 1095 }
1100 1096
1101 /* ------------------------------------------------------------ */ 1097 /* ------------------------------------------------------------ */
1102 /** 1098 /**
1103 * Clear the header. 1099 * Clear the header.
1104 */ 1100 */
1105 public void clear() 1101 public void clear()
1106 { 1102 {
1107 _fields.clear(); 1103 _fields.clear();
1108 _names.clear(); 1104 _names.clear();
1109 } 1105 }
1110 1106
1111 /* ------------------------------------------------------------ */ 1107 /* ------------------------------------------------------------ */
1112 /** 1108 /**
1113 * Add fields from another HttpFields instance. Single valued fields are replaced, while all 1109 * Add fields from another HttpFields instance. Single valued fields are replaced, while all
1114 * others are added. 1110 * others are added.
1115 * 1111 *
1116 * @param fields 1112 * @param fields
1117 */ 1113 */
1118 public void add(HttpFields fields) 1114 public void add(HttpFields fields)
1119 { 1115 {
1120 if (fields == null) return; 1116 if (fields == null) return;
1121 1117
1122 Enumeration e = fields.getFieldNames(); 1118 Enumeration e = fields.getFieldNames();
1123 while (e.hasMoreElements()) 1119 while (e.hasMoreElements())
1124 { 1120 {
1125 String name = (String) e.nextElement(); 1121 String name = (String) e.nextElement();
1126 Enumeration values = fields.getValues(name); 1122 Enumeration values = fields.getValues(name);
1127 while (values.hasMoreElements()) 1123 while (values.hasMoreElements())
1128 add(name, (String) values.nextElement()); 1124 add(name, (String) values.nextElement());
1129 } 1125 }
1130 } 1126 }
1131 1127
1132 /* ------------------------------------------------------------ */ 1128 /* ------------------------------------------------------------ */
1133 /** 1129 /**
1134 * Get field value parameters. Some field values can have parameters. This method separates the 1130 * Get field value parameters. Some field values can have parameters. This method separates the
1135 * value from the parameters and optionally populates a map with the parameters. For example: 1131 * value from the parameters and optionally populates a map with the parameters. For example:
1136 * 1132 *
1137 * <PRE> 1133 * <PRE>
1138 * 1134 *
1139 * FieldName : Value ; param1=val1 ; param2=val2 1135 * FieldName : Value ; param1=val1 ; param2=val2
1140 * 1136 *
1141 * </PRE> 1137 * </PRE>
1142 * 1138 *
1143 * @param value The Field value, possibly with parameteres. 1139 * @param value The Field value, possibly with parameteres.
1144 * @param parameters A map to populate with the parameters, or null 1140 * @param parameters A map to populate with the parameters, or null
1145 * @return The value. 1141 * @return The value.
1146 */ 1142 */
1147 public static String valueParameters(String value, Map<String,String> parameters) 1143 public static String valueParameters(String value, Map<String,String> parameters)
1148 { 1144 {
1149 if (value == null) return null; 1145 if (value == null) return null;
1150 1146
1151 int i = value.indexOf(';'); 1147 int i = value.indexOf(';');
1152 if (i < 0) return value; 1148 if (i < 0) return value;
1153 if (parameters == null) return value.substring(0, i).trim(); 1149 if (parameters == null) return value.substring(0, i).trim();
1154 1150
1155 StringTokenizer tok1 = new QuotedStringTokenizer(value.substring(i), ";", false, true); 1151 StringTokenizer tok1 = new QuotedStringTokenizer(value.substring(i), ";", false, true);
1156 while (tok1.hasMoreTokens()) 1152 while (tok1.hasMoreTokens())
1157 { 1153 {
1158 String token = tok1.nextToken(); 1154 String token = tok1.nextToken();
1159 StringTokenizer tok2 = new QuotedStringTokenizer(token, "= "); 1155 StringTokenizer tok2 = new QuotedStringTokenizer(token, "= ");
1160 if (tok2.hasMoreTokens()) 1156 if (tok2.hasMoreTokens())
1161 { 1157 {
1162 String paramName = tok2.nextToken(); 1158 String paramName = tok2.nextToken();
1163 String paramVal = null; 1159 String paramVal = null;
1164 if (tok2.hasMoreTokens()) paramVal = tok2.nextToken(); 1160 if (tok2.hasMoreTokens()) paramVal = tok2.nextToken();
1165 parameters.put(paramName, paramVal); 1161 parameters.put(paramName, paramVal);
1166 } 1162 }
1167 } 1163 }
1168 1164
1169 return value.substring(0, i).trim(); 1165 return value.substring(0, i).trim();
1170 } 1166 }
1171 1167
1172 /* ------------------------------------------------------------ */ 1168 /* ------------------------------------------------------------ */
1173 private static final Float __one = new Float("1.0"); 1169 private static final Float __zero = Float.valueOf("0.0");
1174 private static final Float __zero = new Float("0.0"); 1170
1175 private static final StringMap __qualities = new StringMap(); 1171 /* ------------------------------------------------------------ */
1176 static 1172 public static float getQuality(String value)
1177 { 1173 {
1178 __qualities.put(null, __one); 1174 if (value == null) return 0f;
1179 __qualities.put("1.0", __one); 1175
1180 __qualities.put("1", __one); 1176 if( value.indexOf(";") == -1 )
1181 __qualities.put("0.9", new Float("0.9")); 1177 return 1f;
1182 __qualities.put("0.8", new Float("0.8")); 1178
1183 __qualities.put("0.7", new Float("0.7")); 1179 Map params = new HashMap();
1184 __qualities.put("0.66", new Float("0.66")); 1180 valueParameters(value, params);
1185 __qualities.put("0.6", new Float("0.6")); 1181 String qs = (String) params.get("q");
1186 __qualities.put("0.5", new Float("0.5")); 1182 try {
1187 __qualities.put("0.4", new Float("0.4")); 1183 return Float.parseFloat(qs);
1188 __qualities.put("0.33", new Float("0.33")); 1184 } catch (NumberFormatException e) {
1189 __qualities.put("0.3", new Float("0.3")); 1185 return 1f;
1190 __qualities.put("0.2", new Float("0.2")); 1186 }
1191 __qualities.put("0.1", new Float("0.1")); 1187 }
1192 __qualities.put("0", __zero); 1188
1193 __qualities.put("0.0", __zero); 1189 /* ------------------------------------------------------------ */
1194 } 1190 /**
1195 1191 * List values in quality order.
1196 /* ------------------------------------------------------------ */ 1192 *
1197 public static Float getQuality(String value) 1193 * @param e Enumeration of values with quality parameters
1198 { 1194 * @return values in quality order.
1199 if (value == null) return __zero; 1195 */
1200 1196 public static List qualityList(Enumeration e)
1201 int qe = value.indexOf(";"); 1197 {
1202 if (qe++ < 0 || qe == value.length()) return __one; 1198 if (e == null || !e.hasMoreElements()) return Collections.EMPTY_LIST;
1203 1199
1204 if (value.charAt(qe++) == 'q') 1200 Object list = null;
1205 { 1201 Object qual = null;
1206 qe++; 1202
1207 Map.Entry entry = __qualities.getEntry(value, qe, value.length() - qe); 1203 // Assume list will be well ordered and just add nonzero
1208 if (entry != null) return (Float) entry.getValue(); 1204 while (e.hasMoreElements())
1209 } 1205 {
1210 1206 String v = e.nextElement().toString();
1211 HashMap params = new HashMap(3); 1207 Float q = getQuality(v);
1212 valueParameters(value, params); 1208
1213 String qs = (String) params.get("q"); 1209 if (q.floatValue() >= 0.001)
1214 Float q = (Float) __qualities.get(qs); 1210 {
1215 if (q == null) 1211 list = LazyList.add(list, v);
1216 { 1212 qual = LazyList.add(qual, q);
1217 try 1213 }
1218 { 1214 }
1219 q = new Float(qs); 1215
1220 } 1216 List vl = LazyList.getList(list, false);
1221 catch (Exception e) 1217 if (vl.size() < 2) return vl;
1222 { 1218
1223 q = __one; 1219 List ql = LazyList.getList(qual, false);
1224 } 1220
1225 } 1221 // sort list with swaps
1226 return q; 1222 Float last = __zero;
1227 } 1223 for (int i = vl.size(); i-- > 0;)
1228 1224 {
1229 /* ------------------------------------------------------------ */ 1225 Float q = (Float) ql.get(i);
1230 /** 1226 if (last.compareTo(q) > 0)
1231 * List values in quality order. 1227 {
1232 * 1228 Object tmp = vl.get(i);
1233 * @param e Enumeration of values with quality parameters 1229 vl.set(i, vl.get(i + 1));
1234 * @return values in quality order. 1230 vl.set(i + 1, tmp);
1235 */ 1231 ql.set(i, ql.get(i + 1));
1236 public static List qualityList(Enumeration e) 1232 ql.set(i + 1, q);
1237 { 1233 last = __zero;
1238 if (e == null || !e.hasMoreElements()) return Collections.EMPTY_LIST; 1234 i = vl.size();
1239 1235 continue;
1240 Object list = null; 1236 }
1241 Object qual = null; 1237 last = q;
1242 1238 }
1243 // Assume list will be well ordered and just add nonzero 1239 ql.clear();
1244 while (e.hasMoreElements()) 1240 return vl;
1245 { 1241 }
1246 String v = e.nextElement().toString(); 1242
1247 Float q = getQuality(v); 1243 /* ------------------------------------------------------------ */
1248 1244 /* ------------------------------------------------------------ */
1249 if (q.floatValue() >= 0.001) 1245 /* ------------------------------------------------------------ */
1250 { 1246 public static final class Field
1251 list = LazyList.add(list, v); 1247 {
1252 qual = LazyList.add(qual, q); 1248 private Buffer _name;
1253 } 1249 private Buffer _value;
1254 } 1250 private Field _next;
1255 1251
1256 List vl = LazyList.getList(list, false); 1252 /* ------------------------------------------------------------ */
1257 if (vl.size() < 2) return vl; 1253 private Field(Buffer name, Buffer value)
1258 1254 {
1259 List ql = LazyList.getList(qual, false); 1255 _name = name;
1260 1256 _value = value;
1261 // sort list with swaps 1257 _next = null;
1262 Float last = __zero; 1258 }
1263 for (int i = vl.size(); i-- > 0;) 1259
1264 { 1260 /* ------------------------------------------------------------ */
1265 Float q = (Float) ql.get(i); 1261 public void putTo(Buffer buffer) throws IOException
1266 if (last.compareTo(q) > 0) 1262 {
1267 { 1263 int o=(_name instanceof CachedBuffer)?((CachedBuffer)_name).getOrdinal():-1;
1268 Object tmp = vl.get(i); 1264 if (o>=0)
1269 vl.set(i, vl.get(i + 1)); 1265 buffer.put(_name);
1270 vl.set(i + 1, tmp); 1266 else
1271 ql.set(i, ql.get(i + 1)); 1267 {
1272 ql.set(i + 1, q); 1268 int s=_name.getIndex();
1273 last = __zero; 1269 int e=_name.putIndex();
1274 i = vl.size(); 1270 while (s<e)
1275 continue; 1271 {
1276 } 1272 byte b=_name.peek(s++);
1277 last = q; 1273 switch(b)
1278 } 1274 {
1279 ql.clear(); 1275 case '\r':
1280 return vl; 1276 case '\n':
1281 } 1277 case ':' :
1282 1278 continue;
1283 /* ------------------------------------------------------------ */ 1279 default:
1284 /* ------------------------------------------------------------ */ 1280 buffer.put(b);
1285 /* ------------------------------------------------------------ */ 1281 }
1286 public static final class Field 1282 }
1287 { 1283 }
1288 private Buffer _name; 1284
1289 private Buffer _value; 1285 buffer.put((byte) ':');
1290 private Field _next; 1286 buffer.put((byte) ' ');
1291 1287
1292 /* ------------------------------------------------------------ */ 1288 o=(_value instanceof CachedBuffer)?((CachedBuffer)_value).getOrdinal():-1;
1293 private Field(Buffer name, Buffer value) 1289 if (o>=0)
1294 { 1290 buffer.put(_value);
1295 _name = name; 1291 else
1296 _value = value; 1292 {
1297 _next = null; 1293 int s=_value.getIndex();
1298 } 1294 int e=_value.putIndex();
1299 1295 while (s<e)
1300 /* ------------------------------------------------------------ */ 1296 {
1301 public void putTo(Buffer buffer) throws IOException 1297 byte b=_value.peek(s++);
1302 { 1298 switch(b)
1303 int o=(_name instanceof CachedBuffer)?((CachedBuffer)_name).getOrdinal():-1; 1299 {
1304 if (o>=0) 1300 case '\r':
1305 buffer.put(_name); 1301 case '\n':
1306 else 1302 continue;
1307 { 1303 default:
1308 int s=_name.getIndex(); 1304 buffer.put(b);
1309 int e=_name.putIndex(); 1305 }
1310 while (s<e) 1306 }
1311 { 1307 }
1312 byte b=_name.peek(s++); 1308
1313 switch(b) 1309 BufferUtil.putCRLF(buffer);
1314 { 1310 }
1315 case '\r': 1311
1316 case '\n': 1312 /* ------------------------------------------------------------ */
1317 case ':' : 1313 public String getName()
1318 continue; 1314 {
1319 default: 1315 return BufferUtil.to8859_1_String(_name);
1320 buffer.put(b); 1316 }
1321 } 1317
1322 } 1318 /* ------------------------------------------------------------ */
1323 } 1319 Buffer getNameBuffer()
1324 1320 {
1325 buffer.put((byte) ':'); 1321 return _name;
1326 buffer.put((byte) ' '); 1322 }
1327 1323
1328 o=(_value instanceof CachedBuffer)?((CachedBuffer)_value).getOrdinal():-1; 1324 /* ------------------------------------------------------------ */
1329 if (o>=0) 1325 public int getNameOrdinal()
1330 buffer.put(_value); 1326 {
1331 else 1327 return HttpHeaders.CACHE.getOrdinal(_name);
1332 { 1328 }
1333 int s=_value.getIndex(); 1329
1334 int e=_value.putIndex(); 1330 /* ------------------------------------------------------------ */
1335 while (s<e) 1331 public String getValue()
1336 { 1332 {
1337 byte b=_value.peek(s++); 1333 return BufferUtil.to8859_1_String(_value);
1338 switch(b) 1334 }
1339 { 1335
1340 case '\r': 1336 /* ------------------------------------------------------------ */
1341 case '\n': 1337 public Buffer getValueBuffer()
1342 continue; 1338 {
1343 default: 1339 return _value;
1344 buffer.put(b); 1340 }
1345 } 1341
1346 } 1342 /* ------------------------------------------------------------ */
1347 } 1343 public int getValueOrdinal()
1348 1344 {
1349 BufferUtil.putCRLF(buffer); 1345 return HttpHeaderValues.CACHE.getOrdinal(_value);
1350 } 1346 }
1351 1347
1352 /* ------------------------------------------------------------ */ 1348 /* ------------------------------------------------------------ */
1353 public String getName() 1349 public int getIntValue()
1354 { 1350 {
1355 return BufferUtil.to8859_1_String(_name); 1351 return (int) getLongValue();
1356 } 1352 }
1357 1353
1358 /* ------------------------------------------------------------ */ 1354 /* ------------------------------------------------------------ */
1359 Buffer getNameBuffer() 1355 public long getLongValue()
1360 { 1356 {
1361 return _name; 1357 return BufferUtil.toLong(_value);
1362 } 1358 }
1363 1359
1364 /* ------------------------------------------------------------ */ 1360 /* ------------------------------------------------------------ */
1365 public int getNameOrdinal() 1361 public String toString()
1366 { 1362 {
1367 return HttpHeaders.CACHE.getOrdinal(_name); 1363 return ("[" + getName() + "=" + _value + (_next == null ? "" : "->") + "]");
1368 } 1364 }
1369 1365 }
1370 /* ------------------------------------------------------------ */
1371 public String getValue()
1372 {
1373 return BufferUtil.to8859_1_String(_value);
1374 }
1375
1376 /* ------------------------------------------------------------ */
1377 public Buffer getValueBuffer()
1378 {
1379 return _value;
1380 }
1381
1382 /* ------------------------------------------------------------ */
1383 public int getValueOrdinal()
1384 {
1385 return HttpHeaderValues.CACHE.getOrdinal(_value);
1386 }
1387
1388 /* ------------------------------------------------------------ */
1389 public int getIntValue()
1390 {
1391 return (int) getLongValue();
1392 }
1393
1394 /* ------------------------------------------------------------ */
1395 public long getLongValue()
1396 {
1397 return BufferUtil.toLong(_value);
1398 }
1399
1400 /* ------------------------------------------------------------ */
1401 public String toString()
1402 {
1403 return ("[" + getName() + "=" + _value + (_next == null ? "" : "->") + "]");
1404 }
1405 }
1406 } 1366 }