1 16 package org.mortbay.http; 17 18 import java.io.IOException ; 19 import java.io.StringWriter ; 20 import java.io.Writer ; 21 import java.text.SimpleDateFormat ; 22 import java.util.ArrayList ; 23 import java.util.Arrays ; 24 import java.util.Calendar ; 25 import java.util.Collections ; 26 import java.util.Date ; 27 import java.util.Enumeration ; 28 import java.util.GregorianCalendar ; 29 import java.util.HashMap ; 30 import java.util.Iterator ; 31 import java.util.List ; 32 import java.util.Locale ; 33 import java.util.Map ; 34 import java.util.NoSuchElementException ; 35 import java.util.StringTokenizer ; 36 import java.util.TimeZone ; 37 38 import javax.servlet.http.Cookie ; 39 40 import org.apache.commons.logging.Log; 41 import org.mortbay.log.LogFactory; 42 import org.mortbay.util.DateCache; 43 import org.mortbay.util.LazyList; 44 import org.mortbay.util.LineInput; 45 import org.mortbay.util.LogSupport; 46 import org.mortbay.util.QuotedStringTokenizer; 47 import org.mortbay.util.StringMap; 48 import org.mortbay.util.StringUtil; 49 import org.mortbay.util.URI; 50 51 52 63 public class HttpFields 64 { 65 private static Log log = LogFactory.getLog(HttpFields.class); 66 67 68 70 public final static String 71 __CacheControl = "Cache-Control", 72 __Connection = "Connection", 73 __Date = "Date", 74 __Pragma = "Pragma", 75 __ProxyConnection = "Proxy-Connection", 76 __Trailer = "Trailer", 77 __TransferEncoding = "Transfer-Encoding", 78 __Upgrade = "Upgrade", 79 __Via = "Via", 80 __Warning = "Warning"; 81 82 83 85 public final static String 86 __Allow = "Allow", 87 __ContentEncoding = "Content-Encoding", 88 __ContentLanguage = "Content-Language", 89 __ContentLength = "Content-Length", 90 __ContentLocation = "Content-Location", 91 __ContentMD5 = "Content-MD5", 92 __ContentRange = "Content-Range", 93 __ContentType = "Content-Type", 94 __Expires = "Expires", 95 __LastModified = "Last-Modified"; 96 97 98 100 public final static String 101 __Accept = "Accept", 102 __AcceptCharset = "Accept-Charset", 103 __AcceptEncoding = "Accept-Encoding", 104 __AcceptLanguage = "Accept-Language", 105 __Authorization = "Authorization", 106 __Expect = "Expect", 107 __Forwarded = "Forwarded", 108 __From = "From", 109 __Host = "Host", 110 __IfMatch = "If-Match", 111 __IfModifiedSince = "If-Modified-Since", 112 __IfNoneMatch = "If-None-Match", 113 __IfRange = "If-Range", 114 __IfUnmodifiedSince = "If-Unmodified-Since", 115 __KeepAlive = "keep-alive", 116 __MaxForwards = "Max-Forwards", 117 __ProxyAuthorization = "Proxy-Authorization", 118 __Range = "Range", 119 __RequestRange = "Request-Range", 120 __Referer = "Referer", 121 __TE = "TE", 122 __UserAgent = "User-Agent", 123 __XForwardedFor = "X-Forwarded-For"; 124 125 126 127 129 public final static String 130 __AcceptRanges = "Accept-Ranges", 131 __Age = "Age", 132 __ETag = "ETag", 133 __Location = "Location", 134 __ProxyAuthenticate = "Proxy-Authenticate", 135 __RetryAfter = "Retry-After", 136 __Server = "Server", 137 __ServletEngine = "Servlet-Engine", 138 __Vary = "Vary", 139 __WwwAuthenticate = "WWW-Authenticate"; 140 141 142 144 public final static String 145 __Cookie = "Cookie", 146 __SetCookie = "Set-Cookie", 147 __SetCookie2 = "Set-Cookie2", 148 __MimeVersion ="MIME-Version", 149 __Identity ="identity", 150 __SoapAction ="SOAPAction"; 151 152 153 155 private static final class FieldInfo 156 { 157 String _name; 158 String _lname; 159 boolean _inlineValues; 160 int _hashCode; 161 static int __hashCode; 162 163 FieldInfo(String name, boolean inline) 164 { 165 synchronized(FieldInfo.class) 166 { 167 _name=name; 168 _lname=StringUtil.asciiToLowerCase(name); 169 _inlineValues=inline; 170 171 _hashCode=__hashCode++; 172 173 if (__hashCode < __maxCacheSize) 174 { 175 FieldInfo oldInfo = (FieldInfo)__info.get(name); 176 if (oldInfo == null) 177 { 178 __info.put(name, this); 179 if (!name.equals(_lname)) 180 __info.put(_lname, this); 181 } 182 else 183 _hashCode = oldInfo._hashCode; 184 } 185 } 186 } 187 188 public String toString() 189 { 190 return "["+_name+","+_hashCode+","+_inlineValues+"]"; 191 } 192 193 public int hashCode() 194 { 195 return _hashCode; 196 } 197 198 public boolean equals(Object o) 199 { 200 if (o==null || !(o instanceof FieldInfo)) 201 return false; 202 FieldInfo fi = (FieldInfo)o; 203 return 204 fi==this || 205 fi._hashCode==_hashCode || 206 fi._name.equals(_name); 207 } 208 } 209 210 211 private static final StringMap __info = new StringMap(true); 212 private static final StringMap __values = new StringMap(true); 213 private static final int __maxCacheSize=128; 214 215 216 static 217 { 218 new FieldInfo(__Host,false); 221 222 new FieldInfo(__KeepAlive,false); 223 new FieldInfo(__Connection,false); 224 225 new FieldInfo(__Cookie,false); 226 227 new FieldInfo(__Accept,false); 228 new FieldInfo(__AcceptLanguage,false); 229 new FieldInfo(__AcceptEncoding,false); 230 new FieldInfo(__AcceptCharset,false); 231 new FieldInfo(__CacheControl,false); 232 new FieldInfo(__SetCookie,false); 233 new FieldInfo(__SetCookie2,false); 234 235 new FieldInfo(__Date,false); 236 new FieldInfo(__TransferEncoding,true); 237 new FieldInfo(__ContentEncoding,true); 238 new FieldInfo(__ContentLength,false); 239 new FieldInfo(__Expires,false); 240 new FieldInfo(__Expect,false); 241 242 new FieldInfo(__Referer,false); 243 new FieldInfo(__TE,false); 244 new FieldInfo(__UserAgent,false); 245 246 new FieldInfo(__IfModifiedSince,false); 247 new FieldInfo(__IfRange,false); 248 new FieldInfo(__IfUnmodifiedSince,false); 249 250 new FieldInfo(__Location,false); 251 new FieldInfo(__Server,false); 252 new FieldInfo(__ServletEngine,false); 253 254 new FieldInfo(__AcceptRanges,false); 255 new FieldInfo(__Range,false); 256 new FieldInfo(__RequestRange,false); 257 258 new FieldInfo(__SoapAction,false); 259 260 new FieldInfo(__ContentLocation,false); 261 new FieldInfo(__ContentMD5,false); 262 new FieldInfo(__ContentRange,false); 263 new FieldInfo(__ContentType,false); 264 new FieldInfo(__LastModified,false); 265 new FieldInfo(__Authorization,false); 266 new FieldInfo(__From,false); 267 new FieldInfo(__MaxForwards,false); 268 new FieldInfo(__ProxyAuthenticate,false); 269 new FieldInfo(__Age,false); 270 new FieldInfo(__ETag,false); 271 new FieldInfo(__RetryAfter,false); 272 273 274 } 275 276 277 private static FieldInfo getFieldInfo(String name) 278 { 279 FieldInfo info = (FieldInfo)__info.get(name); 280 if (info==null) 281 info = new FieldInfo(name,false); 282 return info; 283 } 284 285 286 private static FieldInfo getFieldInfo(char[] name,int offset,int length) 287 { 288 Map.Entry entry = __info.getEntry(name,offset,length); 289 if (entry==null) 290 return new FieldInfo(new String (name,offset,length),false); 291 292 return (FieldInfo) entry.getValue(); 293 } 294 295 296 298 public final static String __Chunked = "chunked"; 299 public final static String __Close = "close"; 300 public final static String __TextHtml = "text/html"; 301 public final static String __MessageHttp = "message/http"; 302 public final static String __WwwFormUrlEncode = 303 "application/x-www-form-urlencoded"; 304 public static final String __ExpectContinue="100-continue"; 305 306 static 307 { 308 __values.put(__KeepAlive,__KeepAlive); 309 __values.put(__Chunked,__Chunked); 310 __values.put(__Close,__Close); 311 __values.put(__TextHtml,__TextHtml); 312 __values.put(__MessageHttp,__MessageHttp); 313 __values.put(__WwwFormUrlEncode,__WwwFormUrlEncode); 314 __values.put(__ExpectContinue,__ExpectContinue); 315 __values.put("max-age=0","max-age=0"); 316 __values.put("no-cache","no-cache"); 317 __values.put("300","300"); 318 __values.put("ISO-8859-1, utf-8;q=0.66, *;q=0.66","ISO-8859-1, utf-8;q=0.66, *;q=0.66"); 319 } 320 321 322 public final static String __separators = ", \t"; 323 324 325 public final static char[] __CRLF = {'\015','\012'}; 326 public final static char[] __COLON = {':',' '}; 327 328 329 private static String [] DAYS= { "Sat","Sun","Mon","Tue","Wed","Thu","Fri","Sat" }; 330 private static String [] MONTHS= { "Jan","Feb","Mar","Apr","May","Jun", 331 "Jul","Aug","Sep","Oct","Nov","Dec","Jan" }; 332 333 334 335 339 public static String formatDate(long date, boolean cookie) 340 { 341 StringBuffer buf = new StringBuffer (32); 342 HttpCal gc = new HttpCal(); 343 gc.setTimeInMillis(date); 344 formatDate(buf,gc,cookie); 345 return buf.toString(); 346 } 347 348 349 353 public static String formatDate(Calendar calendar, boolean cookie) 354 { 355 StringBuffer buf = new StringBuffer (32); 356 formatDate(buf,calendar,cookie); 357 return buf.toString(); 358 } 359 360 361 365 public static String formatDate(StringBuffer buf, long date, boolean cookie) 366 { 367 HttpCal gc = new HttpCal(); 368 gc.setTimeInMillis(date); 369 formatDate(buf,gc,cookie); 370 return buf.toString(); 371 } 372 373 374 378 public static void formatDate(StringBuffer buf,Calendar calendar, boolean cookie) 379 { 380 383 int day_of_week = calendar.get(Calendar.DAY_OF_WEEK); 384 int day_of_month = calendar.get(Calendar.DAY_OF_MONTH); 385 int month = calendar.get(Calendar.MONTH); 386 int year = calendar.get(Calendar.YEAR); 387 int century = year/100; 388 year=year%100; 389 390 long tm = (calendar instanceof HttpCal)?(((HttpCal)calendar).getTimeInMillis()):calendar.getTime().getTime(); 391 int epoch=(int)((tm/1000) % (60*60*24)); 392 int seconds=epoch%60; 393 epoch=epoch/60; 394 int minutes=epoch%60; 395 int hours=epoch/60; 396 397 buf.append(DAYS[day_of_week]); 398 buf.append(','); 399 buf.append(' '); 400 StringUtil.append2digits(buf,day_of_month); 401 402 if (cookie) 403 { 404 buf.append('-'); 405 buf.append(MONTHS[month]); 406 buf.append('-'); 407 StringUtil.append2digits(buf,year); 408 } 409 else 410 { 411 buf.append(' '); 412 buf.append(MONTHS[month]); 413 buf.append(' '); 414 StringUtil.append2digits(buf,century); 415 StringUtil.append2digits(buf,year); 416 } 417 buf.append(' '); 418 StringUtil.append2digits(buf,hours); 419 buf.append(':'); 420 StringUtil.append2digits(buf,minutes); 421 buf.append(':'); 422 StringUtil.append2digits(buf,seconds); 423 buf.append(" GMT"); 424 } 425 426 427 private static TimeZone __GMT = TimeZone.getTimeZone("GMT"); 428 public final static DateCache __dateCache = 429 new DateCache("EEE, dd MMM yyyy HH:mm:ss 'GMT'", 430 Locale.US); 431 432 433 private final static String __dateReceiveFmt[] = 434 { 435 "EEE, dd MMM yyyy HH:mm:ss zzz", 436 "EEE, dd-MMM-yy HH:mm:ss zzz", 437 "EEE MMM dd HH:mm:ss yyyy", 438 "EEE, dd MMM yyyy HH:mm:ss zzz", 439 "EEE, dd-MMM-yy HH:mm:ss zzz", 440 "dd MMM yyyy HH:mm:ss", 441 "dd-MMM-yy HH:mm:ss", 442 }; 443 public static SimpleDateFormat __dateReceiveSource[]; 444 public static final ThreadLocal __dateReceiveCache=new ThreadLocal (); 445 static 446 { 447 __GMT.setID("GMT"); 448 __dateCache.setTimeZone(__GMT); 449 __dateReceiveSource = new SimpleDateFormat [__dateReceiveFmt.length]; 450 for(int i=0;i<__dateReceiveSource.length;i++) 451 { 452 __dateReceiveSource[i] = 453 new SimpleDateFormat (__dateReceiveFmt[i],Locale.US); 454 __dateReceiveSource[i].setTimeZone(__GMT); 455 } 456 } 457 458 public final static String __01Jan1970=HttpFields.formatDate(0,false); 459 460 461 462 463 464 private static final class Field 465 { 466 FieldInfo _info; 467 String _value; 468 Field _next; 469 Field _prev; 470 int _version; 471 472 473 Field(FieldInfo info, String value, int version) 474 { 475 _info=info; 476 _value=value; 477 _next=null; 478 _prev=null; 479 _version=version; 480 } 481 482 483 Field(FieldInfo info, char[] buf, int offset, int length, int version) 484 { 485 Map.Entry valueEntry=__values.getEntry(buf,offset,length); 486 String value=null; 487 if (valueEntry!=null) 488 value=(String )valueEntry.getKey(); 489 else 490 value=new String (buf,offset,length); 491 492 _info=info; 493 _value=value; 494 _next=null; 495 _prev=null; 496 _version=version; 497 } 498 499 500 public boolean equals(Object o) 501 { 502 return (o instanceof Field) && 503 o==this && 504 _version==((Field)o)._version; 505 } 506 507 508 public int hashCode() 509 { 510 return _info.hashCode()*_version; 511 } 512 513 514 void clear() 515 { 516 _version=-1; 517 } 518 519 520 void destroy() 521 { 522 _info=null; 523 _value=null; 524 _next=null; 525 _prev=null; 526 _version=-1; 527 } 528 529 530 void reset(String value,int version) 531 { 532 _value=value; 533 _version=version; 534 } 535 536 537 541 void reset(char[] buf, int offset, int length, int version) 542 { 543 _version=version; 544 if (!StringUtil.equals(_value,buf,offset,length)) 545 { 546 Map.Entry valueEntry=__values.getEntry(buf,offset,length); 547 String value=null; 548 if (valueEntry!=null) 549 value=(String )valueEntry.getKey(); 550 else 551 value=new String (buf,offset,length); 552 _value=value; 553 } 554 } 555 556 557 558 void write(Writer writer, int version) 559 throws IOException 560 { 561 if (_info==null || _version!=version) 562 return; 563 if (_info._inlineValues) 564 { 565 if (_prev!=null) 566 return; 567 writer.write(_info._name); 568 writer.write(__COLON); 569 Field f=this; 570 while (true) 571 { 572 writer.write(QuotedStringTokenizer.quote(f._value,", \t")); 573 f=f._next; 574 if (f==null) 575 break; 576 writer.write(","); 577 } 578 writer.write(__CRLF); 579 } 580 else 581 { 582 writer.write(_info._name); 583 writer.write(__COLON); 584 writer.write(_value); 585 writer.write(__CRLF); 586 } 587 } 588 589 590 String getDisplayName() 591 { 592 return _info._name; 593 } 594 595 596 public String toString() 597 { 598 return ("["+ 599 (_prev==null?"":"<-")+ 600 getDisplayName()+"="+_value+ 601 (_next==null?"":"->")+ 602 "]"); 603 } 604 } 605 606 607 private static Float __one = new Float ("1.0"); 608 private static Float __zero = new Float ("0.0"); 609 private static StringMap __qualities=new StringMap(); 610 static 611 { 612 __qualities.put(null,__one); 613 __qualities.put("1.0",__one); 614 __qualities.put("1",__one); 615 __qualities.put("0.9",new Float ("0.9")); 616 __qualities.put("0.8",new Float ("0.8")); 617 __qualities.put("0.7",new Float ("0.7")); 618 __qualities.put("0.66",new Float ("0.66")); 619 __qualities.put("0.6",new Float ("0.6")); 620 __qualities.put("0.5",new Float ("0.5")); 621 __qualities.put("0.4",new Float ("0.4")); 622 __qualities.put("0.33",new Float ("0.33")); 623 __qualities.put("0.3",new Float ("0.3")); 624 __qualities.put("0.2",new Float ("0.2")); 625 __qualities.put("0.1",new Float ("0.1")); 626 __qualities.put("0",__zero); 627 __qualities.put("0.0",__zero); 628 } 629 630 631 632 private ArrayList _fields=new ArrayList (15); 633 private int[] _index=new int[__maxCacheSize]; 634 private int _version; 635 private SimpleDateFormat _dateReceive[]; 636 private StringBuffer _dateBuffer; 637 private HttpCal _calendar; 638 639 640 642 public HttpFields() 643 { 644 Arrays.fill(_index,-1); 645 } 646 647 648 649 public int size() 650 { 651 return _fields.size(); 652 } 653 654 655 659 public Enumeration getFieldNames() 660 { 661 return new Enumeration () 662 { 663 int i=0; 664 Field field=null; 665 666 public boolean hasMoreElements() 667 { 668 if (field!=null) 669 return true; 670 while (i<_fields.size()) 671 { 672 Field f=(Field)_fields.get(i++); 673 if (f!=null && f._version==_version && f._prev==null) 674 { 675 field=f; 676 return true; 677 } 678 } 679 return false; 680 } 681 682 public Object nextElement() 683 throws NoSuchElementException 684 { 685 if (field!=null || hasMoreElements()) 686 { 687 String n=field._info._name; 688 field=null; 689 return n; 690 } 691 throw new NoSuchElementException (); 692 } 693 }; 694 } 695 696 697 Field getField(String name) 698 { 699 FieldInfo info=getFieldInfo(name); 700 return getField(info,true); 701 } 702 703 704 Field getField(FieldInfo info, boolean getValid) 705 { 706 int hi=info.hashCode(); 707 708 if (hi<_index.length) 709 { 710 if (_index[hi]>=0) 711 { 712 Field field=(Field)(_fields.get(_index[hi])); 713 714 return (field!=null && (!getValid||field._version==_version))?field:null; 715 } 716 } 717 else 718 { 719 for (int i=0;i<_fields.size();i++) 720 { 721 Field field=(Field)_fields.get(i); 722 if (info.equals(field._info) && (!getValid||field._version==_version)) 723 return field; 724 } 725 } 726 return null; 727 } 728 729 730 public boolean containsKey(String name) 731 { 732 FieldInfo info=getFieldInfo(name); 733 return getField(info,true)!=null; 734 } 735 736 737 742 public String get(String name) 743 { 744 FieldInfo info=getFieldInfo(name); 745 Field field=getField(info,true); 746 if (field!=null) 747 return field._value; 748 return null; 749 } 750 751 752 756 public Enumeration getValues(String name) 757 { 758 FieldInfo info=getFieldInfo(name); 759 final Field field=getField(info,true); 760 761 if (field!=null) 762 { 763 return new Enumeration () 764 { 765 Field f=field; 766 767 public boolean hasMoreElements() 768 { 769 while (f!=null && f._version!=_version) 770 f=f._next; 771 return f!=null; 772 } 773 774 public Object nextElement() 775 throws NoSuchElementException 776 { 777 if (f==null) 778 throw new NoSuchElementException (); 779 Field n=f; 780 do f=f._next; while (f!=null && f._version!=_version); 781 return n._value; 782 } 783 }; 784 } 785 return null; 786 } 787 788 789 797 public Enumeration getValues(String name,final String separators) 798 { 799 final Enumeration e = getValues(name); 800 if (e==null) 801 return null; 802 return new Enumeration () 803 { 804 QuotedStringTokenizer tok=null; 805 public boolean hasMoreElements() 806 { 807 if (tok!=null && tok.hasMoreElements()) 808 return true; 809 while (e.hasMoreElements()) 810 { 811 String value=(String )e.nextElement(); 812 tok=new QuotedStringTokenizer(value,separators,false,false); 813 if (tok.hasMoreElements()) 814 return true; 815 } 816 tok=null; 817 return false; 818 } 819 820 public Object nextElement() 821 throws NoSuchElementException 822 { 823 if (!hasMoreElements()) 824 throw new NoSuchElementException (); 825 String next=(String ) tok.nextElement(); 826 if (next!=null)next=next.trim(); 827 return next; 828 } 829 }; 830 } 831 832 833 837 public String put(String name,String value) 838 { 839 if (value==null) 840 return remove(name); 841 842 FieldInfo info=getFieldInfo(name); 843 Field field=getField(info,false); 844 if (field!=null) 846 { 847 String old=(field._version==_version)?field._value:null; 848 field.reset(value,_version); 849 850 field=field._next; 851 while(field!=null) 852 { 853 field.clear(); 854 field=field._next; 855 } 856 return old; 857 } 858 else 859 { 860 field=new Field(info,value,_version); 862 int hi=info.hashCode(); 863 if (hi<_index.length) 864 _index[hi]=_fields.size(); 865 _fields.add(field); 866 return null; 867 } 868 } 869 870 871 872 876 public void put(String name,List list) 877 { 878 if (list==null || list.size()==0) 879 { 880 remove(name); 881 return; 882 } 883 884 Object v=list.get(0); 885 if (v!=null) 886 put(name,v.toString()); 887 else 888 remove(name); 889 890 if (list.size()>1) 891 { 892 java.util.Iterator iter = list.iterator(); 893 iter.next(); 894 while(iter.hasNext()) 895 { 896 v=iter.next(); 897 if (v!=null) 898 add(name,v.toString()); 899 } 900 } 901 } 902 903 904 905 913 public void add(String name,String value) 914 throws IllegalArgumentException 915 { 916 if (value==null) 917 throw new IllegalArgumentException ("null value"); 918 919 FieldInfo info=getFieldInfo(name); 920 Field field=getField(info,false); 921 Field last=null; 922 if (field!=null) 923 { 924 while(field!=null && field._version==_version) 925 { 926 last=field; 927 field=field._next; 928 } 929 } 930 931 if (field!=null) 932 field.reset(value,_version); 933 else 934 { 935 field=new Field(info,value,_version); 937 938 if(last!=null) 940 { 941 field._prev=last; 942 last._next=field; 943 } 944 else if (info.hashCode()<_index.length) 945 _index[info.hashCode()]=_fields.size(); 946 947 _fields.add(field); 948 } 949 } 950 951 952 955 public String remove(String name) 956 { 957 String old=null; 958 FieldInfo info=getFieldInfo(name); 959 Field field=getField(info,true); 960 961 if (field!=null) 962 { 963 old=field._value; 964 while(field!=null) 965 { 966 field.clear(); 967 field=field._next; 968 } 969 } 970 971 return old; 972 } 973 974 975 981 public int getIntField(String name) 982 throws NumberFormatException 983 { 984 String val = valueParameters(get(name),null); 985 if (val!=null) 986 return Integer.parseInt(val); 987 return -1; 988 } 989 990 991 996 public long getDateField(String name) 997 { 998 String val = valueParameters(get(name),null); 999 if (val==null) 1000 return -1; 1001 1002 if (_dateReceive==null) 1003 { 1004 _dateReceive=(SimpleDateFormat [])__dateReceiveCache.get(); 1005 if (_dateReceive==null) 1006 { 1007 _dateReceive=(SimpleDateFormat []) new SimpleDateFormat [__dateReceiveSource.length]; 1008 __dateReceiveCache.set(_dateReceive); 1009 } 1010 } 1011 1012 for (int i=0;i<_dateReceive.length;i++) 1013 { 1014 if (_dateReceive[i]==null) 1016 _dateReceive[i]=(SimpleDateFormat )__dateReceiveSource[i].clone(); 1017 1018 try{ 1019 Date date=(Date )_dateReceive[i].parseObject(val); 1020 return date.getTime(); 1021 } 1022 catch(java.lang.Exception e) 1023 { 1024 LogSupport.ignore(log,e); 1025 } 1026 } 1027 if (val.endsWith(" GMT")) 1028 { 1029 val=val.substring(0,val.length()-4); 1030 for (int i=0;i<_dateReceive.length;i++) 1031 { 1032 try{ 1033 Date date=(Date )_dateReceive[i].parseObject(val); 1034 return date.getTime(); 1035 } 1036 catch(java.lang.Exception e) 1037 { 1038 LogSupport.ignore(log,e); 1039 } 1040 } 1041 } 1042 1043 throw new IllegalArgumentException (val); 1044 } 1045 1046 1047 1052 public void putIntField(String name, int value) 1053 { 1054 put(name, Integer.toString(value)); 1055 } 1056 1057 1058 1063 public void putDateField(String name, Date date) 1064 { 1065 putDateField(name,date.getTime()); 1066 } 1067 1068 1069 1074 public void addDateField(String name, Date date) 1075 { 1076 addDateField(name,date.getTime()); 1077 } 1078 1079 1080 1085 public void addDateField(String name, long date) 1086 { 1087 if (_dateBuffer==null) 1088 { 1089 _dateBuffer=new StringBuffer (32); 1090 _calendar=new HttpCal(); 1091 } 1092 _dateBuffer.setLength(0); 1093 _calendar.setTimeInMillis(date); 1094 formatDate(_dateBuffer, _calendar, false); 1095 add(name, _dateBuffer.toString()); 1096 } 1097 1098 1099 1104 public void putDateField(String name, long date) 1105 { 1106 if (_dateBuffer==null) 1107 { 1108 _dateBuffer=new StringBuffer (32); 1109 _calendar=new HttpCal(); 1110 } 1111 _dateBuffer.setLength(0); 1112 _calendar.setTimeInMillis(date); 1113 formatDate(_dateBuffer, _calendar, false); 1114 put(name, _dateBuffer.toString()); 1115 } 1116 1117 1118 1120 public void read(LineInput in) 1121 throws IOException 1122 { 1123 Field last=null; 1124 char[] buf=null; 1125 int size=0; 1126 org.mortbay.util.LineInput.LineBuffer line_buffer; 1127 synchronized(in) 1128 { 1129 line: 1130 while ((line_buffer=in.readLineBuffer())!=null) 1131 { 1132 buf=line_buffer.buffer; 1134 size=line_buffer.size; 1135 if (size==0) 1136 break; 1137 1138 int i1=-1; 1140 int i2=-1; 1141 int name_l=0; 1142 int i=0; 1143 char c=buf[0]; 1144 1145 if (c!=' ' && c!='\t') 1147 { 1148 i2=0; 1149 for (i=1;i<size;i++) 1151 { 1152 c=buf[i]; 1153 if (c==':') 1154 { 1155 name_l=i2+1; 1156 break; 1157 } 1158 1159 if (c!=' '&&c!='\t') 1160 i2=i; 1161 } 1162 } 1163 1164 for (i++;i<size;i++) 1166 { 1167 c=buf[i]; 1168 if (c!=' ' && c!='\t') 1169 { 1170 i1=i; 1171 i2=i-1; 1172 break; 1173 } 1174 } 1175 1176 for (i=size;i-->i1 && i>=0;) 1178 { 1179 c=buf[i]; 1180 if (c!=' ' && c!='\t') 1181 { 1182 i2=i; 1183 break; 1184 } 1185 } 1186 1187 if (name_l<=0) 1189 { 1190 if (i1>0 && last!=null) 1191 last._value=last._value+' '+new String (buf,i1,i2-i1+1); 1192 continue; 1193 } 1194 1195 FieldInfo info = getFieldInfo(buf,0,name_l); 1197 Field field=getField(info,false); 1198 last=null; 1199 if (field!=null) 1200 { 1201 while(field!=null && field._version==_version) 1202 { 1203 last=field; 1204 field=field._next; 1205 } 1206 } 1207 1208 if (field!=null) 1209 { 1210 if (i1>=0) 1211 field.reset(buf,i1,i2-i1+1,_version); 1212 else 1213 field.reset("",_version); 1214 } 1215 else 1216 { 1217 if (i1>=0) 1219 field=new Field(info,buf,i1,i2-i1+1,_version); 1220 else 1221 field=new Field(info,"",_version); 1222 1223 if(last!=null) 1225 { 1226 field._prev=last; 1227 last._next=field; 1228 1229 } 1230 else if (info.hashCode()<_index.length) 1231 _index[info.hashCode()]=_fields.size(); 1232 _fields.add(field); 1233 } 1234 1235 last=field; 1236 } 1237 } 1238 } 1239 1240 1241 1242 1244 public void write(Writer writer) 1245 throws IOException 1246 { 1247 synchronized(writer) 1248 { 1249 for (int i=0;i<_fields.size();i++) 1250 { 1251 Field field=(Field)_fields.get(i); 1252 if (field!=null) 1253 field.write(writer,_version); 1254 } 1255 writer.write(__CRLF); 1256 } 1257 } 1258 1259 1260 1261 public String toString() 1262 { 1263 try 1264 { 1265 StringWriter writer = new StringWriter (); 1266 write(writer); 1267 return writer.toString(); 1268 } 1269 catch(Exception e) 1270 {} 1271 return null; 1272 } 1273 1274 1275 1277 public void clear() 1278 { 1279 _version++; 1280 if (_version>1000) 1281 { 1282 _version=0; 1283 for (int i=_fields.size();i-->0;) 1284 { 1285 Field field=(Field)_fields.get(i); 1286 if (field!=null) 1287 field.clear(); 1288 } 1289 } 1290 } 1291 1292 1293 1296 public void destroy() 1297 { 1298 for (int i=_fields.size();i-->0;) 1299 { 1300 Field field=(Field)_fields.get(i); 1301 if (field!=null) 1302 field.destroy(); 1303 } 1304 _fields=null; 1305 _index=null; 1306 _dateBuffer=null; 1307 _calendar=null; 1308 _dateReceive=null; 1309 } 1310 1311 1312 1322 public static String valueParameters(String value, Map parameters) 1323 { 1324 if (value==null) 1325 return null; 1326 1327 int i = value.indexOf(';'); 1328 if (i<0) 1329 return value; 1330 if (parameters==null) 1331 return value.substring(0,i).trim(); 1332 1333 StringTokenizer tok1 = 1334 new QuotedStringTokenizer(value.substring(i),";",false,true); 1335 while(tok1.hasMoreTokens()) 1336 { 1337 String token=tok1.nextToken(); 1338 StringTokenizer tok2 = 1339 new QuotedStringTokenizer(token,"= "); 1340 if (tok2.hasMoreTokens()) 1341 { 1342 String paramName=tok2.nextToken(); 1343 String paramVal=null; 1344 if (tok2.hasMoreTokens()) 1345 paramVal=tok2.nextToken(); 1346 parameters.put(paramName,paramVal); 1347 } 1348 } 1349 1350 return value.substring(0,i).trim(); 1351 } 1352 1353 1354 public static Float getQuality(String value) 1355 { 1356 if (value==null) 1357 return __zero; 1358 1359 int qe=value.indexOf(";"); 1360 if (qe++<0 || qe==value.length()) 1361 return __one; 1362 1363 if (value.charAt(qe++)=='q') 1364 { 1365 qe++; 1366 Map.Entry entry=__qualities.getEntry(value,qe,value.length()-qe); 1367 if (entry!=null) 1368 return (Float )entry.getValue(); 1369 } 1370 1371 HashMap params = new HashMap (3); 1372 valueParameters(value,params); 1373 String qs=(String )params.get("q"); 1374 Float q=(Float )__qualities.get(qs); 1375 if (q==null) 1376 { 1377 try{q=new Float (qs);} 1378 catch(Exception e){q=__one;} 1379 } 1380 return q; 1381 } 1382 1383 1384 1388 public static List qualityList(Enumeration enm) 1389 { 1390 if(enm==null || !enm.hasMoreElements()) 1391 return Collections.EMPTY_LIST; 1392 1393 Object list=null; 1394 Object qual=null; 1395 1396 while(enm.hasMoreElements()) 1398 { 1399 String v=enm.nextElement().toString(); 1400 Float q=getQuality(v); 1401 1402 if (q.floatValue()>=0.001) 1403 { 1404 list=LazyList.add(list,v); 1405 qual=LazyList.add(qual,q); 1406 } 1407 } 1408 1409 List vl=LazyList.getList(list,false); 1410 if (vl.size()<2) 1411 return vl; 1412 1413 List ql=LazyList.getList(qual,false); 1414 1415 Float last=__zero; 1417 for (int i=vl.size();i-->0;) 1418 { 1419 Float q = (Float )ql.get(i); 1420 if (last.compareTo(q)>0) 1421 { 1422 Object tmp=vl.get(i); 1423 vl.set(i,vl.get(i+1)); 1424 vl.set(i+1,tmp); 1425 ql.set(i,ql.get(i+1)); 1426 ql.set(i+1,q); 1427 last=__zero; 1428 i=vl.size(); 1429 continue; 1430 } 1431 last=q; 1432 } 1433 ql.clear(); 1434 return vl; 1435 } 1436 1437 1438 1439 1440 1443 public void addSetCookie(Cookie cookie) 1444 { 1445 String name=cookie.getName(); 1446 String value=cookie.getValue(); 1447 int version=cookie.getVersion(); 1448 1449 if (name==null || name.length()==0) 1451 throw new IllegalArgumentException ("Bad cookie name"); 1452 1453 StringBuffer buf = new StringBuffer (128); 1455 String name_value_params=null; 1456 synchronized(buf) 1457 { 1458 buf.append(name); 1459 buf.append('='); 1460 if (value!=null && value.length()>0) 1461 { 1462 if (version==0) 1463 URI.encodeString(buf,value,"\";, "); 1464 else 1465 buf.append(QuotedStringTokenizer.quote(value,"\";, ")); 1466 } 1467 1468 if (version>0) 1469 { 1470 buf.append(";Version="); 1471 buf.append(version); 1472 String comment=cookie.getComment(); 1473 if (comment!=null && comment.length()>0) 1474 { 1475 buf.append(";Comment="); 1476 QuotedStringTokenizer.quote(buf,comment); 1477 } 1478 } 1479 String path=cookie.getPath(); 1480 if (path!=null && path.length()>0) 1481 { 1482 buf.append(";Path="); 1483 buf.append(path); 1484 } 1485 String domain=cookie.getDomain(); 1486 if (domain!=null && domain.length()>0) 1487 { 1488 buf.append(";Domain="); 1489 buf.append(domain.toLowerCase()); } 1491 long maxAge = cookie.getMaxAge(); 1492 if (maxAge>=0) 1493 { 1494 if (version==0) 1495 { 1496 buf.append(";Expires="); 1497 if (maxAge==0) 1498 buf.append(__01Jan1970); 1499 else 1500 formatDate(buf,System.currentTimeMillis()+1000L*maxAge,true); 1501 } 1502 else 1503 { 1504 buf.append (";Max-Age="); 1505 buf.append (cookie.getMaxAge()); 1506 } 1507 } 1508 else if (version>0) 1509 { 1510 buf.append (";Discard"); 1511 } 1512 if (cookie.getSecure()) 1513 { 1514 buf.append(";Secure"); 1515 } 1516 if (cookie instanceof HttpOnlyCookie) 1517 buf.append(";HttpOnly"); 1518 1519 name_value_params = buf.toString(); 1520 } 1521 put(__Expires,__01Jan1970); 1522 add(__SetCookie,name_value_params); 1523 } 1524 1525 1526 1530 public void add(HttpFields fields) 1531 { 1532 if (fields==null) 1533 return; 1534 1535 Enumeration enm = fields.getFieldNames(); 1536 while( enm.hasMoreElements() ) 1537 { 1538 String name = (String )enm.nextElement(); 1539 Enumeration values = fields.getValues(name); 1540 while(values.hasMoreElements()) 1541 add(name,(String )values.nextElement()); 1542 } 1543 } 1544 1545 1546 1550 public Iterator iterator() {return new EntryIterator();} 1551 1552 1553 1554 1555 public class Entry 1556 { 1557 protected int _i; 1558 1559 Entry(int i) {_i=i;} 1560 public String getKey() {return ((Field)_fields.get(_i)).getDisplayName();} 1561 public String getValue() {return ((Field)_fields.get(_i))._value;} 1562 } 1563 1564 1565 1566 private class EntryIterator implements Iterator 1567 { 1568 protected int _i=0; 1569 public boolean hasNext() {return (_i<_fields.size());} 1570 public Object next() throws NoSuchElementException {return new Entry(_i++);} 1571 public void remove() { throw new UnsupportedOperationException ();} 1572 } 1573 1574 1575 1576 1577 private static class HttpCal extends GregorianCalendar 1578 { 1579 HttpCal() 1580 { 1581 super(__GMT); 1582 } 1583 1584 1585 1588 public void setTimeInMillis(long arg0) 1589 { 1590 super.setTimeInMillis(arg0); 1591 } 1592 1593 1596 public long getTimeInMillis() 1597 { 1598 return super.getTimeInMillis(); 1599 } 1600 } 1601} 1602 | Popular Tags |