Source Code Cross Referenced for HttpCookie.java in  » 6.0-JDK-Core » net » java » net » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » net » java.net 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001        /*
0002         * Copyright 2005 Sun Microsystems, Inc.  All Rights Reserved.
0003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004         *
0005         * This code is free software; you can redistribute it and/or modify it
0006         * under the terms of the GNU General Public License version 2 only, as
0007         * published by the Free Software Foundation.  Sun designates this
0008         * particular file as subject to the "Classpath" exception as provided
0009         * by Sun in the LICENSE file that accompanied this code.
0010         *
0011         * This code is distributed in the hope that it will be useful, but WITHOUT
0012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014         * version 2 for more details (a copy is included in the LICENSE file that
0015         * accompanied this code).
0016         *
0017         * You should have received a copy of the GNU General Public License version
0018         * 2 along with this work; if not, write to the Free Software Foundation,
0019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020         *
0021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022         * CA 95054 USA or visit www.sun.com if you need additional information or
0023         * have any questions.
0024         */
0025
0026        package java.net;
0027
0028        import java.util.List;
0029        import java.util.StringTokenizer;
0030        import java.util.NoSuchElementException;
0031        import java.text.SimpleDateFormat;
0032        import java.util.TimeZone;
0033        import java.util.Date;
0034
0035        import java.lang.NullPointerException; // for javadoc
0036
0037        /**
0038         * An HttpCookie object represents an http cookie, which carries state
0039         * information between server and user agent. Cookie is widely adopted
0040         * to create stateful sessions.
0041         *
0042         * <p>There are 3 http cookie specifications:
0043         * <blockquote>
0044         *   Netscape draft<br>
0045         *   RFC 2109 - <a href="http://www.ietf.org/rfc/rfc2109.txt">
0046         * <i>http://www.ietf.org/rfc/rfc2109.txt</i></a><br>
0047         *   RFC 2965 - <a href="http://www.ietf.org/rfc/rfc2965.txt">
0048         * <i>http://www.ietf.org/rfc/rfc2965.txt</i></a>
0049         * </blockquote>
0050         *
0051         * <p>HttpCookie class can accept all these 3 forms of syntax.
0052         *
0053         * @version 1.11, 07/05/05
0054         * @author Edward Wang
0055         * @since 1.6
0056         */
0057        public final class HttpCookie implements  Cloneable {
0058            /* ---------------- Fields -------------- */
0059
0060            //
0061            // The value of the cookie itself.
0062            //
0063            private String name; // NAME= ... "$Name" style is reserved
0064            private String value; // value of NAME
0065
0066            //
0067            // Attributes encoded in the header's cookie fields.
0068            //
0069
0070            private String comment; // Comment=VALUE ... describes cookie's use
0071            private String commentURL; // CommentURL="http URL" ... describes cookie's use
0072            private boolean toDiscard; // Discard ... discard cookie unconditionally
0073            private String domain; // Domain=VALUE ... domain that sees cookie
0074            private long maxAge = MAX_AGE_UNSPECIFIED; // Max-Age=VALUE ... cookies auto-expire
0075            private String path; // Path=VALUE ... URLs that see the cookie
0076            private String portlist; // Port[="portlist"] ... the port cookie may be returned to
0077            private boolean secure; // Secure ... e.g. use SSL
0078            private int version = 1; // Version=1 ... RFC 2965 style
0079
0080            //
0081            // Hold the creation time (in seconds) of the http cookie for later
0082            // expiration calculation
0083            //
0084            private long whenCreated = 0;
0085
0086            //
0087            // Since the positive and zero max-age have their meanings,
0088            // this value serves as a hint as 'not specify max-age'
0089            //
0090            private final static long MAX_AGE_UNSPECIFIED = -1;
0091
0092            //
0093            // date format used by Netscape's cookie draft
0094            //
0095            private final static String NETSCAPE_COOKIE_DATE_FORMAT = "EEE',' dd-MMM-yyyy HH:mm:ss 'GMT'";
0096
0097            //
0098            // constant strings represent set-cookie header token
0099            //
0100            private final static String SET_COOKIE = "set-cookie:";
0101            private final static String SET_COOKIE2 = "set-cookie2:";
0102
0103            /* ---------------- Ctors -------------- */
0104
0105            /**
0106             * Constructs a cookie with a specified name and value.
0107             *
0108             * <p>The name must conform to RFC 2965. That means it can contain 
0109             * only ASCII alphanumeric characters and cannot contain commas, 
0110             * semicolons, or white space or begin with a $ character. The cookie's
0111             * name cannot be changed after creation.
0112             *
0113             * <p>The value can be anything the server chooses to send. Its
0114             * value is probably of interest only to the server. The cookie's
0115             * value can be changed after creation with the
0116             * <code>setValue</code> method.
0117             *
0118             * <p>By default, cookies are created according to the RFC 2965
0119             * cookie specification. The version can be changed with the 
0120             * <code>setVersion</code> method.
0121             *
0122             *
0123             * @param name 			a <code>String</code> specifying the name of the cookie
0124             *
0125             * @param value			a <code>String</code> specifying the value of the cookie
0126             *
0127             * @throws IllegalArgumentException	if the cookie name contains illegal characters
0128             *					or it is one of the tokens reserved for use
0129             *					by the cookie protocol
0130             * @throws NullPointerException     if <tt>name</tt> is <tt>null</tt>
0131             * @see #setValue
0132             * @see #setVersion
0133             *
0134             */
0135
0136            public HttpCookie(String name, String value) {
0137                name = name.trim();
0138                if (name.length() == 0 || !isToken(name) || isReserved(name)) {
0139                    throw new IllegalArgumentException("Illegal cookie name");
0140                }
0141
0142                this .name = name;
0143                this .value = value;
0144                toDiscard = false;
0145                secure = false;
0146
0147                whenCreated = System.currentTimeMillis();
0148            }
0149
0150            /**
0151             * Constructs cookies from set-cookie or set-cookie2 header string.
0152             * RFC 2965 section 3.2.2 set-cookie2 syntax indicates that one header line
0153             * may contain more than one cookie definitions, so this is a static
0154             * utility method instead of another constructor.
0155             *
0156             * @param header    a <tt>String</tt> specifying the set-cookie header.
0157             *                  The header should start with "set-cookie", or "set-cookie2"
0158             *                  token; or it should have no leading token at all.
0159             * @return          a List of cookie parsed from header line string
0160             * @throws IllegalArgumentException if header string violates the cookie
0161             *                                  specification's syntax, or the cookie
0162             *                                  name contains llegal characters, or
0163             *                                  the cookie name is one of the tokens
0164             *                                  reserved for use by the cookie protocol
0165             * @throws NullPointerException     if the header string is <tt>null</tt>
0166             */
0167            public static List<HttpCookie> parse(String header) {
0168                int version = guessCookieVersion(header);
0169
0170                // if header start with set-cookie or set-cookie2, strip it off
0171                if (startsWithIgnoreCase(header, SET_COOKIE2)) {
0172                    header = header.substring(SET_COOKIE2.length());
0173                } else if (startsWithIgnoreCase(header, SET_COOKIE)) {
0174                    header = header.substring(SET_COOKIE.length());
0175                }
0176
0177                List<HttpCookie> cookies = new java.util.ArrayList<HttpCookie>();
0178                // The Netscape cookie may have a comma in its expires attribute,
0179                // while the comma is the delimiter in rfc 2965/2109 cookie header string.
0180                // so the parse logic is slightly different
0181                if (version == 0) {
0182                    // Netscape draft cookie
0183                    HttpCookie cookie = parseInternal(header);
0184                    cookie.setVersion(0);
0185                    cookies.add(cookie);
0186                } else {
0187                    // rfc2965/2109 cookie
0188                    // if header string contains more than one cookie,
0189                    // it'll separate them with comma
0190                    List<String> cookieStrings = splitMultiCookies(header);
0191                    for (String cookieStr : cookieStrings) {
0192                        HttpCookie cookie = parseInternal(cookieStr);
0193                        cookie.setVersion(1);
0194                        cookies.add(cookie);
0195                    }
0196                }
0197
0198                return cookies;
0199            }
0200
0201            /* ---------------- Public operations -------------- */
0202
0203            /**
0204             * Reports whether this http cookie has expired or not.
0205             *
0206             * @return  <tt>true</tt> to indicate this http cookie has expired;
0207             *          otherwise, <tt>false</tt>
0208             */
0209            public boolean hasExpired() {
0210                if (maxAge == 0)
0211                    return true;
0212
0213                // if not specify max-age, this cookie should be
0214                // discarded when user agent is to be closed, but
0215                // it is not expired.
0216                if (maxAge == MAX_AGE_UNSPECIFIED)
0217                    return false;
0218
0219                long deltaSecond = (System.currentTimeMillis() - whenCreated) / 1000;
0220                if (deltaSecond > maxAge)
0221                    return true;
0222                else
0223                    return false;
0224            }
0225
0226            /**
0227             *
0228             * Specifies a comment that describes a cookie's purpose.
0229             * The comment is useful if the browser presents the cookie 
0230             * to the user. Comments
0231             * are not supported by Netscape Version 0 cookies.
0232             *
0233             * @param purpose		a <code>String</code> specifying the comment 
0234             *				to display to the user
0235             *
0236             * @see #getComment
0237             *
0238             */
0239
0240            public void setComment(String purpose) {
0241                comment = purpose;
0242            }
0243
0244            /**
0245             * Returns the comment describing the purpose of this cookie, or
0246             * <code>null</code> if the cookie has no comment.
0247             *
0248             * @return			a <code>String</code> containing the comment,
0249             *				or <code>null</code> if none
0250             *
0251             * @see #setComment
0252             *
0253             */
0254
0255            public String getComment() {
0256                return comment;
0257            }
0258
0259            /**
0260             *
0261             * Specifies a comment url that describes a cookie's purpose.
0262             * The comment url is useful if the browser presents the cookie 
0263             * to the user. Comment url is RFC 2965 only.
0264             *
0265             * @param purpose		a <code>String</code> specifying the comment url
0266             *				to display to the user
0267             *
0268             * @see #getCommentURL
0269             *
0270             */
0271
0272            public void setCommentURL(String purpose) {
0273                commentURL = purpose;
0274            }
0275
0276            /**
0277             * Returns the comment url describing the purpose of this cookie, or
0278             * <code>null</code> if the cookie has no comment url.
0279             *
0280             * @return			a <code>String</code> containing the comment url,
0281             *				or <code>null</code> if none
0282             *
0283             * @see #setCommentURL
0284             *
0285             */
0286
0287            public String getCommentURL() {
0288                return commentURL;
0289            }
0290
0291            /**
0292             * Specify whether user agent should discard the cookie unconditionally.
0293             * This is RFC 2965 only attribute.
0294             *
0295             * @param discard   <tt>true</tt> indicates to discard cookie unconditionally
0296             *
0297             * @see #getDiscard
0298             */
0299
0300            public void setDiscard(boolean discard) {
0301                toDiscard = discard;
0302            }
0303
0304            /**
0305             * Return the discard attribute of the cookie
0306             *
0307             * @return  a <tt>boolean</tt> to represent this cookie's discard attribute
0308             *
0309             * @see #setDiscard
0310             */
0311
0312            public boolean getDiscard() {
0313                return toDiscard;
0314            }
0315
0316            /**
0317             * Specify the portlist of the cookie, which restricts the port(s)
0318             * to which a cookie may be sent back in a Cookie header.
0319             *
0320             * @param ports     a <tt>String</tt> specify the port list, which is
0321             *                  comma seperated series of digits
0322             * @see #getPortlist
0323             */
0324
0325            public void setPortlist(String ports) {
0326                portlist = ports;
0327            }
0328
0329            /**
0330             * Return the port list attribute of the cookie
0331             *
0332             * @return  a <tt>String</tt> contains the port list
0333             *          or <tt>null</tt> if none
0334             * @see #setPortlist
0335             */
0336
0337            public String getPortlist() {
0338                return portlist;
0339            }
0340
0341            /**
0342             *
0343             * Specifies the domain within which this cookie should be presented.
0344             *
0345             * <p>The form of the domain name is specified by RFC 2965. A domain
0346             * name begins with a dot (<code>.foo.com</code>) and means that
0347             * the cookie is visible to servers in a specified Domain Name System
0348             * (DNS) zone (for example, <code>www.foo.com</code>, but not 
0349             * <code>a.b.foo.com</code>). By default, cookies are only returned
0350             * to the server that sent them.
0351             *
0352             *
0353             * @param pattern		a <code>String</code> containing the domain name
0354             *				within which this cookie is visible;
0355             *				form is according to RFC 2965
0356             *
0357             * @see #getDomain
0358             *
0359             */
0360
0361            public void setDomain(String pattern) {
0362                if (pattern != null)
0363                    domain = pattern.toLowerCase();
0364                else
0365                    domain = pattern;
0366            }
0367
0368            /**
0369             * Returns the domain name set for this cookie. The form of 
0370             * the domain name is set by RFC 2965.
0371             *
0372             * @return			a <code>String</code> containing the domain name
0373             *
0374             * @see #setDomain
0375             *
0376             */
0377
0378            public String getDomain() {
0379                return domain;
0380            }
0381
0382            /**
0383             * Sets the maximum age of the cookie in seconds.
0384             *
0385             * <p>A positive value indicates that the cookie will expire
0386             * after that many seconds have passed. Note that the value is
0387             * the <i>maximum</i> age when the cookie will expire, not the cookie's
0388             * current age.
0389             *
0390             * <p>A negative value means
0391             * that the cookie is not stored persistently and will be deleted
0392             * when the Web browser exits. A zero value causes the cookie
0393             * to be deleted.
0394             *
0395             * @param expiry		an integer specifying the maximum age of the
0396             * 				cookie in seconds; if zero, the cookie
0397             *                          should be discarded immediately;
0398             *                          otherwise, the cookie's max age is unspecified.
0399             *
0400             * @see #getMaxAge
0401             *
0402             */
0403            public void setMaxAge(long expiry) {
0404                maxAge = expiry;
0405            }
0406
0407            /**
0408             * Returns the maximum age of the cookie, specified in seconds.
0409             * By default, <code>-1</code> indicating the cookie will persist
0410             * until browser shutdown.
0411             *
0412             *
0413             * @return			an integer specifying the maximum age of the
0414             *				cookie in seconds
0415             *
0416             *
0417             * @see #setMaxAge
0418             *
0419             */
0420
0421            public long getMaxAge() {
0422                return maxAge;
0423            }
0424
0425            /**
0426             * Specifies a path for the cookie
0427             * to which the client should return the cookie.
0428             *
0429             * <p>The cookie is visible to all the pages in the directory
0430             * you specify, and all the pages in that directory's subdirectories. 
0431             * A cookie's path must include the servlet that set the cookie,
0432             * for example, <i>/catalog</i>, which makes the cookie
0433             * visible to all directories on the server under <i>/catalog</i>.
0434             *
0435             * <p>Consult RFC 2965 (available on the Internet) for more
0436             * information on setting path names for cookies.
0437             *
0438             *
0439             * @param uri		a <code>String</code> specifying a path
0440             *
0441             *
0442             * @see #getPath
0443             *
0444             */
0445
0446            public void setPath(String uri) {
0447                path = uri;
0448            }
0449
0450            /**
0451             * Returns the path on the server 
0452             * to which the browser returns this cookie. The
0453             * cookie is visible to all subpaths on the server.
0454             *
0455             *
0456             * @return		a <code>String</code> specifying a path that contains
0457             *			a servlet name, for example, <i>/catalog</i>
0458             *
0459             * @see #setPath
0460             *
0461             */
0462
0463            public String getPath() {
0464                return path;
0465            }
0466
0467            /**
0468             * Indicates to the browser whether the cookie should only be sent
0469             * using a secure protocol, such as HTTPS or SSL.
0470             *
0471             * <p>The default value is <code>false</code>.
0472             *
0473             * @param flag	if <code>true</code>, sends the cookie from the browser
0474             *			to the server using only when using a secure protocol;
0475             *			if <code>false</code>, sent on any protocol
0476             *
0477             * @see #getSecure
0478             *
0479             */
0480
0481            public void setSecure(boolean flag) {
0482                secure = flag;
0483            }
0484
0485            /**
0486             * Returns <code>true</code> if the browser is sending cookies
0487             * only over a secure protocol, or <code>false</code> if the
0488             * browser can send cookies using any protocol.
0489             *
0490             * @return		<code>true</code> if the browser can use
0491             *			any standard protocol; otherwise, <code>false</code>
0492             *
0493             * @see #setSecure
0494             *
0495             */
0496
0497            public boolean getSecure() {
0498                return secure;
0499            }
0500
0501            /**
0502             * Returns the name of the cookie. The name cannot be changed after
0503             * creation.
0504             *
0505             * @return		a <code>String</code> specifying the cookie's name
0506             *
0507             */
0508
0509            public String getName() {
0510                return name;
0511            }
0512
0513            /**
0514             *
0515             * Assigns a new value to a cookie after the cookie is created.
0516             * If you use a binary value, you may want to use BASE64 encoding.
0517             *
0518             * <p>With Version 0 cookies, values should not contain white 
0519             * space, brackets, parentheses, equals signs, commas,
0520             * double quotes, slashes, question marks, at signs, colons,
0521             * and semicolons. Empty values may not behave the same way
0522             * on all browsers.
0523             *
0524             * @param newValue		a <code>String</code> specifying the new value 
0525             *
0526             *
0527             * @see #getValue
0528             *
0529             */
0530
0531            public void setValue(String newValue) {
0532                value = newValue;
0533            }
0534
0535            /**
0536             * Returns the value of the cookie.
0537             *
0538             * @return			a <code>String</code> containing the cookie's
0539             *				present value
0540             *
0541             * @see #setValue
0542             *
0543             */
0544
0545            public String getValue() {
0546                return value;
0547            }
0548
0549            /**
0550             * Returns the version of the protocol this cookie complies 
0551             * with. Version 1 complies with RFC 2965/2109, 
0552             * and version 0 complies with the original
0553             * cookie specification drafted by Netscape. Cookies provided
0554             * by a browser use and identify the browser's cookie version.
0555             *
0556             *
0557             * @return			0 if the cookie complies with the
0558             *				original Netscape specification; 1
0559             *				if the cookie complies with RFC 2965/2109
0560             *
0561             * @see #setVersion
0562             *
0563             */
0564
0565            public int getVersion() {
0566                return version;
0567            }
0568
0569            /**
0570             * Sets the version of the cookie protocol this cookie complies
0571             * with. Version 0 complies with the original Netscape cookie
0572             * specification. Version 1 complies with RFC 2965/2109.
0573             *
0574             *
0575             * @param v			0 if the cookie should comply with 
0576             *				the original Netscape specification;
0577             *				1 if the cookie should comply with RFC 2965/2109
0578             *
0579             * @throws IllegalArgumentException if <tt>v</tt> is neither 0 nor 1
0580             *
0581             * @see #getVersion
0582             *
0583             */
0584
0585            public void setVersion(int v) {
0586                if (v != 0 && v != 1) {
0587                    throw new IllegalArgumentException(
0588                            "cookie version should be 0 or 1");
0589                }
0590
0591                version = v;
0592            }
0593
0594            /**
0595             * The utility method to check whether a host name is in a domain
0596             * or not.
0597             *
0598             * <p>This concept is described in the cookie specification.
0599             * To understand the concept, some terminologies need to be defined first:
0600             * <blockquote>
0601             * effective host name = hostname if host name contains dot<br>
0602             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;or = hostname.local if not
0603             * </blockquote>
0604             * <p>Host A's name domain-matches host B's if:
0605             * <blockquote><ul>
0606             *   <li>their host name strings string-compare equal; or</li>
0607             *   <li>A is a HDN string and has the form NB, where N is a non-empty
0608             *   name string, B has the form .B', and B' is a HDN string.  (So,
0609             *   x.y.com domain-matches .Y.com but not Y.com.)</li>
0610             * </ul></blockquote>
0611             *
0612             * <p>A host isn't in a domain (RFC 2965 sec. 3.3.2) if:
0613             * <blockquote><ul>
0614             *   <li>The value for the Domain attribute contains no embedded dots,
0615             *   and the value is not .local.</li>
0616             *   <li>The effective host name that derives from the request-host does
0617             *   not domain-match the Domain attribute.</li>
0618             *   <li>The request-host is a HDN (not IP address) and has the form HD,
0619             *   where D is the value of the Domain attribute, and H is a string
0620             *   that contains one or more dots.</li>
0621             * </ul></blockquote>
0622             *
0623             * <p>Examples:
0624             * <blockquote><ul>
0625             *   <li>A Set-Cookie2 from request-host y.x.foo.com for Domain=.foo.com
0626             *   would be rejected, because H is y.x and contains a dot.</li>
0627             *   <li>A Set-Cookie2 from request-host x.foo.com for Domain=.foo.com
0628             *   would be accepted.</li>
0629             *   <li>A Set-Cookie2 with Domain=.com or Domain=.com., will always be
0630             *   rejected, because there is no embedded dot.</li>
0631             *   <li>A Set-Cookie2 with Domain=ajax.com will be accepted, and the
0632             *   value for Domain will be taken to be .ajax.com, because a dot
0633             *   gets prepended to the value.</li>
0634             *   <li>A Set-Cookie2 from request-host example for Domain=.local will
0635             *   be accepted, because the effective host name for the request-
0636             *   host is example.local, and example.local domain-matches .local.</li>
0637             * </ul></blockquote>
0638             *
0639             * @param domain    the domain name to check host name with
0640             * @param host      the host name in question
0641             * @return          <tt>true</tt> if they domain-matches; <tt>false</tt> if not
0642             */
0643            public static boolean domainMatches(String domain, String host) {
0644                if (domain == null || host == null)
0645                    return false;
0646
0647                // if there's no embedded dot in domain and domain is not .local
0648                boolean isLocalDomain = ".local".equalsIgnoreCase(domain);
0649                int embeddedDotInDomain = domain.indexOf('.');
0650                if (embeddedDotInDomain == 0)
0651                    embeddedDotInDomain = domain.indexOf('.', 1);
0652                if (!isLocalDomain
0653                        && (embeddedDotInDomain == -1 || embeddedDotInDomain == domain
0654                                .length() - 1))
0655                    return false;
0656
0657                // if the host name contains no dot and the domain name is .local
0658                int firstDotInHost = host.indexOf('.');
0659                if (firstDotInHost == -1 && isLocalDomain)
0660                    return true;
0661
0662                int domainLength = domain.length();
0663                int lengthDiff = host.length() - domainLength;
0664                if (lengthDiff == 0) {
0665                    // if the host name and the domain name are just string-compare euqal
0666                    return host.equalsIgnoreCase(domain);
0667                } else if (lengthDiff > 0) {
0668                    // need to check H & D component
0669                    String H = host.substring(0, lengthDiff);
0670                    String D = host.substring(lengthDiff);
0671
0672                    return (H.indexOf('.') == -1 && D.equalsIgnoreCase(domain));
0673                } else if (lengthDiff == -1) {
0674                    // if domain is actually .host
0675                    return (domain.charAt(0) == '.' && host
0676                            .equalsIgnoreCase(domain.substring(1)));
0677                }
0678
0679                return false;
0680            }
0681
0682            /**
0683             * Constructs a cookie header string representation of this cookie,
0684             * which is in the format defined by corresponding cookie specification,
0685             * but without the leading "Cookie:" token.
0686             *
0687             * @return  a string form of the cookie. The string has the defined format
0688             */
0689            public String toString() {
0690                if (getVersion() > 0) {
0691                    return toRFC2965HeaderString();
0692                } else {
0693                    return toNetscapeHeaderString();
0694                }
0695            }
0696
0697            /**
0698             * Test the equality of two http cookies.
0699             *
0700             * <p> The result is <tt>true</tt> only if two cookies
0701             * come from same domain (case-insensitive),
0702             * have same name (case-insensitive),
0703             * and have same path (case-sensitive).
0704             *
0705             * @return          <tt>true</tt> if 2 http cookies equal to each other;
0706             *                  otherwise, <tt>false</tt>
0707             */
0708            public boolean equals(Object obj) {
0709                if (obj == this )
0710                    return true;
0711                if (!(obj instanceof  HttpCookie))
0712                    return false;
0713                HttpCookie other = (HttpCookie) obj;
0714
0715                // One http cookie equals to another cookie (RFC 2965 sec. 3.3.3) if:
0716                //   1. they come from same domain (case-insensitive),
0717                //   2. have same name (case-insensitive),
0718                //   3. and have same path (case-sensitive).
0719                return equalsIgnoreCase(getName(), other.getName())
0720                        && equalsIgnoreCase(getDomain(), other.getDomain())
0721                        && equals(getPath(), other.getPath());
0722            }
0723
0724            /**
0725             * Return hash code of this http cookie. The result is the sum of
0726             * hash code value of three significant components of this cookie:
0727             * name, domain, and path.
0728             * That is, the hash code is the value of the expression:
0729             * <blockquote>
0730             * getName().toLowerCase().hashCode()<br>
0731             * + getDomain().toLowerCase().hashCode()<br>
0732             * + getPath().hashCode()
0733             * </blockquote>
0734             *
0735             * @return          this http cookie's hash code
0736             */
0737            public int hashCode() {
0738                int h1 = name.toLowerCase().hashCode();
0739                int h2 = (domain != null) ? domain.toLowerCase().hashCode() : 0;
0740                int h3 = (path != null) ? path.hashCode() : 0;
0741
0742                return h1 + h2 + h3;
0743            }
0744
0745            /**
0746             * Create and return a copy of this object.
0747             *
0748             * @return          a clone of this http cookie
0749             */
0750            public Object clone() {
0751                try {
0752                    return super .clone();
0753                } catch (CloneNotSupportedException e) {
0754                    throw new RuntimeException(e.getMessage());
0755                }
0756            }
0757
0758            /* ---------------- Private operations -------------- */
0759
0760            // Note -- disabled for now to allow full Netscape compatibility
0761            // from RFC 2068, token special case characters
0762            // 
0763            // private static final String tspecials = "()<>@,;:\\\"/[]?={} \t";
0764            private static final String tspecials = ",;";
0765
0766            /*
0767             * Tests a string and returns true if the string counts as a 
0768             * token.
0769             * 
0770             * @param value		the <code>String</code> to be tested
0771             *
0772             * @return			<code>true</code> if the <code>String</code> is
0773             *				a token; <code>false</code> if it is not
0774             */
0775
0776            private static boolean isToken(String value) {
0777                int len = value.length();
0778
0779                for (int i = 0; i < len; i++) {
0780                    char c = value.charAt(i);
0781
0782                    if (c < 0x20 || c >= 0x7f || tspecials.indexOf(c) != -1)
0783                        return false;
0784                }
0785                return true;
0786            }
0787
0788            /*
0789             * @param name      the name to be tested
0790             * @return          <tt>true</tt> if the name is reserved by cookie
0791             *                  specification, <tt>false</tt> if it is not
0792             */
0793            private static boolean isReserved(String name) {
0794                if (name.equalsIgnoreCase("Comment")
0795                        || name.equalsIgnoreCase("CommentURL") // rfc2965 only
0796                        || name.equalsIgnoreCase("Discard") // rfc2965 only
0797                        || name.equalsIgnoreCase("Domain")
0798                        || name.equalsIgnoreCase("Expires") // netscape draft only
0799                        || name.equalsIgnoreCase("Max-Age")
0800                        || name.equalsIgnoreCase("Path")
0801                        || name.equalsIgnoreCase("Port") // rfc2965 only
0802                        || name.equalsIgnoreCase("Secure")
0803                        || name.equalsIgnoreCase("Version")
0804                        || name.charAt(0) == '$') {
0805                    return true;
0806                }
0807
0808                return false;
0809            }
0810
0811            /*
0812             * Parse header string to cookie object.
0813             *
0814             * @param header    header string; should contain only one NAME=VALUE pair
0815             *
0816             * @return          an HttpCookie being extracted
0817             *
0818             * @throws IllegalArgumentException if header string violates the cookie
0819             *                                  specification
0820             */
0821            private static HttpCookie parseInternal(String header) {
0822                HttpCookie cookie = null;
0823                String namevaluePair = null;
0824
0825                StringTokenizer tokenizer = new StringTokenizer(header, ";");
0826
0827                // there should always have at least on name-value pair;
0828                // it's cookie's name
0829                try {
0830                    namevaluePair = tokenizer.nextToken();
0831                    int index = namevaluePair.indexOf('=');
0832                    if (index != -1) {
0833                        String name = namevaluePair.substring(0, index).trim();
0834                        String value = namevaluePair.substring(index + 1)
0835                                .trim();
0836                        cookie = new HttpCookie(name,
0837                                stripOffSurroundingQuote(value));
0838                    } else {
0839                        // no "=" in name-value pair; it's an error
0840                        throw new IllegalArgumentException(
0841                                "Invalid cookie name-value pair");
0842                    }
0843                } catch (NoSuchElementException ignored) {
0844                    throw new IllegalArgumentException(
0845                            "Empty cookie header string");
0846                }
0847
0848                // remaining name-value pairs are cookie's attributes
0849                while (tokenizer.hasMoreTokens()) {
0850                    namevaluePair = tokenizer.nextToken();
0851                    int index = namevaluePair.indexOf('=');
0852                    String name, value;
0853                    if (index != -1) {
0854                        name = namevaluePair.substring(0, index).trim();
0855                        value = namevaluePair.substring(index + 1).trim();
0856                    } else {
0857                        name = namevaluePair.trim();
0858                        value = null;
0859                    }
0860
0861                    // assign attribute to cookie
0862                    assignAttribute(cookie, name, value);
0863                }
0864
0865                return cookie;
0866            }
0867
0868            /*
0869             * assign cookie attribute value to attribute name;
0870             * use a map to simulate method dispatch
0871             */
0872            static interface CookieAttributeAssignor {
0873                public void assign(HttpCookie cookie, String attrName,
0874                        String attrValue);
0875            }
0876
0877            static java.util.Map<String, CookieAttributeAssignor> assignors = null;
0878            static {
0879                assignors = new java.util.HashMap<String, CookieAttributeAssignor>();
0880                assignors.put("comment", new CookieAttributeAssignor() {
0881                    public void assign(HttpCookie cookie, String attrName,
0882                            String attrValue) {
0883                        if (cookie.getComment() == null)
0884                            cookie.setComment(attrValue);
0885                    }
0886                });
0887                assignors.put("commenturl", new CookieAttributeAssignor() {
0888                    public void assign(HttpCookie cookie, String attrName,
0889                            String attrValue) {
0890                        if (cookie.getCommentURL() == null)
0891                            cookie.setCommentURL(attrValue);
0892                    }
0893                });
0894                assignors.put("discard", new CookieAttributeAssignor() {
0895                    public void assign(HttpCookie cookie, String attrName,
0896                            String attrValue) {
0897                        cookie.setDiscard(true);
0898                    }
0899                });
0900                assignors.put("domain", new CookieAttributeAssignor() {
0901                    public void assign(HttpCookie cookie, String attrName,
0902                            String attrValue) {
0903                        if (cookie.getDomain() == null)
0904                            cookie.setDomain(attrValue);
0905                    }
0906                });
0907                assignors.put("max-age", new CookieAttributeAssignor() {
0908                    public void assign(HttpCookie cookie, String attrName,
0909                            String attrValue) {
0910                        try {
0911                            long maxage = Long.parseLong(attrValue);
0912                            if (cookie.getMaxAge() == MAX_AGE_UNSPECIFIED)
0913                                cookie.setMaxAge(maxage);
0914                        } catch (NumberFormatException ignored) {
0915                            throw new IllegalArgumentException(
0916                                    "Illegal cookie max-age attribute");
0917                        }
0918                    }
0919                });
0920                assignors.put("path", new CookieAttributeAssignor() {
0921                    public void assign(HttpCookie cookie, String attrName,
0922                            String attrValue) {
0923                        if (cookie.getPath() == null)
0924                            cookie.setPath(attrValue);
0925                    }
0926                });
0927                assignors.put("port", new CookieAttributeAssignor() {
0928                    public void assign(HttpCookie cookie, String attrName,
0929                            String attrValue) {
0930                        if (cookie.getPortlist() == null)
0931                            cookie.setPortlist(attrValue);
0932                    }
0933                });
0934                assignors.put("secure", new CookieAttributeAssignor() {
0935                    public void assign(HttpCookie cookie, String attrName,
0936                            String attrValue) {
0937                        cookie.setSecure(true);
0938                    }
0939                });
0940                assignors.put("version", new CookieAttributeAssignor() {
0941                    public void assign(HttpCookie cookie, String attrName,
0942                            String attrValue) {
0943                        try {
0944                            int version = Integer.parseInt(attrValue);
0945                            cookie.setVersion(version);
0946                        } catch (NumberFormatException ignored) {
0947                            throw new IllegalArgumentException(
0948                                    "Illegal cookie version attribute");
0949                        }
0950                    }
0951                });
0952                assignors.put("expires", new CookieAttributeAssignor() { // Netscape only
0953                            public void assign(HttpCookie cookie,
0954                                    String attrName, String attrValue) {
0955                                if (cookie.getMaxAge() == MAX_AGE_UNSPECIFIED) {
0956                                    cookie
0957                                            .setMaxAge(cookie
0958                                                    .expiryDate2DeltaSeconds(attrValue));
0959                                }
0960                            }
0961                        });
0962            }
0963
0964            private static void assignAttribute(HttpCookie cookie,
0965                    String attrName, String attrValue) {
0966                // strip off the surrounding "-sign if there's any
0967                attrValue = stripOffSurroundingQuote(attrValue);
0968
0969                CookieAttributeAssignor assignor = assignors.get(attrName
0970                        .toLowerCase());
0971                if (assignor != null) {
0972                    assignor.assign(cookie, attrName, attrValue);
0973                } else {
0974                    // must be an error
0975                    throw new IllegalArgumentException(
0976                            "Illegal cookie attribute");
0977                }
0978            }
0979
0980            /*
0981             * Constructs a string representation of this cookie. The string format is
0982             * as Netscape spec, but without leading "Cookie:" token.
0983             */
0984            private String toNetscapeHeaderString() {
0985                StringBuilder sb = new StringBuilder();
0986
0987                sb.append(getName() + "=" + getValue());
0988
0989                return sb.toString();
0990            }
0991
0992            /*
0993             * Constructs a string representation of this cookie. The string format is
0994             * as RFC 2965/2109, but without leading "Cookie:" token.
0995             */
0996            private String toRFC2965HeaderString() {
0997                StringBuilder sb = new StringBuilder();
0998
0999                sb.append(getName()).append("=\"").append(getValue()).append(
1000                        '"');
1001                if (getPath() != null)
1002                    sb.append(";$Path=\"").append(getPath()).append('"');
1003                if (getDomain() != null)
1004                    sb.append(";$Domain=\"").append(getDomain()).append('"');
1005                if (getPortlist() != null)
1006                    sb.append(";$Port=\"").append(getPortlist()).append('"');
1007
1008                return sb.toString();
1009            }
1010
1011            /*
1012             * @param dateString        a date string in format of
1013             *                          "EEE',' dd-MMM-yyyy HH:mm:ss 'GMT'",
1014             *                          which defined in Netscape cookie spec
1015             *
1016             * @return                  delta seconds between this cookie's creation
1017             *                          time and the time specified by dateString
1018             */
1019            private long expiryDate2DeltaSeconds(String dateString) {
1020                SimpleDateFormat df = new SimpleDateFormat(
1021                        NETSCAPE_COOKIE_DATE_FORMAT);
1022                df.setTimeZone(TimeZone.getTimeZone("GMT"));
1023
1024                try {
1025                    Date date = df.parse(dateString);
1026                    return (date.getTime() - whenCreated) / 1000;
1027                } catch (Exception e) {
1028                    return 0;
1029                }
1030            }
1031
1032            /*
1033             * try to guess the cookie version through set-cookie header string
1034             */
1035            private static int guessCookieVersion(String header) {
1036                int version = 0;
1037
1038                header = header.toLowerCase();
1039                if (header.indexOf("expires=") != -1) {
1040                    // only netscape cookie using 'expires'
1041                    version = 0;
1042                } else if (header.indexOf("version=") != -1) {
1043                    // version is mandatory for rfc 2965/2109 cookie
1044                    version = 1;
1045                } else if (header.indexOf("max-age") != -1) {
1046                    // rfc 2965/2109 use 'max-age'
1047                    version = 1;
1048                } else if (startsWithIgnoreCase(header, SET_COOKIE2)) {
1049                    // only rfc 2965 cookie starts with 'set-cookie2'
1050                    version = 1;
1051                }
1052
1053                return version;
1054            }
1055
1056            private static String stripOffSurroundingQuote(String str) {
1057                if (str != null && str.length() > 0 && str.charAt(0) == '"'
1058                        && str.charAt(str.length() - 1) == '"') {
1059                    return str.substring(1, str.length() - 1);
1060                } else {
1061                    return str;
1062                }
1063            }
1064
1065            private static boolean equalsIgnoreCase(String s, String t) {
1066                if (s == t)
1067                    return true;
1068                if ((s != null) && (t != null)) {
1069                    return s.equalsIgnoreCase(t);
1070                }
1071                return false;
1072            }
1073
1074            private static boolean equals(String s, String t) {
1075                if (s == t)
1076                    return true;
1077                if ((s != null) && (t != null)) {
1078                    return s.equals(t);
1079                }
1080                return false;
1081            }
1082
1083            private static boolean startsWithIgnoreCase(String s, String start) {
1084                if (s == null || start == null)
1085                    return false;
1086
1087                if (s.length() >= start.length()
1088                        && start.equalsIgnoreCase(s
1089                                .substring(0, start.length()))) {
1090                    return true;
1091                }
1092
1093                return false;
1094            }
1095
1096            /*
1097             * Split cookie header string according to rfc 2965:
1098             *   1) split where it is a comma;
1099             *   2) but not the comma surrounding by double-quotes, which is the comma
1100             *      inside port list or embeded URIs.
1101             *
1102             * @param header            the cookie header string to split
1103             *
1104             * @return                  list of strings; never null
1105             *
1106             */
1107            private static List<String> splitMultiCookies(String header) {
1108                List<String> cookies = new java.util.ArrayList<String>();
1109                int quoteCount = 0;
1110                int p, q;
1111
1112                for (p = 0, q = 0; p < header.length(); p++) {
1113                    char c = header.charAt(p);
1114                    if (c == '"')
1115                        quoteCount++;
1116                    if (c == ',' && (quoteCount % 2 == 0)) { // it is comma and not surrounding by double-quotes
1117                        cookies.add(header.substring(q, p));
1118                        q = p + 1;
1119                    }
1120                }
1121
1122                cookies.add(header.substring(q));
1123
1124                return cookies;
1125            }
1126        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.