1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.http;
20
21 import java.io.IOException;
22 import java.nio.ByteBuffer;
23 import java.text.SimpleDateFormat;
24 import java.util.ArrayList;
25 import java.util.Calendar;
26 import java.util.Collection;
27 import java.util.Collections;
28 import java.util.Date;
29 import java.util.Enumeration;
30 import java.util.GregorianCalendar;
31 import java.util.HashMap;
32 import java.util.HashSet;
33 import java.util.Iterator;
34 import java.util.List;
35 import java.util.Locale;
36 import java.util.Map;
37 import java.util.NoSuchElementException;
38 import java.util.Set;
39 import java.util.StringTokenizer;
40 import java.util.TimeZone;
41
42 import org.eclipse.jetty.util.ArrayTernaryTrie;
43 import org.eclipse.jetty.util.BufferUtil;
44 import org.eclipse.jetty.util.DateCache;
45 import org.eclipse.jetty.util.LazyList;
46 import org.eclipse.jetty.util.QuotedStringTokenizer;
47 import org.eclipse.jetty.util.StringMap;
48 import org.eclipse.jetty.util.StringUtil;
49 import org.eclipse.jetty.util.Trie;
50 import org.eclipse.jetty.util.log.Log;
51 import org.eclipse.jetty.util.log.Logger;
52
53
54
55
56
57
58
59
60
61 public class HttpFields implements Iterable<HttpField>
62 {
63 private static final Logger LOG = Log.getLogger(HttpFields.class);
64 public static final String __COOKIE_DELIM="\"\\\n\r\t\f\b%+ ;=";
65 public static final TimeZone __GMT = TimeZone.getTimeZone("GMT");
66 public static final DateCache __dateCache = new DateCache("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
67
68 static
69 {
70 __GMT.setID("GMT");
71 __dateCache.setTimeZone(__GMT);
72 }
73
74 public final static String __separators = ", \t";
75
76 private static final String[] DAYS =
77 { "Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
78 private static final String[] MONTHS =
79 { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Jan"};
80
81 public static class DateGenerator
82 {
83 private final StringBuilder buf = new StringBuilder(32);
84 private final GregorianCalendar gc = new GregorianCalendar(__GMT);
85
86
87
88
89 public String formatDate(long date)
90 {
91 buf.setLength(0);
92 gc.setTimeInMillis(date);
93
94 int day_of_week = gc.get(Calendar.DAY_OF_WEEK);
95 int day_of_month = gc.get(Calendar.DAY_OF_MONTH);
96 int month = gc.get(Calendar.MONTH);
97 int year = gc.get(Calendar.YEAR);
98 int century = year / 100;
99 year = year % 100;
100
101 int hours = gc.get(Calendar.HOUR_OF_DAY);
102 int minutes = gc.get(Calendar.MINUTE);
103 int seconds = gc.get(Calendar.SECOND);
104
105 buf.append(DAYS[day_of_week]);
106 buf.append(',');
107 buf.append(' ');
108 StringUtil.append2digits(buf, day_of_month);
109
110 buf.append(' ');
111 buf.append(MONTHS[month]);
112 buf.append(' ');
113 StringUtil.append2digits(buf, century);
114 StringUtil.append2digits(buf, year);
115
116 buf.append(' ');
117 StringUtil.append2digits(buf, hours);
118 buf.append(':');
119 StringUtil.append2digits(buf, minutes);
120 buf.append(':');
121 StringUtil.append2digits(buf, seconds);
122 buf.append(" GMT");
123 return buf.toString();
124 }
125
126
127
128
129 public void formatCookieDate(StringBuilder buf, long date)
130 {
131 gc.setTimeInMillis(date);
132
133 int day_of_week = gc.get(Calendar.DAY_OF_WEEK);
134 int day_of_month = gc.get(Calendar.DAY_OF_MONTH);
135 int month = gc.get(Calendar.MONTH);
136 int year = gc.get(Calendar.YEAR);
137 year = year % 10000;
138
139 int epoch = (int) ((date / 1000) % (60 * 60 * 24));
140 int seconds = epoch % 60;
141 epoch = epoch / 60;
142 int minutes = epoch % 60;
143 int hours = epoch / 60;
144
145 buf.append(DAYS[day_of_week]);
146 buf.append(',');
147 buf.append(' ');
148 StringUtil.append2digits(buf, day_of_month);
149
150 buf.append('-');
151 buf.append(MONTHS[month]);
152 buf.append('-');
153 StringUtil.append2digits(buf, year/100);
154 StringUtil.append2digits(buf, year%100);
155
156 buf.append(' ');
157 StringUtil.append2digits(buf, hours);
158 buf.append(':');
159 StringUtil.append2digits(buf, minutes);
160 buf.append(':');
161 StringUtil.append2digits(buf, seconds);
162 buf.append(" GMT");
163 }
164 }
165
166 private static final ThreadLocal<DateGenerator> __dateGenerator =new ThreadLocal<DateGenerator>()
167 {
168 @Override
169 protected DateGenerator initialValue()
170 {
171 return new DateGenerator();
172 }
173 };
174
175
176
177
178 public static String formatDate(long date)
179 {
180 return __dateGenerator.get().formatDate(date);
181 }
182
183
184
185
186 public static void formatCookieDate(StringBuilder buf, long date)
187 {
188 __dateGenerator.get().formatCookieDate(buf,date);
189 }
190
191
192
193
194 public static String formatCookieDate(long date)
195 {
196 StringBuilder buf = new StringBuilder(28);
197 formatCookieDate(buf, date);
198 return buf.toString();
199 }
200
201 private final static String __dateReceiveFmt[] =
202 {
203 "EEE, dd MMM yyyy HH:mm:ss zzz",
204 "EEE, dd-MMM-yy HH:mm:ss",
205 "EEE MMM dd HH:mm:ss yyyy",
206
207 "EEE, dd MMM yyyy HH:mm:ss", "EEE dd MMM yyyy HH:mm:ss zzz",
208 "EEE dd MMM yyyy HH:mm:ss", "EEE MMM dd yyyy HH:mm:ss zzz", "EEE MMM dd yyyy HH:mm:ss",
209 "EEE MMM-dd-yyyy HH:mm:ss zzz", "EEE MMM-dd-yyyy HH:mm:ss", "dd MMM yyyy HH:mm:ss zzz",
210 "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",
211 "MMM dd HH:mm:ss yyyy", "EEE MMM dd HH:mm:ss yyyy zzz",
212 "EEE, MMM dd HH:mm:ss yyyy zzz", "EEE, MMM dd HH:mm:ss yyyy", "EEE, dd-MMM-yy HH:mm:ss zzz",
213 "EEE dd-MMM-yy HH:mm:ss zzz", "EEE dd-MMM-yy HH:mm:ss",
214 };
215
216 private static class DateParser
217 {
218 final SimpleDateFormat _dateReceive[]= new SimpleDateFormat[__dateReceiveFmt.length];
219
220 long parse(final String dateVal)
221 {
222 for (int i = 0; i < _dateReceive.length; i++)
223 {
224 if (_dateReceive[i] == null)
225 {
226 _dateReceive[i] = new SimpleDateFormat(__dateReceiveFmt[i], Locale.US);
227 _dateReceive[i].setTimeZone(__GMT);
228 }
229
230 try
231 {
232 Date date = (Date) _dateReceive[i].parseObject(dateVal);
233 return date.getTime();
234 }
235 catch (java.lang.Exception e)
236 {
237
238 }
239 }
240
241 if (dateVal.endsWith(" GMT"))
242 {
243 final String val = dateVal.substring(0, dateVal.length() - 4);
244
245 for (SimpleDateFormat element : _dateReceive)
246 {
247 try
248 {
249 Date date = (Date) element.parseObject(val);
250 return date.getTime();
251 }
252 catch (java.lang.Exception e)
253 {
254
255 }
256 }
257 }
258 return -1;
259 }
260 }
261
262 public static long parseDate(String date)
263 {
264 return __dateParser.get().parse(date);
265 }
266
267 private static final ThreadLocal<DateParser> __dateParser =new ThreadLocal<DateParser>()
268 {
269 @Override
270 protected DateParser initialValue()
271 {
272 return new DateParser();
273 }
274 };
275
276 public final static String __01Jan1970=formatDate(0);
277 public final static ByteBuffer __01Jan1970_BUFFER=BufferUtil.toBuffer(__01Jan1970);
278 public final static String __01Jan1970_COOKIE = formatCookieDate(0).trim();
279 private final ArrayList<HttpField> _fields = new ArrayList<>(20);
280
281
282
283
284 public HttpFields()
285 {
286 }
287
288
289
290
291
292 public Collection<String> getFieldNamesCollection()
293 {
294 final Set<String> list = new HashSet<>(_fields.size());
295 for (HttpField f : _fields)
296 {
297 if (f!=null)
298 list.add(f.getName());
299 }
300 return list;
301 }
302
303
304
305
306
307 public Enumeration<String> getFieldNames()
308 {
309 return Collections.enumeration(getFieldNamesCollection());
310 }
311
312 public int size()
313 {
314 return _fields.size();
315 }
316
317
318
319
320
321
322 public HttpField getField(int i)
323 {
324 return _fields.get(i);
325 }
326
327 @Override
328 public Iterator<HttpField> iterator()
329 {
330 return _fields.iterator();
331 }
332
333 public HttpField getField(HttpHeader header)
334 {
335 for (int i=0;i<_fields.size();i++)
336 {
337 HttpField f=_fields.get(i);
338 if (f.getHeader()==header)
339 return f;
340 }
341 return null;
342 }
343
344 public HttpField getField(String name)
345 {
346 for (int i=0;i<_fields.size();i++)
347 {
348 HttpField f=_fields.get(i);
349 if (f.getName().equalsIgnoreCase(name))
350 return f;
351 }
352 return null;
353 }
354
355 public boolean contains(HttpHeader header, String value)
356 {
357 for (int i=0;i<_fields.size();i++)
358 {
359 HttpField f=_fields.get(i);
360 if (f.getHeader()==header && f.contains(value))
361 return true;
362 }
363 return false;
364 }
365
366 public boolean contains(String name, String value)
367 {
368 for (int i=0;i<_fields.size();i++)
369 {
370 HttpField f=_fields.get(i);
371 if (f.getName().equalsIgnoreCase(name) && f.contains(value))
372 return true;
373 }
374 return false;
375 }
376
377 public boolean containsKey(String name)
378 {
379 for (int i=0;i<_fields.size();i++)
380 {
381 HttpField f=_fields.get(i);
382 if (f.getName().equalsIgnoreCase(name))
383 return true;
384 }
385 return false;
386 }
387
388 public String getStringField(HttpHeader header)
389 {
390 return getStringField(header.asString());
391 }
392
393 public String get(HttpHeader header)
394 {
395 return getStringField(header.asString());
396 }
397
398 public String get(String header)
399 {
400 return getStringField(header);
401 }
402
403
404
405
406
407
408 public String getStringField(String name)
409 {
410 HttpField field = getField(name);
411 return field==null?null:field.getValue();
412 }
413
414
415
416
417
418
419
420
421 public Collection<String> getValuesCollection(String name)
422 {
423 final List<String> list = new ArrayList<>();
424 for (HttpField f : _fields)
425 if (f.getName().equalsIgnoreCase(name))
426 list.add(f.getValue());
427 return list;
428 }
429
430
431
432
433
434
435
436 public Enumeration<String> getValues(final String name)
437 {
438 for (int i=0;i<_fields.size();i++)
439 {
440 final HttpField f = _fields.get(i);
441
442 if (f.getName().equalsIgnoreCase(name))
443 {
444 final int first=i;
445 return new Enumeration<String>()
446 {
447 HttpField field=f;
448 int i = first+1;
449
450 @Override
451 public boolean hasMoreElements()
452 {
453 if (field==null)
454 {
455 while (i<_fields.size())
456 {
457 field=_fields.get(i++);
458 if (field.getName().equalsIgnoreCase(name))
459 return true;
460 }
461 field=null;
462 return false;
463 }
464 return true;
465 }
466
467 @Override
468 public String nextElement() throws NoSuchElementException
469 {
470 if (hasMoreElements())
471 {
472 String value=field.getValue();
473 field=null;
474 return value;
475 }
476 throw new NoSuchElementException();
477 }
478
479 };
480 }
481 }
482
483 List<String> empty=Collections.emptyList();
484 return Collections.enumeration(empty);
485
486 }
487
488
489
490
491
492
493
494
495
496
497 public Enumeration<String> getValues(String name, final String separators)
498 {
499 final Enumeration<String> e = getValues(name);
500 if (e == null)
501 return null;
502 return new Enumeration<String>()
503 {
504 QuotedStringTokenizer tok = null;
505
506 @Override
507 public boolean hasMoreElements()
508 {
509 if (tok != null && tok.hasMoreElements()) return true;
510 while (e.hasMoreElements())
511 {
512 String value = e.nextElement();
513 tok = new QuotedStringTokenizer(value, separators, false, false);
514 if (tok.hasMoreElements()) return true;
515 }
516 tok = null;
517 return false;
518 }
519
520 @Override
521 public String nextElement() throws NoSuchElementException
522 {
523 if (!hasMoreElements()) throw new NoSuchElementException();
524 String next = (String) tok.nextElement();
525 if (next != null) next = next.trim();
526 return next;
527 }
528 };
529 }
530
531 public void put(HttpField field)
532 {
533 boolean put=false;
534 for (int i=_fields.size();i-->0;)
535 {
536 HttpField f=_fields.get(i);
537 if (f.isSame(field))
538 {
539 if (put)
540 _fields.remove(i);
541 else
542 {
543 _fields.set(i,field);
544 put=true;
545 }
546 }
547 }
548 if (!put)
549 _fields.add(field);
550 }
551
552
553
554
555
556
557
558 public void put(String name, String value)
559 {
560 if (value == null)
561 remove(name);
562 else
563 put(new HttpField(name, value));
564 }
565
566 public void put(HttpHeader header, HttpHeaderValue value)
567 {
568 put(header,value.toString());
569 }
570
571
572
573
574
575
576
577 public void put(HttpHeader header, String value)
578 {
579 if (value == null)
580 remove(header);
581 else
582 put(new HttpField(header, value));
583 }
584
585
586
587
588
589
590
591 public void put(String name, List<String> list)
592 {
593 remove(name);
594 for (String v : list)
595 if (v!=null)
596 add(name,v);
597 }
598
599
600
601
602
603
604
605
606
607
608 public void add(String name, String value) throws IllegalArgumentException
609 {
610 if (value == null)
611 return;
612
613 HttpField field = new HttpField(name, value);
614 _fields.add(field);
615 }
616
617 public void add(HttpHeader header, HttpHeaderValue value) throws IllegalArgumentException
618 {
619 add(header,value.toString());
620 }
621
622
623
624
625
626
627
628
629
630 public void add(HttpHeader header, String value) throws IllegalArgumentException
631 {
632 if (value == null) throw new IllegalArgumentException("null value");
633
634 HttpField field = new HttpField(header, value);
635 _fields.add(field);
636 }
637
638
639
640
641
642
643 public void remove(HttpHeader name)
644 {
645 for (int i=_fields.size();i-->0;)
646 {
647 HttpField f=_fields.get(i);
648 if (f.getHeader()==name)
649 _fields.remove(i);
650 }
651 }
652
653
654
655
656
657
658 public void remove(String name)
659 {
660 for (int i=_fields.size();i-->0;)
661 {
662 HttpField f=_fields.get(i);
663 if (f.getName().equalsIgnoreCase(name))
664 _fields.remove(i);
665 }
666 }
667
668
669
670
671
672
673
674
675 public long getLongField(String name) throws NumberFormatException
676 {
677 HttpField field = getField(name);
678 return field==null?-1L:field.getLongValue();
679 }
680
681
682
683
684
685
686
687 public long getDateField(String name)
688 {
689 HttpField field = getField(name);
690 if (field == null)
691 return -1;
692
693 String val = valueParameters(field.getValue(), null);
694 if (val == null)
695 return -1;
696
697 final long date = __dateParser.get().parse(val);
698 if (date==-1)
699 throw new IllegalArgumentException("Cannot convert date: " + val);
700 return date;
701 }
702
703
704
705
706
707
708
709
710 public void putLongField(HttpHeader name, long value)
711 {
712 String v = Long.toString(value);
713 put(name, v);
714 }
715
716
717
718
719
720
721
722 public void putLongField(String name, long value)
723 {
724 String v = Long.toString(value);
725 put(name, v);
726 }
727
728
729
730
731
732
733
734
735 public void putDateField(HttpHeader name, long date)
736 {
737 String d=formatDate(date);
738 put(name, d);
739 }
740
741
742
743
744
745
746
747 public void putDateField(String name, long date)
748 {
749 String d=formatDate(date);
750 put(name, d);
751 }
752
753
754
755
756
757
758
759 public void addDateField(String name, long date)
760 {
761 String d=formatDate(date);
762 add(name,d);
763 }
764
765
766
767
768
769
770 public void addSetCookie(HttpCookie cookie)
771 {
772 addSetCookie(
773 cookie.getName(),
774 cookie.getValue(),
775 cookie.getDomain(),
776 cookie.getPath(),
777 cookie.getMaxAge(),
778 cookie.getComment(),
779 cookie.isSecure(),
780 cookie.isHttpOnly(),
781 cookie.getVersion());
782 }
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797 public void addSetCookie(
798 final String name,
799 final String value,
800 final String domain,
801 final String path,
802 final long maxAge,
803 final String comment,
804 final boolean isSecure,
805 final boolean isHttpOnly,
806 int version)
807 {
808 String delim=__COOKIE_DELIM;
809
810
811 if (name == null || name.length() == 0)
812 throw new IllegalArgumentException("Bad cookie name");
813
814
815 StringBuilder buf = new StringBuilder(128);
816 String name_value_params;
817 QuotedStringTokenizer.quoteIfNeeded(buf, name, delim);
818 buf.append('=');
819 String start=buf.toString();
820 boolean hasDomain = false;
821 boolean hasPath = false;
822
823 if (value != null && value.length() > 0)
824 QuotedStringTokenizer.quoteIfNeeded(buf, value, delim);
825
826
827 if (path != null && path.length() > 0)
828 {
829 hasPath = true;
830 buf.append(";Path=");
831 if (path.trim().startsWith("\""))
832 buf.append(path);
833 else
834 QuotedStringTokenizer.quoteIfNeeded(buf,path,delim);
835 }
836 if (domain != null && domain.length() > 0)
837 {
838 hasDomain = true;
839 buf.append(";Domain=");
840 QuotedStringTokenizer.quoteIfNeeded(buf,domain.toLowerCase(Locale.ENGLISH),delim);
841 }
842
843 if (maxAge >= 0)
844 {
845
846 buf.append(";Expires=");
847 if (maxAge == 0)
848 buf.append(__01Jan1970_COOKIE);
849 else
850 formatCookieDate(buf, System.currentTimeMillis() + 1000L * maxAge);
851
852 buf.append(";Max-Age=");
853 buf.append(maxAge);
854 }
855
856 if (isSecure)
857 buf.append(";Secure");
858 if (isHttpOnly)
859 buf.append(";HttpOnly");
860
861 if (comment != null && comment.length() > 0)
862 {
863 buf.append(";Comment=");
864 QuotedStringTokenizer.quoteIfNeeded(buf, comment, delim);
865 }
866
867 name_value_params = buf.toString();
868
869
870
871 Iterator<HttpField> i=_fields.iterator();
872 while (i.hasNext())
873 {
874 HttpField field=i.next();
875 if (field.getHeader()==HttpHeader.SET_COOKIE)
876 {
877 String val = (field.getValue() == null ? null : field.getValue().toString());
878 if (val!=null && val.startsWith(start))
879 {
880
881 if (((!hasDomain && !val.contains("Domain")) || (hasDomain && val.contains("Domain="+domain))) &&
882 ((!hasPath && !val.contains("Path")) || (hasPath && val.contains("Path="+path))))
883 {
884 i.remove();
885 }
886 }
887
888 }
889 }
890
891 add(HttpHeader.SET_COOKIE.toString(), name_value_params);
892
893
894 put(HttpHeader.EXPIRES.toString(), __01Jan1970);
895 }
896
897 public void putTo(ByteBuffer bufferInFillMode) throws IOException
898 {
899 for (HttpField field : _fields)
900 {
901 if (field != null)
902 field.putTo(bufferInFillMode);
903 }
904 BufferUtil.putCRLF(bufferInFillMode);
905 }
906
907 @Override
908 public String
909 toString()
910 {
911 try
912 {
913 StringBuilder buffer = new StringBuilder();
914 for (HttpField field : _fields)
915 {
916 if (field != null)
917 {
918 String tmp = field.getName();
919 if (tmp != null) buffer.append(tmp);
920 buffer.append(": ");
921 tmp = field.getValue();
922 if (tmp != null) buffer.append(tmp);
923 buffer.append("\r\n");
924 }
925 }
926 buffer.append("\r\n");
927 return buffer.toString();
928 }
929 catch (Exception e)
930 {
931 LOG.warn(e);
932 return e.toString();
933 }
934 }
935
936
937
938
939 public void clear()
940 {
941 _fields.clear();
942 }
943
944 public void add(HttpField field)
945 {
946 _fields.add(field);
947 }
948
949
950
951
952
953
954
955
956
957 public void add(HttpFields fields)
958 {
959 if (fields == null) return;
960
961 Enumeration<String> e = fields.getFieldNames();
962 while (e.hasMoreElements())
963 {
964 String name = e.nextElement();
965 Enumeration<String> values = fields.getValues(name);
966 while (values.hasMoreElements())
967 add(name, values.nextElement());
968 }
969 }
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985 public static String valueParameters(String value, Map<String,String> parameters)
986 {
987 if (value == null) return null;
988
989 int i = value.indexOf(';');
990 if (i < 0) return value;
991 if (parameters == null) return value.substring(0, i).trim();
992
993 StringTokenizer tok1 = new QuotedStringTokenizer(value.substring(i), ";", false, true);
994 while (tok1.hasMoreTokens())
995 {
996 String token = tok1.nextToken();
997 StringTokenizer tok2 = new QuotedStringTokenizer(token, "= ");
998 if (tok2.hasMoreTokens())
999 {
1000 String paramName = tok2.nextToken();
1001 String paramVal = null;
1002 if (tok2.hasMoreTokens()) paramVal = tok2.nextToken();
1003 parameters.put(paramName, paramVal);
1004 }
1005 }
1006
1007 return value.substring(0, i).trim();
1008 }
1009
1010 private static final Float __one = new Float("1.0");
1011 private static final Float __zero = new Float("0.0");
1012 private static final Trie<Float> __qualities = new ArrayTernaryTrie<>();
1013 static
1014 {
1015 __qualities.put("*", __one);
1016 __qualities.put("1.0", __one);
1017 __qualities.put("1", __one);
1018 __qualities.put("0.9", new Float("0.9"));
1019 __qualities.put("0.8", new Float("0.8"));
1020 __qualities.put("0.7", new Float("0.7"));
1021 __qualities.put("0.66", new Float("0.66"));
1022 __qualities.put("0.6", new Float("0.6"));
1023 __qualities.put("0.5", new Float("0.5"));
1024 __qualities.put("0.4", new Float("0.4"));
1025 __qualities.put("0.33", new Float("0.33"));
1026 __qualities.put("0.3", new Float("0.3"));
1027 __qualities.put("0.2", new Float("0.2"));
1028 __qualities.put("0.1", new Float("0.1"));
1029 __qualities.put("0", __zero);
1030 __qualities.put("0.0", __zero);
1031 }
1032
1033 public static Float getQuality(String value)
1034 {
1035 if (value == null) return __zero;
1036
1037 int qe = value.indexOf(";");
1038 if (qe++ < 0 || qe == value.length()) return __one;
1039
1040 if (value.charAt(qe++) == 'q')
1041 {
1042 qe++;
1043 Float q = __qualities.get(value, qe, value.length() - qe);
1044 if (q != null)
1045 return q;
1046 }
1047
1048 Map<String,String> params = new HashMap<>(4);
1049 valueParameters(value, params);
1050 String qs = params.get("q");
1051 if (qs==null)
1052 qs="*";
1053 Float q = __qualities.get(qs);
1054 if (q == null)
1055 {
1056 try
1057 {
1058 q = new Float(qs);
1059 }
1060 catch (Exception e)
1061 {
1062 q = __one;
1063 }
1064 }
1065 return q;
1066 }
1067
1068
1069
1070
1071
1072
1073
1074 public static List<String> qualityList(Enumeration<String> e)
1075 {
1076 if (e == null || !e.hasMoreElements())
1077 return Collections.emptyList();
1078
1079 Object list = null;
1080 Object qual = null;
1081
1082
1083 while (e.hasMoreElements())
1084 {
1085 String v = e.nextElement();
1086 Float q = getQuality(v);
1087
1088 if (q >= 0.001)
1089 {
1090 list = LazyList.add(list, v);
1091 qual = LazyList.add(qual, q);
1092 }
1093 }
1094
1095 List vl = LazyList.getList(list, false);
1096 if (vl.size() < 2) return vl;
1097
1098 List ql = LazyList.getList(qual, false);
1099
1100
1101 Float last = __zero;
1102 for (int i = vl.size(); i-- > 0;)
1103 {
1104 Float q = (Float) ql.get(i);
1105 if (last.compareTo(q) > 0)
1106 {
1107 Object tmp = vl.get(i);
1108 vl.set(i, vl.get(i + 1));
1109 vl.set(i + 1, tmp);
1110 ql.set(i, ql.get(i + 1));
1111 ql.set(i + 1, q);
1112 last = __zero;
1113 i = vl.size();
1114 continue;
1115 }
1116 last = q;
1117 }
1118 ql.clear();
1119 return vl;
1120 }
1121
1122
1123 }