1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.http.impl.cookie;
29
30 import java.util.List;
31
32 import org.apache.http.FormattedHeader;
33 import org.apache.http.Header;
34 import org.apache.http.HeaderElement;
35 import org.apache.http.annotation.NotThreadSafe;
36 import org.apache.http.cookie.Cookie;
37 import org.apache.http.cookie.CookieOrigin;
38 import org.apache.http.cookie.CookieSpec;
39 import org.apache.http.cookie.MalformedCookieException;
40 import org.apache.http.cookie.SM;
41 import org.apache.http.cookie.SetCookie2;
42 import org.apache.http.message.ParserCursor;
43 import org.apache.http.util.Args;
44 import org.apache.http.util.CharArrayBuffer;
45
46
47
48
49
50
51
52 @NotThreadSafe
53 public class BestMatchSpec implements CookieSpec {
54
55 private final String[] datepatterns;
56 private final boolean oneHeader;
57
58
59 private RFC2965Spec strict;
60 private RFC2109Spec obsoleteStrict;
61 private BrowserCompatSpec compat;
62
63 public BestMatchSpec(final String[] datepatterns, final boolean oneHeader) {
64 super();
65 this.datepatterns = datepatterns == null ? null : datepatterns.clone();
66 this.oneHeader = oneHeader;
67 }
68
69 public BestMatchSpec() {
70 this(null, false);
71 }
72
73 private RFC2965Spec getStrict() {
74 if (this.strict == null) {
75 this.strict = new RFC2965Spec(this.datepatterns, this.oneHeader);
76 }
77 return strict;
78 }
79
80 private RFC2109Spec getObsoleteStrict() {
81 if (this.obsoleteStrict == null) {
82 this.obsoleteStrict = new RFC2109Spec(this.datepatterns, this.oneHeader);
83 }
84 return obsoleteStrict;
85 }
86
87 private BrowserCompatSpec getCompat() {
88 if (this.compat == null) {
89 this.compat = new BrowserCompatSpec(this.datepatterns);
90 }
91 return compat;
92 }
93
94 public List<Cookie> parse(
95 final Header header,
96 final CookieOrigin origin) throws MalformedCookieException {
97 Args.notNull(header, "Header");
98 Args.notNull(origin, "Cookie origin");
99 HeaderElement[] helems = header.getElements();
100 boolean versioned = false;
101 boolean netscape = false;
102 for (final HeaderElement helem: helems) {
103 if (helem.getParameterByName("version") != null) {
104 versioned = true;
105 }
106 if (helem.getParameterByName("expires") != null) {
107 netscape = true;
108 }
109 }
110 if (netscape || !versioned) {
111
112
113 final NetscapeDraftHeaderParser parser = NetscapeDraftHeaderParser.DEFAULT;
114 CharArrayBuffer buffer;
115 ParserCursor cursor;
116 if (header instanceof FormattedHeader) {
117 buffer = ((FormattedHeader) header).getBuffer();
118 cursor = new ParserCursor(
119 ((FormattedHeader) header).getValuePos(),
120 buffer.length());
121 } else {
122 final String s = header.getValue();
123 if (s == null) {
124 throw new MalformedCookieException("Header value is null");
125 }
126 buffer = new CharArrayBuffer(s.length());
127 buffer.append(s);
128 cursor = new ParserCursor(0, buffer.length());
129 }
130 helems = new HeaderElement[] { parser.parseHeader(buffer, cursor) };
131 return getCompat().parse(helems, origin);
132 } else {
133 if (SM.SET_COOKIE2.equals(header.getName())) {
134 return getStrict().parse(helems, origin);
135 } else {
136 return getObsoleteStrict().parse(helems, origin);
137 }
138 }
139 }
140
141 public void validate(
142 final Cookie cookie,
143 final CookieOrigin origin) throws MalformedCookieException {
144 Args.notNull(cookie, "Cookie");
145 Args.notNull(origin, "Cookie origin");
146 if (cookie.getVersion() > 0) {
147 if (cookie instanceof SetCookie2) {
148 getStrict().validate(cookie, origin);
149 } else {
150 getObsoleteStrict().validate(cookie, origin);
151 }
152 } else {
153 getCompat().validate(cookie, origin);
154 }
155 }
156
157 public boolean match(final Cookie cookie, final CookieOrigin origin) {
158 Args.notNull(cookie, "Cookie");
159 Args.notNull(origin, "Cookie origin");
160 if (cookie.getVersion() > 0) {
161 if (cookie instanceof SetCookie2) {
162 return getStrict().match(cookie, origin);
163 } else {
164 return getObsoleteStrict().match(cookie, origin);
165 }
166 } else {
167 return getCompat().match(cookie, origin);
168 }
169 }
170
171 public List<Header> formatCookies(final List<Cookie> cookies) {
172 Args.notNull(cookies, "List of cookies");
173 int version = Integer.MAX_VALUE;
174 boolean isSetCookie2 = true;
175 for (final Cookie cookie: cookies) {
176 if (!(cookie instanceof SetCookie2)) {
177 isSetCookie2 = false;
178 }
179 if (cookie.getVersion() < version) {
180 version = cookie.getVersion();
181 }
182 }
183 if (version > 0) {
184 if (isSetCookie2) {
185 return getStrict().formatCookies(cookies);
186 } else {
187 return getObsoleteStrict().formatCookies(cookies);
188 }
189 } else {
190 return getCompat().formatCookies(cookies);
191 }
192 }
193
194 public int getVersion() {
195 return getStrict().getVersion();
196 }
197
198 public Header getVersionHeader() {
199 return getStrict().getVersionHeader();
200 }
201
202 @Override
203 public String toString() {
204 return "best-match";
205 }
206
207 }