1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 package org.melati.util;
50
51 import java.nio.charset.Charset;
52 import java.nio.charset.UnsupportedCharsetException;
53 import java.util.HashMap;
54 import java.util.Iterator;
55 import java.util.List;
56
57
58
59
60
61
62
63
64
65 public class AcceptCharset extends HttpHeader {
66
67
68
69
70
71
72 protected HashMap<String, CharsetAndQValue> supportedAcceptedOrPreferred = new HashMap<String, CharsetAndQValue>();
73
74
75
76
77 CharsetAndQValue wildcard = null;
78
79
80
81
82
83
84
85
86
87
88 String firstOther = null;
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116 public AcceptCharset(String values, List<String> serverPreference) {
117 super(values);
118 int position = 0;
119 for (CharsetAndQValueIterator i = charsetAndQValueIterator(); i.hasNext();) {
120 try {
121 CharsetAndQValue c = i.nextCharsetAndQValue();
122 if (c.isWildcard()) {
123 wildcard = c;
124 } else {
125 String n = c.charset.name();
126 if (supportedAcceptedOrPreferred.get(c) == null) {
127 supportedAcceptedOrPreferred.put(n, c);
128 c.position = position++;
129 }
130 }
131 } catch (UnsupportedCharsetException uce) {
132
133 uce = null;
134 }
135 }
136 if (wildcard == null) {
137 Charset latin1 = Charset.forName("ISO-8859-1");
138 if (supportedAcceptedOrPreferred.get(latin1.name()) == null) {
139 CharsetAndQValue c = new CharsetAndQValue(latin1, 1.0f);
140 supportedAcceptedOrPreferred.put(latin1.name(), c);
141 }
142 }
143 for (int i = 0; i < serverPreference.size(); i++) {
144 try {
145 Charset charset = Charset.forName(serverPreference.get(i));
146 CharsetAndQValue acceptable = (CharsetAndQValue) supportedAcceptedOrPreferred
147 .get(charset.name());
148 if (acceptable == null) {
149 if (wildcard == null) {
150 if (firstOther == null) {
151 firstOther = charset.name();
152 }
153 } else {
154 CharsetAndQValue c = new CharsetAndQValue(charset, wildcard);
155 supportedAcceptedOrPreferred.put(charset.name(), c);
156 c.serverPreferability = i;
157 }
158 } else {
159 supportedAcceptedOrPreferred.put(charset.name(), acceptable);
160 if (i < acceptable.serverPreferability) {
161 acceptable.serverPreferability = i;
162 }
163 }
164 } catch (UnsupportedCharsetException uce) {
165
166 uce = null;
167 }
168 }
169 }
170
171
172
173
174 public class CharsetAndQValueIterator extends TokenAndQValueIterator {
175
176
177
178
179 public CharsetAndQValue nextCharsetAndQValue() throws HttpHeaderException {
180 return (CharsetAndQValue) AcceptCharset.this.nextTokenAndQValue();
181 }
182 }
183
184
185
186
187
188
189 public TokenAndQValue nextTokenAndQValue() {
190 return new CharsetAndQValue(tokenizer);
191 }
192
193
194
195
196
197
198
199 public CharsetAndQValueIterator charsetAndQValueIterator() {
200 return new CharsetAndQValueIterator();
201 }
202
203 private final Comparator<CharsetAndQValue> clientComparator = new Comparator<CharsetAndQValue>();
204
205
206
207
208
209
210 public String clientChoice() {
211 return choice(clientComparator);
212 }
213
214 private final Comparator<CharsetAndQValue> serverComparator = new Comparator<CharsetAndQValue>() {
215 protected int compareCharsetAndQValue(CharsetAndQValue one,
216 CharsetAndQValue two) {
217 int result;
218 result = two.serverPreferability - one.serverPreferability;
219 if (result == 0) {
220 result = super.compareCharsetAndQValue(one, two);
221 }
222 return result;
223 }
224 };
225
226
227
228
229
230 public String serverChoice() {
231 return choice(serverComparator);
232 }
233
234
235
236
237
238
239
240
241
242
243 public String choice(Comparator<CharsetAndQValue> comparator) {
244 CharsetAndQValue best = null;
245 for (Iterator<CharsetAndQValue> i = supportedAcceptedOrPreferred.values()
246 .iterator(); i.hasNext();) {
247 CharsetAndQValue c = (CharsetAndQValue) i.next();
248 if (best == null || comparator.compare(c, best) > 0) {
249 best = c;
250 }
251 }
252 if (best == null || best.q == 0.0) {
253 return null;
254 } else {
255 return best.charset.name();
256 }
257 }
258
259
260
261
262 protected static class Comparator<T> implements java.util.Comparator<T> {
263
264 @Override
265 public final int compare(Object one, Object two) {
266 return compareCharsetAndQValue((CharsetAndQValue) one,
267 (CharsetAndQValue) two);
268 }
269
270
271
272
273 protected int compareCharsetAndQValue(CharsetAndQValue one,
274 CharsetAndQValue two) {
275 if (one.q == two.q) {
276 return two.position - one.position;
277 } else if (one.q > two.q) {
278 return 1;
279 } else {
280
281 return -1;
282 }
283 }
284 }
285
286
287
288
289 public static class CharsetAndQValue extends TokenAndQValue {
290
291
292
293
294 Charset charset = null;
295
296
297
298
299
300
301
302
303 public int serverPreferability = Integer.MAX_VALUE;
304
305
306
307
308
309
310
311
312
313
314
315 public int position = Integer.MAX_VALUE;
316
317
318
319
320
321
322
323 public CharsetAndQValue(Tokenizer t) {
324 super(t);
325 if (!isWildcard()) {
326 charset = Charset.forName(token);
327 }
328 }
329
330
331
332
333 public CharsetAndQValue(Charset charset, float q) {
334 super();
335 this.token = charset.name();
336 this.charset = charset;
337 this.q = q;
338 }
339
340
341
342
343
344 public CharsetAndQValue(Charset charset, CharsetAndQValue wildcard) {
345 this(charset, wildcard.q);
346 }
347
348
349
350
351 public boolean isWildcard() {
352 return token.equals("*");
353 }
354
355 }
356
357 }