diff --git a/src/java/org/apache/http/cookie/Cookie.java b/src/java/org/apache/http/cookie/Cookie.java index 4681247ad..667803361 100644 --- a/src/java/org/apache/http/cookie/Cookie.java +++ b/src/java/org/apache/http/cookie/Cookie.java @@ -49,10 +49,10 @@ import org.apache.http.util.LangUtils; * @author Sean C. Sullivan * @author John Evans * @author Marc A. Saegesser - * @author Oleg Kalnichevski + * @author Oleg Kalnichevski * @author Mike Bowler * - * @version $Revision$ $Date$ + * @version $Revision$ */ public class Cookie extends NameValuePair { diff --git a/src/java/org/apache/http/cookie/CookiePolicy.java b/src/java/org/apache/http/cookie/CookiePolicy.java new file mode 100644 index 000000000..ca3591d5e --- /dev/null +++ b/src/java/org/apache/http/cookie/CookiePolicy.java @@ -0,0 +1,173 @@ +/* + * $HeadURL$ + * $Revision$ + * $Date$ + * + * ==================================================================== + * + * 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.cookie; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.apache.http.cookie.params.CookieSpecParams; +import org.apache.http.params.HttpParams; + +/** + * Cookie management policy class. The cookie policy provides corresponding + * cookie management interfrace for a given type or version of cookie. + * + * @author Oleg Kalnichevski + * @author Mike Bowler + * + * @since 2.0 + */ +public class CookiePolicy { + + private static Map SPECS = Collections.synchronizedMap(new HashMap()); + + private CookiePolicy() { + } + + /** + * Registers a {@link CookieSpecFactory} with the given identifier. + * If a specification with the given ID already exists it will be overridden. + * This ID is the same one used to retrieve the {@link CookieSpecFactory} + * from {@link #getCookieSpec(String)}. + * + * @param id the identifier for this specification + * @param factory the {@link CookieSpecFactory} class to register + * + * @see #getCookieSpec(String) + * + * @since 3.0 + */ + public static void register(final String id, final CookieSpecFactory factory) { + if (id == null) { + throw new IllegalArgumentException("Id may not be null"); + } + if (factory == null) { + throw new IllegalArgumentException("Cookie spec factory may not be null"); + } + SPECS.put(id.toLowerCase(), factory); + } + + /** + * Unregisters the {@link CookieSpecFactory} with the given ID. + * + * @param id the ID of the {@link CookieSpec cookie specification} to unregister + * + * @since 3.0 + */ + public static void unregister(final String id) { + if (id == null) { + throw new IllegalArgumentException("Id may not be null"); + } + SPECS.remove(id.toLowerCase()); + } + + /** + * Gets the {@link CookieSpec cookie specification} with the given ID. + * + * @param id the {@link CookieSpec cookie specification} ID + * @param params the {@link HttpParams HTTP parameters} for the cookie + * specification. + * + * @return {@link CookieSpec cookie specification} + * + * @throws IllegalStateException if a policy with the ID cannot be found + * + * @since 4.0 + */ + public static CookieSpec getCookieSpec(final String id, final HttpParams params) + throws IllegalStateException { + + if (id == null) { + throw new IllegalArgumentException("Id may not be null"); + } + CookieSpecFactory factory = (CookieSpecFactory) SPECS.get(id.toLowerCase()); + if (factory != null) { + return factory.newInstance(params); + } else { + throw new IllegalStateException("Unsupported cookie spec " + id); + } + } + + /** + * Gets the {@link CookieSpec cookie specification} based on the given + * HTTP parameters. The cookie specification ID will be obtained from + * the HTTP parameters. + * + * @param params the {@link HttpParams HTTP parameters} for the cookie + * specification. + * + * @return {@link CookieSpec cookie specification} + * + * @throws IllegalStateException if a policy with the ID cannot be found + * + * @see CookieSpecParams#getCookiePolicy(HttpParams) + * + * @since 4.0 + */ + public static CookieSpec getCookieSpec(final HttpParams params) + throws IllegalStateException { + if (params == null) { + throw new IllegalArgumentException("HTTP parameters may not be null"); + } + return getCookieSpec(CookieSpecParams.getCookiePolicy(params), params); + } + + /** + * Gets the {@link CookieSpec cookie specification} with the given ID. + * + * @param id the {@link CookieSpec cookie specification} ID + * + * @return {@link CookieSpec cookie specification} + * + * @throws IllegalStateException if a policy with the ID cannot be found + * + * @since 3.0 + */ + public static CookieSpec getCookieSpec(final String id) + throws IllegalStateException { + return getCookieSpec(id, null); + } + + /** + * Obtains the currently registered cookie policy names. + * + * Note that the DEFAULT policy (if present) is likely to be the same + * as one of the other policies, but does not have to be. + * + * @return array of registered cookie policy names + * + * @since 3.1 + */ + public static String[] getRegisteredCookieSpecs(){ + return (String[]) SPECS.keySet().toArray(new String [SPECS.size()]); + } + +} diff --git a/src/java/org/apache/http/cookie/CookieSpecFactory.java b/src/java/org/apache/http/cookie/CookieSpecFactory.java new file mode 100644 index 000000000..d2f194e33 --- /dev/null +++ b/src/java/org/apache/http/cookie/CookieSpecFactory.java @@ -0,0 +1,44 @@ +/* + * $HeadURL$ + * $Revision$ + * $Date$ + * + * ==================================================================== + * + * Copyright 2002-2004 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.cookie; + +import org.apache.http.params.HttpParams; + +/** + * + * @author Oleg Kalnichevski + * + * @since 4.0 + */ +public interface CookieSpecFactory { + + CookieSpec newInstance(HttpParams params); + +} diff --git a/src/java/org/apache/http/cookie/impl/BrowserCompatSpecFactory.java b/src/java/org/apache/http/cookie/impl/BrowserCompatSpecFactory.java new file mode 100644 index 000000000..34c75c52d --- /dev/null +++ b/src/java/org/apache/http/cookie/impl/BrowserCompatSpecFactory.java @@ -0,0 +1,54 @@ +/* + * $HeadURL$ + * $Revision$ + * $Date$ + * + * ==================================================================== + * + * Copyright 2002-2004 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.cookie.impl; + +import org.apache.http.cookie.CookieSpec; +import org.apache.http.cookie.CookieSpecFactory; +import org.apache.http.cookie.params.CookieSpecParams; +import org.apache.http.params.HttpParams; + +/** + * + * @author Oleg Kalnichevski + * + * @since 4.0 + */ +public class BrowserCompatSpecFactory implements CookieSpecFactory { + + public CookieSpec newInstance(final HttpParams params) { + if (params != null) { + return new BrowserCompatSpec( + (String []) params.getParameter(CookieSpecParams.DATE_PATTERNS)); + } else { + return new BrowserCompatSpec(); + } + } + +} diff --git a/src/java/org/apache/http/cookie/impl/NetscapeDraftSpecFactory.java b/src/java/org/apache/http/cookie/impl/NetscapeDraftSpecFactory.java new file mode 100644 index 000000000..187ebed4c --- /dev/null +++ b/src/java/org/apache/http/cookie/impl/NetscapeDraftSpecFactory.java @@ -0,0 +1,48 @@ +/* + * $HeadURL$ + * $Revision$ + * $Date$ + * + * ==================================================================== + * + * Copyright 2002-2004 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.cookie.impl; + +import org.apache.http.cookie.CookieSpec; +import org.apache.http.cookie.CookieSpecFactory; +import org.apache.http.params.HttpParams; + +/** + * + * @author Oleg Kalnichevski + * + * @since 4.0 + */ +public class NetscapeDraftSpecFactory implements CookieSpecFactory { + + public CookieSpec newInstance(final HttpParams params) { + return new NetscapeDraftSpec(); + } + +} diff --git a/src/java/org/apache/http/cookie/impl/RFC2109SpecFactory.java b/src/java/org/apache/http/cookie/impl/RFC2109SpecFactory.java new file mode 100644 index 000000000..9872d92d6 --- /dev/null +++ b/src/java/org/apache/http/cookie/impl/RFC2109SpecFactory.java @@ -0,0 +1,55 @@ +/* + * $HeadURL$ + * $Revision$ + * $Date$ + * + * ==================================================================== + * + * Copyright 2002-2004 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.cookie.impl; + +import org.apache.http.cookie.CookieSpec; +import org.apache.http.cookie.CookieSpecFactory; +import org.apache.http.cookie.params.CookieSpecParams; +import org.apache.http.params.HttpParams; + +/** + * + * @author Oleg Kalnichevski + * + * @since 4.0 + */ +public class RFC2109SpecFactory implements CookieSpecFactory { + + public CookieSpec newInstance(final HttpParams params) { + if (params != null) { + return new RFC2109Spec( + (String []) params.getParameter(CookieSpecParams.DATE_PATTERNS), + params.getBooleanParameter(CookieSpecParams.SINGLE_COOKIE_HEADER, false)); + } else { + return new RFC2109Spec(); + } + } + +} diff --git a/src/java/org/apache/http/cookie/params/CookieSpecParams.java b/src/java/org/apache/http/cookie/params/CookieSpecParams.java new file mode 100644 index 000000000..7dd680be9 --- /dev/null +++ b/src/java/org/apache/http/cookie/params/CookieSpecParams.java @@ -0,0 +1,119 @@ +/* + * $HeadURL$ + * $Revision$ + * $Date$ + * + * ==================================================================== + * + * 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.cookie.params; + +import org.apache.http.params.HttpParams; + +/** + * This class implements an adaptor around the {@link HttpParams} interface + * to simplify manipulation of cookie management specific parameters. + * + * @author Oleg Kalnichevski + * + * @version $Revision$ + * + * @since 4.0 + */ +public final class CookieSpecParams { + + /** + * The key used to look up the date patterns used for parsing. The String patterns are stored + * in a {@link java.util.Collection} and must be compatible with + * {@link java.text.SimpleDateFormat}. + *

+ * This parameter expects a value of type {@link java.util.Collection}. + *

+ */ + public static final String DATE_PATTERNS = "http.protocol.cookie-datepatterns"; + + /** + * Defines whether {@link org.apache.commons.httpclient.Cookie cookies} should be put on + * a single {@link org.apache.commons.httpclient.Header response header}. + *

+ * This parameter expects a value of type {@link Boolean}. + *

+ */ + public static final String SINGLE_COOKIE_HEADER = "http.protocol.single-cookie-header"; + + /** + * Defines {@link CookieSpec cookie specification} to be used for cookie management. + *

+ * This parameter expects a value of type {@link String}. + *

+ */ + public static final String COOKIE_POLICY = "http.protocol.cookie-policy"; + + /** + * The policy that provides high degree of compatibilty + * with common cookie management of popular HTTP agents. + */ + public static final String BROWSER_COMPATIBILITY = "compatibility"; + + /** + * The Netscape cookie draft compliant policy. + */ + public static final String NETSCAPE = "netscape"; + + /** + * The RFC 2109 compliant policy. + */ + public static final String RFC_2109 = "rfc2109"; + + /** + * The default cookie policy. + */ + public static final String DEFAULT = "default"; + + public static String getCookiePolicy(final HttpParams params) { + if (params == null) { + throw new IllegalArgumentException("HTTP parameters may not be null"); + } + Object param = params.getParameter(COOKIE_POLICY); + if (param == null) { + return DEFAULT; + } + return (String) param; + } + + /** + * Assigns the {@link CookiePolicy cookie policy} to be used by the + * {@link org.apache.commons.httpclient.HttpMethod HTTP methods} + * this collection of parameters applies to. + * + * @param policy the {@link CookiePolicy cookie policy} + */ + public static void setCookiePolicy(final HttpParams params, String policy) { + if (params == null) { + throw new IllegalArgumentException("HTTP parameters may not be null"); + } + params.setParameter(COOKIE_POLICY, policy); + } + +} diff --git a/src/test/org/apache/http/cookie/TestAllCookie.java b/src/test/org/apache/http/cookie/TestAllCookie.java index 7ec60ee74..caadf8224 100644 --- a/src/test/org/apache/http/cookie/TestAllCookie.java +++ b/src/test/org/apache/http/cookie/TestAllCookie.java @@ -40,6 +40,7 @@ public class TestAllCookie extends TestCase { TestSuite suite = new TestSuite(); suite.addTest(TestCookieOrigin.suite()); suite.addTest(TestCookiePathComparator.suite()); + suite.addTest(TestCookiePolicy.suite()); return suite; } diff --git a/src/test/org/apache/http/cookie/TestCookiePolicy.java b/src/test/org/apache/http/cookie/TestCookiePolicy.java new file mode 100644 index 000000000..71dd0478a --- /dev/null +++ b/src/test/org/apache/http/cookie/TestCookiePolicy.java @@ -0,0 +1,156 @@ +/* + * $HeadURL$ + * $Revision$ + * $Date$ + * ==================================================================== + * + * 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.cookie; + +import org.apache.http.cookie.impl.BrowserCompatSpec; +import org.apache.http.cookie.impl.BrowserCompatSpecFactory; +import org.apache.http.cookie.impl.NetscapeDraftSpecFactory; +import org.apache.http.cookie.impl.RFC2109SpecFactory; +import org.apache.http.cookie.params.CookieSpecParams; +import org.apache.http.impl.DefaultHttpParams; +import org.apache.http.params.HttpParams; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Test cases for {@link CookiePolicy}. + */ +public class TestCookiePolicy extends TestCase { + + + // ------------------------------------------------------------ Constructor + + public TestCookiePolicy(String name) { + super(name); + } + + // ------------------------------------------------------- TestCase Methods + + public static Test suite() { + return new TestSuite(TestCookiePolicy.class); + } + + public void testRegisterUnregisterCookieSpecFactory() { + String[] specs = CookiePolicy.getRegisteredCookieSpecs(); + assertNotNull(specs); + assertEquals(0, specs.length); + + CookiePolicy.register(CookieSpecParams.BROWSER_COMPATIBILITY, + new BrowserCompatSpecFactory()); + CookiePolicy.register(CookieSpecParams.NETSCAPE, + new NetscapeDraftSpecFactory()); + CookiePolicy.register(CookieSpecParams.RFC_2109, + new RFC2109SpecFactory()); + CookiePolicy.register(CookieSpecParams.RFC_2109, + new RFC2109SpecFactory()); + + specs = CookiePolicy.getRegisteredCookieSpecs(); + assertNotNull(specs); + assertEquals(3, specs.length); + + CookiePolicy.unregister(CookieSpecParams.NETSCAPE); + CookiePolicy.unregister(CookieSpecParams.NETSCAPE); + CookiePolicy.unregister(CookieSpecParams.RFC_2109); + CookiePolicy.unregister(CookieSpecParams.BROWSER_COMPATIBILITY); + CookiePolicy.unregister("whatever"); + + specs = CookiePolicy.getRegisteredCookieSpecs(); + assertNotNull(specs); + assertEquals(0, specs.length); + } + + public void testGetNewCookieSpec() { + CookiePolicy.register(CookieSpecParams.BROWSER_COMPATIBILITY, + new BrowserCompatSpecFactory()); + CookiePolicy.register(CookieSpecParams.NETSCAPE, + new NetscapeDraftSpecFactory()); + CookiePolicy.register(CookieSpecParams.RFC_2109, + new RFC2109SpecFactory()); + + assertNotNull(CookiePolicy.getCookieSpec(CookieSpecParams.NETSCAPE)); + assertNotNull(CookiePolicy.getCookieSpec(CookieSpecParams.RFC_2109)); + assertNotNull(CookiePolicy.getCookieSpec(CookieSpecParams.BROWSER_COMPATIBILITY)); + try { + CookiePolicy.getCookieSpec("whatever"); + fail("IllegalStateException should have been thrown"); + } catch (IllegalStateException ex) { + // expected + } + HttpParams params = new DefaultHttpParams(); + assertNotNull(CookiePolicy.getCookieSpec(CookieSpecParams.NETSCAPE, params)); + assertNotNull(CookiePolicy.getCookieSpec(CookieSpecParams.RFC_2109, params)); + assertNotNull(CookiePolicy.getCookieSpec(CookieSpecParams.BROWSER_COMPATIBILITY, params)); + try { + CookiePolicy.getCookieSpec("whatever", params); + fail("IllegalStateException should have been thrown"); + } catch (IllegalStateException ex) { + // expected + } + CookieSpecParams.setCookiePolicy(params, CookieSpecParams.BROWSER_COMPATIBILITY); + CookieSpec cookiespec = CookiePolicy.getCookieSpec(params); + assertTrue(cookiespec instanceof BrowserCompatSpec); + } + + public void testInvalidInput() { + try { + CookiePolicy.register(null, null); + fail("IllegalArgumentException should have been thrown"); + } catch (IllegalArgumentException ex) { + // expected + } + try { + CookiePolicy.register("whatever", null); + fail("IllegalArgumentException should have been thrown"); + } catch (IllegalArgumentException ex) { + // expected + } + try { + CookiePolicy.unregister(null); + fail("IllegalArgumentException should have been thrown"); + } catch (IllegalArgumentException ex) { + // expected + } + try { + CookiePolicy.getCookieSpec((String)null); + fail("IllegalArgumentException should have been thrown"); + } catch (IllegalArgumentException ex) { + // expected + } + try { + CookiePolicy.getCookieSpec((HttpParams)null); + fail("IllegalArgumentException should have been thrown"); + } catch (IllegalArgumentException ex) { + // expected + } + } + +} +