001/* 002 * ==================================================================== 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, 014 * software distributed under the License is distributed on an 015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 016 * KIND, either express or implied. See the License for the 017 * specific language governing permissions and limitations 018 * under the License. 019 * ==================================================================== 020 * 021 * This software consists of voluntary contributions made by many 022 * individuals on behalf of the Apache Software Foundation. For more 023 * information on the Apache Software Foundation, please see 024 * <http://www.apache.org/>. 025 * 026 */ 027 028package org.apache.http.impl.cookie; 029 030import org.apache.http.annotation.Contract; 031import org.apache.http.annotation.ThreadingBehavior; 032import org.apache.http.conn.util.PublicSuffixMatcher; 033import org.apache.http.cookie.Cookie; 034import org.apache.http.cookie.CookieOrigin; 035import org.apache.http.cookie.CookieSpec; 036import org.apache.http.cookie.CookieSpecProvider; 037import org.apache.http.cookie.MalformedCookieException; 038import org.apache.http.protocol.HttpContext; 039 040/** 041 * {@link org.apache.http.cookie.CookieSpecProvider} implementation that provides an instance of 042 * {@link org.apache.http.impl.cookie.DefaultCookieSpec}. The instance returned by this factory can 043 * be shared by multiple threads. 044 * 045 * @since 4.4 046 */ 047@Contract(threading = ThreadingBehavior.IMMUTABLE) 048public class DefaultCookieSpecProvider implements CookieSpecProvider { 049 050 public enum CompatibilityLevel { 051 DEFAULT, 052 IE_MEDIUM_SECURITY 053 } 054 055 private final CompatibilityLevel compatibilityLevel; 056 private final PublicSuffixMatcher publicSuffixMatcher; 057 private final String[] datepatterns; 058 private final boolean oneHeader; 059 060 private volatile CookieSpec cookieSpec; 061 062 public DefaultCookieSpecProvider( 063 final CompatibilityLevel compatibilityLevel, 064 final PublicSuffixMatcher publicSuffixMatcher, 065 final String[] datepatterns, 066 final boolean oneHeader) { 067 super(); 068 this.compatibilityLevel = compatibilityLevel != null ? compatibilityLevel : CompatibilityLevel.DEFAULT; 069 this.publicSuffixMatcher = publicSuffixMatcher; 070 this.datepatterns = datepatterns; 071 this.oneHeader = oneHeader; 072 } 073 074 public DefaultCookieSpecProvider( 075 final CompatibilityLevel compatibilityLevel, 076 final PublicSuffixMatcher publicSuffixMatcher) { 077 this(compatibilityLevel, publicSuffixMatcher, null, false); 078 } 079 080 public DefaultCookieSpecProvider(final PublicSuffixMatcher publicSuffixMatcher) { 081 this(CompatibilityLevel.DEFAULT, publicSuffixMatcher, null, false); 082 } 083 084 public DefaultCookieSpecProvider() { 085 this(CompatibilityLevel.DEFAULT, null, null, false); 086 } 087 088 @Override 089 public CookieSpec create(final HttpContext context) { 090 if (cookieSpec == null) { 091 synchronized (this) { 092 if (cookieSpec == null) { 093 final RFC2965Spec strict = new RFC2965Spec(this.oneHeader, 094 new RFC2965VersionAttributeHandler(), 095 new BasicPathHandler(), 096 PublicSuffixDomainFilter.decorate( 097 new RFC2965DomainAttributeHandler(), this.publicSuffixMatcher), 098 new RFC2965PortAttributeHandler(), 099 new BasicMaxAgeHandler(), 100 new BasicSecureHandler(), 101 new BasicCommentHandler(), 102 new RFC2965CommentUrlAttributeHandler(), 103 new RFC2965DiscardAttributeHandler()); 104 final RFC2109Spec obsoleteStrict = new RFC2109Spec(this.oneHeader, 105 new RFC2109VersionHandler(), 106 new BasicPathHandler(), 107 PublicSuffixDomainFilter.decorate( 108 new RFC2109DomainHandler(), this.publicSuffixMatcher), 109 new BasicMaxAgeHandler(), 110 new BasicSecureHandler(), 111 new BasicCommentHandler()); 112 final NetscapeDraftSpec netscapeDraft = new NetscapeDraftSpec( 113 PublicSuffixDomainFilter.decorate( 114 new BasicDomainHandler(), this.publicSuffixMatcher), 115 this.compatibilityLevel == CompatibilityLevel.IE_MEDIUM_SECURITY ? 116 new BasicPathHandler() { 117 @Override 118 public void validate( 119 final Cookie cookie, 120 final CookieOrigin origin) throws MalformedCookieException { 121 // No validation 122 } 123 } : new BasicPathHandler(), 124 new BasicSecureHandler(), 125 new BasicCommentHandler(), 126 new BasicExpiresHandler(this.datepatterns != null ? this.datepatterns.clone() : 127 new String[]{NetscapeDraftSpec.EXPIRES_PATTERN})); 128 this.cookieSpec = new DefaultCookieSpec(strict, obsoleteStrict, netscapeDraft); 129 } 130 } 131 } 132 return this.cookieSpec; 133 } 134 135}