You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2006/06/26 00:34:09 UTC

svn commit: r417083 - in /jakarta/httpcomponents/httpclient/trunk/src: java/org/apache/http/cookie/impl/RFC2109Spec.java test/org/apache/http/cookie/impl/TestAllCookieImpl.java test/org/apache/http/cookie/impl/TestCookieRFC2109Spec.java

Author: olegk
Date: Sun Jun 25 15:34:09 2006
New Revision: 417083

URL: http://svn.apache.org/viewvc?rev=417083&view=rev
Log:
Refactoring of the RFC2109 cookie draft spec

Added:
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/cookie/impl/RFC2109Spec.java
      - copied, changed from r415072, jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/cookie/RFC2109Spec.java
    jakarta/httpcomponents/httpclient/trunk/src/test/org/apache/http/cookie/impl/TestCookieRFC2109Spec.java
      - copied, changed from r417040, jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/cookie/TestCookieRFC2109Spec.java
Modified:
    jakarta/httpcomponents/httpclient/trunk/src/test/org/apache/http/cookie/impl/TestAllCookieImpl.java

Copied: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/cookie/impl/RFC2109Spec.java (from r415072, jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/cookie/RFC2109Spec.java)
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/cookie/impl/RFC2109Spec.java?p2=jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/cookie/impl/RFC2109Spec.java&p1=jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/cookie/RFC2109Spec.java&r1=415072&r2=417083&rev=417083&view=diff
==============================================================================
--- jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/cookie/RFC2109Spec.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/cookie/impl/RFC2109Spec.java Sun Jun 25 15:34:09 2006
@@ -1,11 +1,11 @@
 /*
- * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/cookie/RFC2109Spec.java,v 1.21 2004/06/05 16:49:20 olegk Exp $
+ * $HeadRL$
  * $Revision$
  * $Date$
  * 
  * ====================================================================
  *
- *  Copyright 2002-2004 The Apache Software Foundation
+ *  Copyright 2002-2006 The Apache Software Foundation
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -27,14 +27,21 @@
  *
  */
 
-package org.apache.commons.httpclient.cookie;
+package org.apache.http.cookie.impl;
 
-import org.apache.commons.httpclient.NameValuePair;
-import org.apache.commons.httpclient.Cookie;
-import org.apache.commons.httpclient.util.ParameterFormatter;
+import java.util.Arrays;
+
+import org.apache.http.Header;
+import org.apache.http.HeaderElement;
+import org.apache.http.cookie.Cookie;
+import org.apache.http.cookie.CookieOrigin;
+import org.apache.http.cookie.CookiePathComparator;
+import org.apache.http.cookie.MalformedCookieException;
+import org.apache.http.io.CharArrayBuffer;
+import org.apache.http.util.DateUtils;
 
 /**
- * <p>RFC 2109 specific cookie management functions
+ * RFC 2109 compliant cookie policy
  *
  * @author  B.C. Holmes
  * @author <a href="mailto:jericho@thinkfree.com">Park, Sung-Gu</a>
@@ -44,7 +51,7 @@
  * @author Sean C. Sullivan
  * @author <a href="mailto:JEvans@Cyveillance.com">John Evans</a>
  * @author Marc A. Saegesser
- * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
  * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
  * 
  * @since 2.0 
@@ -52,240 +59,148 @@
 
 public class RFC2109Spec extends CookieSpecBase {
 
-    private final ParameterFormatter formatter;
-
-    /**
-     * Cookie Response Header  name for cookies processed
-     * by this spec.
-     */
-    public static String SET_COOKIE_KEY = "set-cookie";
-
+    private final static CookiePathComparator PATH_COMPARATOR = new CookiePathComparator(); 
+    
+    private boolean oneHeader = false;
+    
     /** Default constructor */
-    public RFC2109Spec() {
+    public RFC2109Spec(boolean oneHeader) {
         super();
-        this.formatter = new ParameterFormatter();
-        this.formatter.setAlwaysUseQuotes(true);
+        registerAttribHandler("version", new RFC2109VersionHandler());
+        registerAttribHandler("path", new BasicPathHandler());
+        registerAttribHandler("domain", new RFC2109DomainHandler());
+        registerAttribHandler("max-age", new BasicMaxAgeHandler());
+        registerAttribHandler("secure", new BasicSecureHandler());
+        registerAttribHandler("comment", new BasicCommentHandler());
+        registerAttribHandler("expires", new BasicExpiresHandler(
+                new String[] {
+                        DateUtils.PATTERN_RFC1123,
+                        DateUtils.PATTERN_RFC1036,
+                        DateUtils.PATTERN_ASCTIME}));
+        this.oneHeader = oneHeader;
     }
 
-    /**
-      * Parse RFC 2109 specific cookie attribute and update the corresponsing
-      * {@link Cookie} properties.
-      *
-      * @param attribute {@link NameValuePair} cookie attribute from the
-      * <tt>Set- Cookie</tt>
-      * @param cookie {@link Cookie} to be updated
-      * @throws MalformedCookieException if an exception occurs during parsing
-      */
-    public void parseAttribute(
-        final NameValuePair attribute, final Cookie cookie)
-        throws MalformedCookieException {
-          
-        if (attribute == null) {
-            throw new IllegalArgumentException("Attribute may not be null.");
-        }
-        if (cookie == null) {
-            throw new IllegalArgumentException("Cookie may not be null.");
+    /** Default constructor */
+    public RFC2109Spec() {
+        this(false);
+    }
+    
+    public Cookie[] parse(final Header header, final CookieOrigin origin) 
+            throws MalformedCookieException {
+        if (header == null) {
+            throw new IllegalArgumentException("Header may not be null");
         }
-        final String paramName = attribute.getName().toLowerCase();
-        final String paramValue = attribute.getValue();
-
-        if (paramName.equals("path")) {
-            if (paramValue == null) {
-                throw new MalformedCookieException(
-                    "Missing value for path attribute");
-            }
-            if (paramValue.trim().equals("")) {
-                throw new MalformedCookieException(
-                    "Blank value for path attribute");
-            }
-            cookie.setPath(paramValue);
-            cookie.setPathAttributeSpecified(true);
-        } else if (paramName.equals("version")) {
-
-            if (paramValue == null) {
-                throw new MalformedCookieException(
-                    "Missing value for version attribute");
-            }
-            try {
-               cookie.setVersion(Integer.parseInt(paramValue));
-            } catch (NumberFormatException e) {
-                throw new MalformedCookieException("Invalid version: " 
-                    + e.getMessage());
-            }
-
-        } else {
-            super.parseAttribute(attribute, cookie);
+        if (origin == null) {
+            throw new IllegalArgumentException("Cookie origin may not be null");
         }
+        HeaderElement[] elems = header.getElements();
+        return parse(elems, origin);
     }
 
-    /**
-      * Performs RFC 2109 compliant {@link Cookie} validation
-      *
-      * @param host the host from which the {@link Cookie} was received
-      * @param port the port from which the {@link Cookie} was received
-      * @param path the path from which the {@link Cookie} was received
-      * @param secure <tt>true</tt> when the {@link Cookie} was received using a
-      * secure connection
-      * @param cookie The cookie to validate
-      * @throws MalformedCookieException if an exception occurs during
-      * validation
-      */
-    public void validate(String host, int port, String path, 
-        boolean secure, final Cookie cookie) throws MalformedCookieException {
-            
-        LOG.trace("enter RFC2109Spec.validate(String, int, String, "
-            + "boolean, Cookie)");
-            
-        // Perform generic validation
-        super.validate(host, port, path, secure, cookie);
-        // Perform RFC 2109 specific validation
-        
-        if (cookie.getName().indexOf(' ') != -1) {
+    public void validate(final Cookie cookie, final CookieOrigin origin) 
+            throws MalformedCookieException {
+        if (cookie == null) {
+            throw new IllegalArgumentException("Cookie may not be null");
+        }
+        String name = cookie.getName();
+        if (name.indexOf(' ') != -1) {
             throw new MalformedCookieException("Cookie name may not contain blanks");
         }
-        if (cookie.getName().startsWith("$")) {
+        if (name.startsWith("$")) {
             throw new MalformedCookieException("Cookie name may not start with $");
         }
-        
-        if (cookie.isDomainAttributeSpecified() 
-            && (!cookie.getDomain().equals(host))) {
-                
-            // domain must start with dot
-            if (!cookie.getDomain().startsWith(".")) {
-                throw new MalformedCookieException("Domain attribute \"" 
-                    + cookie.getDomain() 
-                    + "\" violates RFC 2109: domain must start with a dot");
-            }
-            // domain must have at least one embedded dot
-            int dotIndex = cookie.getDomain().indexOf('.', 1);
-            if (dotIndex < 0 || dotIndex == cookie.getDomain().length() - 1) {
-                throw new MalformedCookieException("Domain attribute \"" 
-                    + cookie.getDomain() 
-                    + "\" violates RFC 2109: domain must contain an embedded dot");
-            }
-            host = host.toLowerCase();
-            if (!host.endsWith(cookie.getDomain())) {
-                throw new MalformedCookieException(
-                    "Illegal domain attribute \"" + cookie.getDomain() 
-                    + "\". Domain of origin: \"" + host + "\"");
-            }
-            // host minus domain may not contain any dots
-            String hostWithoutDomain = host.substring(0, host.length() 
-                - cookie.getDomain().length());
-            if (hostWithoutDomain.indexOf('.') != -1) {
-                throw new MalformedCookieException("Domain attribute \"" 
-                    + cookie.getDomain() 
-                    + "\" violates RFC 2109: host minus domain may not contain any dots");
-            }
-        }
+        super.validate(cookie, origin);
     }
 
-    /**
-     * Performs domain-match as defined by the RFC2109.
-     * @param host The target host.
-     * @param domain The cookie domain attribute.
-     * @return true if the specified host matches the given domain.
-     * 
-     * @since 3.0
-     */
-    public boolean domainMatch(String host, String domain) {
-        boolean match = host.equals(domain) 
-            || (domain.startsWith(".") && host.endsWith(domain));
+    public Header[] formatCookies(final Cookie[] cookies) {
+        if (cookies == null) {
+            throw new IllegalArgumentException("Cookie array may not be null");
+        }
+        if (cookies.length == 0) {
+            throw new IllegalArgumentException("Cookie array may not be empty");
+        }
+        Arrays.sort(cookies, PATH_COMPARATOR);
+        if (this.oneHeader) {
+            return doFormatOneHeader(cookies);
+        } else {
+            return doFormatManyHeaders(cookies);
+        }
+    }
 
-        return match;
+    private Header[] doFormatOneHeader(final Cookie[] cookies) {
+        int version = Integer.MAX_VALUE;
+        // Pick the lowerest common denominator
+        for (int i = 0; i < cookies.length; i++) {
+            Cookie cookie = cookies[i];
+            if (cookie.getVersion() < version) {
+                version = cookie.getVersion();
+            }
+        }
+        CharArrayBuffer buffer = new CharArrayBuffer(40 * cookies.length);
+        formatParamAsVer(buffer, "$Version", Integer.toString(version), version);
+        for (int i = 0; i < cookies.length; i++) {
+            buffer.append("; ");
+            Cookie cookie = cookies[i];
+            formatCookieAsVer(buffer, cookie, version);
+        }
+        return new Header[] {new Header("Cookie", buffer.toString())};
     }
 
+    private Header[] doFormatManyHeaders(final Cookie[] cookies) {
+        Header[] headers = new Header[cookies.length]; 
+        for (int i = 0; i < cookies.length; i++) {
+            Cookie cookie = cookies[i];
+            int version = cookie.getVersion();
+            CharArrayBuffer buffer = new CharArrayBuffer(40);
+            formatParamAsVer(buffer, "$Version", Integer.toString(version), version);
+            buffer.append("; ");
+            formatCookieAsVer(buffer, cookies[i], version);
+            headers[i] = new Header("Cookie", buffer.toString());
+        }
+        return headers;
+    }
+    
     /**
      * Return a name/value string suitable for sending in a <tt>"Cookie"</tt>
      * header as defined in RFC 2109 for backward compatibility with cookie
      * version 0
-     * @param buffer The string buffer to use for output
+     * @param buffer The char array buffer to use for output
      * @param param The parameter.
      * @param version The cookie version 
      */
-    private void formatParam(final StringBuffer buffer, final NameValuePair param, int version) {
-        if (version < 1) {
-            buffer.append(param.getName());
-            buffer.append("=");
-            if (param.getValue() != null) {
-                buffer.append(param.getValue());   
+    private void formatParamAsVer(final CharArrayBuffer buffer, 
+            final String name, final String value, int version) {
+        buffer.append(name);
+        buffer.append("=");
+        if (value != null) {
+            if (version > 0) {
+                buffer.append('\"');
+                buffer.append(value);
+                buffer.append('\"');
+            } else {
+                buffer.append(value);
             }
-        } else {
-            this.formatter.format(buffer, param);
         }
     }
 
     /**
      * Return a string suitable for sending in a <tt>"Cookie"</tt> header 
      * as defined in RFC 2109 for backward compatibility with cookie version 0
-     * @param buffer The string buffer to use for output
+     * @param buffer The char array buffer to use for output
      * @param cookie The {@link Cookie} to be formatted as string
      * @param version The version to use.
      */
-    private void formatCookieAsVer(final StringBuffer buffer, final Cookie cookie, int version) {
-        String value = cookie.getValue();
-        if (value == null) {
-            value = "";
-        }
-        formatParam(buffer, new NameValuePair(cookie.getName(), value), version);
-        if ((cookie.getPath() != null) && cookie.isPathAttributeSpecified()) {
-          buffer.append("; ");
-          formatParam(buffer, new NameValuePair("$Path", cookie.getPath()), version);
-        }
-        if ((cookie.getDomain() != null) 
-            && cookie.isDomainAttributeSpecified()) {
+    private void formatCookieAsVer(final CharArrayBuffer buffer, 
+            final Cookie cookie, int version) {
+        formatParamAsVer(buffer, cookie.getName(), cookie.getValue(), version);
+        if (cookie.getPath() != null && cookie.isPathAttributeSpecified()) {
             buffer.append("; ");
-            formatParam(buffer, new NameValuePair("$Domain", cookie.getDomain()), version);
-        }
-    }
-
-    /**
-     * Return a string suitable for sending in a <tt>"Cookie"</tt> header as
-     * defined in RFC 2109
-     * @param cookie a {@link Cookie} to be formatted as string
-     * @return a string suitable for sending in a <tt>"Cookie"</tt> header.
-     */
-    public String formatCookie(Cookie cookie) {
-        LOG.trace("enter RFC2109Spec.formatCookie(Cookie)");
-        if (cookie == null) {
-            throw new IllegalArgumentException("Cookie may not be null");
+            formatParamAsVer(buffer, "$Path", cookie.getPath(), version);
         }
-        int version = cookie.getVersion();
-        StringBuffer buffer = new StringBuffer();
-        formatParam(buffer, 
-                new NameValuePair("$Version", Integer.toString(version)), 
-                version);
-        buffer.append("; ");
-        formatCookieAsVer(buffer, cookie, version);
-        return buffer.toString();
-    }
-
-    /**
-     * Create a RFC 2109 compliant <tt>"Cookie"</tt> header value containing all
-     * {@link Cookie}s in <i>cookies</i> suitable for sending in a <tt>"Cookie"
-     * </tt> header
-     * @param cookies an array of {@link Cookie}s to be formatted
-     * @return a string suitable for sending in a Cookie header.
-     */
-    public String formatCookies(Cookie[] cookies) {
-        LOG.trace("enter RFC2109Spec.formatCookieHeader(Cookie[])");
-        int version = Integer.MAX_VALUE;
-        // Pick the lowerest common denominator
-        for (int i = 0; i < cookies.length; i++) {
-            Cookie cookie = cookies[i];
-            if (cookie.getVersion() < version) {
-                version = cookie.getVersion();
-            }
-        }
-        final StringBuffer buffer = new StringBuffer();
-        formatParam(buffer, 
-                new NameValuePair("$Version", Integer.toString(version)), 
-                version);
-        for (int i = 0; i < cookies.length; i++) {
+        if (cookie.getDomain() != null && cookie.isDomainAttributeSpecified()) {
             buffer.append("; ");
-            formatCookieAsVer(buffer, cookies[i], version);
+            formatParamAsVer(buffer, "$Domain", cookie.getDomain(), version);
         }
-        return buffer.toString();
     }
-
+    
 }

Modified: jakarta/httpcomponents/httpclient/trunk/src/test/org/apache/http/cookie/impl/TestAllCookieImpl.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/test/org/apache/http/cookie/impl/TestAllCookieImpl.java?rev=417083&r1=417082&r2=417083&view=diff
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/test/org/apache/http/cookie/impl/TestAllCookieImpl.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/src/test/org/apache/http/cookie/impl/TestAllCookieImpl.java Sun Jun 25 15:34:09 2006
@@ -44,6 +44,7 @@
         suite.addTest(TestRFC2109CookieAttribHandlers.suite());
         suite.addTest(TestBrowserCompatSpec.suite());
         suite.addTest(TestCookieNetscapeDraft.suite());
+        suite.addTest(TestCookieRFC2109Spec.suite());
         return suite;
     }
 

Copied: jakarta/httpcomponents/httpclient/trunk/src/test/org/apache/http/cookie/impl/TestCookieRFC2109Spec.java (from r417040, jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/cookie/TestCookieRFC2109Spec.java)
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/test/org/apache/http/cookie/impl/TestCookieRFC2109Spec.java?p2=jakarta/httpcomponents/httpclient/trunk/src/test/org/apache/http/cookie/impl/TestCookieRFC2109Spec.java&p1=jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/cookie/TestCookieRFC2109Spec.java&r1=417040&r2=417083&rev=417083&view=diff
==============================================================================
--- jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/cookie/TestCookieRFC2109Spec.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/src/test/org/apache/http/cookie/impl/TestCookieRFC2109Spec.java Sun Jun 25 15:34:09 2006
@@ -1,10 +1,10 @@
 /*
- * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/test/org/apache/commons/httpclient/cookie/TestCookieRFC2109Spec.java,v 1.3 2004/06/05 16:49:20 olegk Exp $
+ * $HeadURL$
  * $Revision$
  * $Date$
  * ====================================================================
  *
- *  Copyright 1999-2004 The Apache Software Foundation
+ *  Copyright 1999-2006 The Apache Software Foundation
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -26,23 +26,26 @@
  *
  */
 
-package org.apache.commons.httpclient.cookie;
+package org.apache.http.cookie.impl;
+
+import org.apache.http.Header;
+import org.apache.http.cookie.Cookie;
+import org.apache.http.cookie.CookieOrigin;
+import org.apache.http.cookie.CookieSpec;
+import org.apache.http.cookie.MalformedCookieException;
 
 import junit.framework.Test;
+import junit.framework.TestCase;
 import junit.framework.TestSuite;
 
-import org.apache.commons.httpclient.Cookie;
-import org.apache.commons.httpclient.Header;
-import org.apache.commons.httpclient.NameValuePair;
-
 /**
  * Test cases for RFC2109 cookie spec
  *
- * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
  * 
  * @version $Revision$
  */
-public class TestCookieRFC2109Spec extends TestCookieBase {
+public class TestCookieRFC2109Spec extends TestCase {
 
 
     // ------------------------------------------------------------ Constructor
@@ -57,69 +60,15 @@
         return new TestSuite(TestCookieRFC2109Spec.class);
     }
 
-    public void testParseAttributeInvalidAttrib() throws Exception {
-        CookieSpec cookiespec = new RFC2109Spec();
-        try {
-            cookiespec.parseAttribute(null, null);
-            fail("IllegalArgumentException must have been thrown");
-        } catch (IllegalArgumentException expected) {
-        }
-    }
-
-    public void testParseAttributeInvalidCookie() throws Exception {
-        CookieSpec cookiespec = new RFC2109Spec();
-        try {
-            cookiespec.parseAttribute(new NameValuePair("name", "value"), null);
-            fail("IllegalArgumentException must have been thrown");
-        } catch (IllegalArgumentException expected) {
-        }
-    }
-
-    public void testParseAttributeNullPath() throws Exception {
-        CookieSpec cookiespec = new RFC2109Spec();
-        try {
-            Cookie cookie = new Cookie();
-            cookiespec.parseAttribute(new NameValuePair("path", null), cookie);
-            fail("MalformedCookieException must have been thrown");
-        } catch (MalformedCookieException expected) {
-        }
-    }
-
-    public void testParseAttributeBlankPath() throws Exception {
-        CookieSpec cookiespec = new RFC2109Spec();
-        try {
-            Cookie cookie = new Cookie();
-            cookiespec.parseAttribute(new NameValuePair("path", "   "), cookie);
-            fail("MalformedCookieException must have been thrown");
-        } catch (MalformedCookieException expected) {
-        }
-    }
-
-    public void testParseAttributeNullVersion() throws Exception {
-        CookieSpec cookiespec = new RFC2109Spec();
-        try {
-            Cookie cookie = new Cookie();
-            cookiespec.parseAttribute(new NameValuePair("version", null), cookie);
-            fail("MalformedCookieException must have been thrown");
-        } catch (MalformedCookieException expected) {
-        }
-    }
-
-    public void testParseAttributeInvalidVersion() throws Exception {
-        CookieSpec cookiespec = new RFC2109Spec();
-        try {
-            Cookie cookie = new Cookie();
-            cookiespec.parseAttribute(new NameValuePair("version", "nonsense"), cookie);
-            fail("MalformedCookieException must have been thrown");
-        } catch (MalformedCookieException expected) {
-        }
-    }
-
     public void testParseVersion() throws Exception {
         Header header = new Header("Set-Cookie","cookie-name=cookie-value; version=1");
 
         CookieSpec cookiespec = new RFC2109Spec();
-        Cookie[] parsed = cookieParse(cookiespec, "127.0.0.1", 80, "/", false, header);
+        CookieOrigin origin = new CookieOrigin("127.0.0.1", 80, "/", false);
+        Cookie[] parsed = cookiespec.parse(header, origin);
+        for (int i = 0; i < parsed.length; i++) {
+            cookiespec.validate(parsed[i], origin);
+        }
         assertEquals("Found 1 cookie.",1,parsed.length);
         assertEquals("Name","cookie-name",parsed[0].getName());
         assertEquals("Value","cookie-value",parsed[0].getValue());
@@ -134,7 +83,11 @@
             "cookie-name=cookie-value; domain=www.b.com; version=1");
 
         CookieSpec cookiespec = new RFC2109Spec();
-        Cookie[] parsed = cookieParse(cookiespec, "www.b.com", 80, "/", false, header);
+        CookieOrigin origin = new CookieOrigin("www.b.com", 80, "/", false);
+        Cookie[] parsed = cookiespec.parse(header, origin);
+        for (int i = 0; i < parsed.length; i++) {
+            cookiespec.validate(parsed[i], origin);
+        }
         assertNotNull(parsed);
         assertEquals(1, parsed.length);
         assertEquals("www.b.com", parsed[0].getDomain());
@@ -148,8 +101,12 @@
             "cookie-name=cookie-value; domain=a.b.com; version=1");
 
         CookieSpec cookiespec = new RFC2109Spec();
+        CookieOrigin origin = new CookieOrigin("www.a.b.com", 80, "/", false);
         try {
-            Cookie[] parsed = cookieParse(cookiespec, "www.a.b.com", 80, "/", false, header);
+            Cookie[] parsed = cookiespec.parse(header, origin);
+            for (int i = 0; i < parsed.length; i++) {
+                cookiespec.validate(parsed[i], origin);
+            }
             fail("MalformedCookieException should have been thrown");
         } catch (MalformedCookieException e) {
             // expected
@@ -164,28 +121,17 @@
             "cookie-name=cookie-value; domain=.com; version=1");
 
         CookieSpec cookiespec = new RFC2109Spec();
+        CookieOrigin origin = new CookieOrigin("b.com", 80, "/", false);
         try {
-            Cookie[] parsed = cookieParse(cookiespec, "b.com", 80, "/", false, header);
+            Cookie[] parsed = cookiespec.parse(header, origin);
+            for (int i = 0; i < parsed.length; i++) {
+                cookiespec.validate(parsed[i], origin);
+            }
             fail("MalformedCookieException should have been thrown");
         } catch (MalformedCookieException e) {
             // expected
         }
     }
-    /**
-     * Domain must have alt least one embedded dot
-     */
-    public void testParseWithIllegalDomain3() throws Exception {
-        Header header = new Header("Set-Cookie",
-            "cookie-name=cookie-value; domain=.com.; version=1");
-
-        CookieSpec cookiespec = new RFC2109Spec();
-        try {
-            Cookie[] parsed = cookieParse(cookiespec, "b.com", 80, "/", false, header);
-            fail("HttpException exception should have been thrown");
-        } catch (MalformedCookieException e) {
-            // expected
-        }
-    }
 
     /**
      * Host minus domain may not contain any dots
@@ -195,8 +141,12 @@
             "cookie-name=cookie-value; domain=.c.com; version=1");
 
         CookieSpec cookiespec = new RFC2109Spec();
+        CookieOrigin origin = new CookieOrigin("a.b.c.com", 80, "/", false);
         try {
-            Cookie[] parsed = cookieParse(cookiespec, "a.b.c.com", 80, "/", false, header);
+            Cookie[] parsed = cookiespec.parse(header, origin);
+            for (int i = 0; i < parsed.length; i++) {
+                cookiespec.validate(parsed[i], origin);
+            }
             fail("MalformedCookieException should have been thrown");
         } catch (MalformedCookieException e) {
             // expected
@@ -209,13 +159,16 @@
      * browser compatibility mode.
      */
     public void testSecondDomainLevelCookie() throws Exception {
-        Cookie cookie = new Cookie(".sourceforge.net", "name", null, "/", null, false); 
+        Cookie cookie = new Cookie("name", null);
+        cookie.setDomain(".sourceforge.net");
+        cookie.setPath("/");
         cookie.setDomainAttributeSpecified(true);
         cookie.setPathAttributeSpecified(true);
 
         CookieSpec cookiespec = new RFC2109Spec();
+        CookieOrigin origin = new CookieOrigin("sourceforge.net", 80, "/", false);
         try {
-            cookiespec.validate("sourceforge.net", 80, "/", false, cookie);
+            cookiespec.validate(cookie, origin);
             fail("MalformedCookieException should have been thrown");
         } catch (MalformedCookieException e) {
             // Expected
@@ -223,12 +176,15 @@
     }    
 
     public void testSecondDomainLevelCookieMatch() throws Exception {
-        Cookie cookie = new Cookie(".sourceforge.net", "name", null, "/", null, false); 
+        Cookie cookie = new Cookie("name", null);
+        cookie.setDomain(".sourceforge.net");
+        cookie.setPath("/");
         cookie.setDomainAttributeSpecified(true);
         cookie.setPathAttributeSpecified(true);
 
         CookieSpec cookiespec = new RFC2109Spec();
-        assertFalse(cookiespec.match("sourceforge.net", 80, "/", false, cookie));
+        CookieOrigin origin = new CookieOrigin("sourceforge.net", 80, "/", false);
+        assertFalse(cookiespec.match(cookie, origin));
     }
     
     public void testParseWithWrongPath() throws Exception {
@@ -236,9 +192,13 @@
             "cookie-name=cookie-value; domain=127.0.0.1; path=/not/just/root");
 
         CookieSpec cookiespec = new RFC2109Spec();
+        CookieOrigin origin = new CookieOrigin("127.0.0.1", 80, "/", false);
         try {
-            Cookie[] parsed = cookieParse(cookiespec, "127.0.0.1", 80, "/", false, header);
-            fail("HttpException exception should have been thrown");
+            Cookie[] parsed = cookiespec.parse(header, origin);
+            for (int i = 0; i < parsed.length; i++) {
+                cookiespec.validate(parsed[i], origin);
+            }
+            fail("MalformedCookieException exception should have been thrown");
         } catch (MalformedCookieException e) {
             // expected
         }
@@ -250,23 +210,30 @@
     public void testCookieNameWithBlanks() throws Exception {
         Header setcookie = new Header("Set-Cookie", "invalid name=");
         CookieSpec cookiespec = new RFC2109Spec();
+        CookieOrigin origin = new CookieOrigin("127.0.0.1", 80, "/", false);
         try {
-            Cookie[] parsed = cookieParse(cookiespec, "127.0.0.1", 80, "/", false, setcookie);
+            Cookie[] parsed = cookiespec.parse(setcookie, origin);
+            for (int i = 0; i < parsed.length; i++) {
+                cookiespec.validate(parsed[i], origin);
+            }
             fail("MalformedCookieException exception should have been thrown");
         } catch (MalformedCookieException e) {
             // expected
         }
     }
 
-
     /**
      * Tests if cookie constructor rejects cookie name starting with $.
      */
     public void testCookieNameStartingWithDollarSign() throws Exception {
         Header setcookie = new Header("Set-Cookie", "$invalid_name=");
         CookieSpec cookiespec = new RFC2109Spec();
+        CookieOrigin origin = new CookieOrigin("127.0.0.1", 80, "/", false);
         try {
-            Cookie[] parsed = cookieParse(cookiespec, "127.0.0.1", 80, "/", false, setcookie);
+            Cookie[] parsed = cookiespec.parse(setcookie, origin);
+            for (int i = 0; i < parsed.length; i++) {
+                cookiespec.validate(parsed[i], origin);
+            }
             fail("MalformedCookieException exception should have been thrown");
         } catch (MalformedCookieException e) {
             // expected
@@ -281,18 +248,20 @@
         CookieSpec cookiespec = new RFC2109Spec();
         Header header = new Header("Set-Cookie", 
             "name=\"value\"; version=\"1\"; path=\"/\"; domain=\".mydomain.com\"");
-        Cookie[]cookies = cookiespec.parse("host", 80, "/", false, header );
+        CookieOrigin origin1 = new CookieOrigin("host", 80, "/", false);
+        Cookie[]cookies = cookiespec.parse(header, origin1);
         try {
-            cookiespec.validate("host", 80, "/", false, cookies[0]);
+            cookiespec.validate(cookies[0], origin1);
             fail("MalformedCookieException must have thrown");
         }
         catch(MalformedCookieException expected) {
         }
+        CookieOrigin origin2 = new CookieOrigin("host2", 80, "/", false);
         header = new Header("Set-Cookie", 
             "name=\"value\"; version=\"1\"; path=\"/\"; domain=\"host1\"");
-        cookies = cookiespec.parse("host2", 80, "/", false, header );
+        cookies = cookiespec.parse(header, origin2);
         try {
-            cookiespec.validate("host2", 80, "/", false, cookies[0]);
+            cookiespec.validate(cookies[0], origin2);
             fail("MalformedCookieException must have thrown");
         }
         catch(MalformedCookieException expected) {
@@ -306,7 +275,8 @@
         Header header = new Header("Set-Cookie", "a=b,c");
 
         CookieSpec cookiespec = new RFC2109Spec();
-        Cookie[] cookies = cookiespec.parse("localhost", 80, "/", false, header);
+        CookieOrigin origin = new CookieOrigin("localhost", 80, "/", false);
+        Cookie[] cookies = cookiespec.parse(header, origin);
         assertEquals("number of cookies", 2, cookies.length);
         assertEquals("a", cookies[0].getName());
         assertEquals("b", cookies[0].getValue());
@@ -314,91 +284,146 @@
         assertEquals(null, cookies[1].getValue());
     }
 
-    public void testFormatInvalidCookies() throws Exception {
-        CookieSpec cookiespec = new RFC2109Spec();
-        try {
-            String s = cookiespec.formatCookie(null);
-            fail("IllegalArgumentException nust have been thrown");
-        } catch (IllegalArgumentException expected) {
-        }
-    }    
-
     /**
      * Tests RFC 2109 compiant cookie formatting.
      */
     public void testRFC2109CookieFormatting() throws Exception {
-        CookieSpec cookiespec = new RFC2109Spec();
+        CookieSpec cookiespec = new RFC2109Spec(false);
         Header header = new Header("Set-Cookie", 
             "name=\"value\"; version=\"1\"; path=\"/\"; domain=\".mydomain.com\"");
-        Cookie[] cookies  = cookiespec.parse("myhost.mydomain.com", 80, "/", false, header );
-        cookiespec.validate("myhost.mydomain.com", 80, "/", false, cookies[0]);
-        String s1 = cookiespec.formatCookie(cookies[0]);
-        assertEquals(s1, "$Version=\"1\"; name=\"value\"; $Path=\"/\"; $Domain=\".mydomain.com\"");
+        CookieOrigin origin = new CookieOrigin("myhost.mydomain.com", 80, "/", false);
+        Cookie[] cookies  = cookiespec.parse(header, origin);
+        cookiespec.validate(cookies[0], origin);
+        Header[] headers = cookiespec.formatCookies(cookies);
+        assertNotNull(headers);
+        assertEquals(1, headers.length);
+        assertEquals("$Version=\"1\"; name=\"value\"; $Path=\"/\"; $Domain=\".mydomain.com\"", 
+                headers[0].getValue());
 
         header = new Header( "Set-Cookie", 
             "name=value; path=/; domain=.mydomain.com");
-        cookies = cookiespec.parse("myhost.mydomain.com", 80, "/", false, header );
-        cookiespec.validate("myhost.mydomain.com", 80, "/", false, cookies[0]);
-        String s2 = cookiespec.formatCookie(cookies[0]);
-        assertEquals(s2, "$Version=0; name=value; $Path=/; $Domain=.mydomain.com");
+        cookies = cookiespec.parse(header, origin);
+        cookiespec.validate(cookies[0], origin);
+        headers = cookiespec.formatCookies(cookies);
+        assertNotNull(headers);
+        assertEquals(1, headers.length);
+        assertEquals("$Version=0; name=value; $Path=/; $Domain=.mydomain.com", 
+                headers[0].getValue());
     }
 
     public void testRFC2109CookiesFormatting() throws Exception {
-        CookieSpec cookiespec = new RFC2109Spec();
+        CookieSpec cookiespec = new RFC2109Spec(true);
         Header header = new Header("Set-Cookie", 
             "name1=value1; path=/; domain=.mydomain.com, " + 
             "name2=\"value2\"; version=\"1\"; path=\"/\"; domain=\".mydomain.com\"");
-        Cookie[] cookies = cookieParse(cookiespec, "myhost.mydomain.com", 80, "/", false, header);
+        CookieOrigin origin = new CookieOrigin("myhost.mydomain.com", 80, "/", false);
+        Cookie[] cookies = cookiespec.parse(header, origin);
+        for (int i = 0; i < cookies.length; i++) {
+            cookiespec.validate(cookies[i], origin);
+        }
         assertNotNull(cookies);
         assertEquals(2, cookies.length);
-        String s1 = cookiespec.formatCookies(cookies);
-        assertEquals(s1, 
+        Header[] headers  = cookiespec.formatCookies(cookies);
+        assertNotNull(headers);
+        assertEquals(1, headers.length);
+        assertEquals( 
             "$Version=0; name1=value1; $Path=/; $Domain=.mydomain.com; " + 
-            "name2=value2; $Path=/; $Domain=.mydomain.com");
+            "name2=value2; $Path=/; $Domain=.mydomain.com",
+            headers[0].getValue());
 
         header = new Header("Set-Cookie", 
             "name1=value1; version=1; path=/; domain=.mydomain.com, " + 
             "name2=\"value2\"; version=\"1\"; path=\"/\"; domain=\".mydomain.com\"");
-        cookies = cookieParse(cookiespec, "myhost.mydomain.com", 80, "/", false, header);
+        cookies = cookiespec.parse(header, origin);
+        for (int i = 0; i < cookies.length; i++) {
+            cookiespec.validate(cookies[i], origin);
+        }
         assertNotNull(cookies);
         assertEquals(2, cookies.length);
-        String s2 = cookiespec.formatCookies(cookies);
-        assertEquals(s2, 
+        headers = cookiespec.formatCookies(cookies);
+        assertEquals( 
             "$Version=\"1\"; name1=\"value1\"; $Path=\"/\"; $Domain=\".mydomain.com\"; " + 
-            "name2=\"value2\"; $Path=\"/\"; $Domain=\".mydomain.com\"");
+            "name2=\"value2\"; $Path=\"/\"; $Domain=\".mydomain.com\"",
+            headers[0].getValue());
     }
     
     /**
      * Tests if null cookie values are handled correctly.
      */
     public void testNullCookieValueFormatting() {
-        Cookie cookie = new Cookie(".whatever.com", "name", null, "/", null, false); 
+        Cookie cookie = new Cookie("name", null);
+        cookie.setDomain(".whatever.com");
+        cookie.setPath("/");
         cookie.setDomainAttributeSpecified(true);
         cookie.setPathAttributeSpecified(true);
 
         CookieSpec cookiespec = new RFC2109Spec();
-        String s = cookiespec.formatCookie(cookie);
-        assertEquals("$Version=0; name=; $Path=/; $Domain=.whatever.com", s);
+        Header[] headers = cookiespec.formatCookies(new Cookie[] { cookie });
+        assertNotNull(headers);
+        assertEquals(1, headers.length);
+        assertEquals("$Version=0; name=; $Path=/; $Domain=.whatever.com", 
+                headers[0].getValue());
 
         cookie.setVersion(1);
-        s = cookiespec.formatCookie(cookie);
-        assertEquals("$Version=\"1\"; name=\"\"; $Path=\"/\"; $Domain=\".whatever.com\"", s);
+        headers = cookiespec.formatCookies(new Cookie[] { cookie });
+        assertNotNull(headers);
+        assertEquals(1, headers.length);
+        assertEquals("$Version=\"1\"; name=; $Path=\"/\"; $Domain=\".whatever.com\"", 
+                headers[0].getValue());
     }
 
     public void testCookieNullDomainNullPathFormatting() {
-        Cookie cookie = new Cookie(null, "name", null, "/", null, false); 
+        Cookie cookie = new Cookie("name", null); 
         cookie.setDomainAttributeSpecified(true);
+        cookie.setPath("/");
         cookie.setPathAttributeSpecified(true);
 
         CookieSpec cookiespec = new RFC2109Spec();
-        String s = cookiespec.formatCookie(cookie);
-        assertEquals("$Version=0; name=; $Path=/", s);
+        Header[] headers = cookiespec.formatCookies(new Cookie[] { cookie });
+        assertNotNull(headers);
+        assertEquals(1, headers.length);
+        assertEquals("$Version=0; name=; $Path=/", headers[0].getValue());
 
         cookie.setDomainAttributeSpecified(false);
         cookie.setPathAttributeSpecified(false);
-        s = cookiespec.formatCookie(cookie);
-        assertEquals("$Version=0; name=", s);
+        headers = cookiespec.formatCookies(new Cookie[] { cookie });
+        assertNotNull(headers);
+        assertEquals(1, headers.length);
+        assertEquals("$Version=0; name=", headers[0].getValue());
     }
 
-}
-
+    public void testInvalidInput() throws Exception {
+        CookieSpec cookiespec = new RFC2109Spec();
+        try {
+            cookiespec.parse(null, null);
+            fail("IllegalArgumentException must have been thrown");
+        } catch (IllegalArgumentException ex) {
+            // expected
+        }
+        try {
+            cookiespec.parse(new Header("Set-Cookie", "name=value"), null);
+            fail("IllegalArgumentException must have been thrown");
+        } catch (IllegalArgumentException ex) {
+            // expected
+        }
+        try {
+            cookiespec.validate(null, null);
+            fail("IllegalArgumentException must have been thrown");
+        } catch (IllegalArgumentException ex) {
+            // expected
+        }
+        try {
+            cookiespec.formatCookies(null);
+            fail("IllegalArgumentException must have been thrown");
+        } catch (IllegalArgumentException ex) {
+            // expected
+        }
+        try {
+            cookiespec.formatCookies(new Cookie[] {});
+            fail("IllegalArgumentException must have been thrown");
+        } catch (IllegalArgumentException ex) {
+            // expected
+        }
+    }
+        
+}
\ No newline at end of file