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