Mercurial Hosting > luan
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 } |