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