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
29
30 package org.apache.commons.httpclient.cookie;
31
32 import java.util.Collections;
33 import java.util.HashMap;
34 import java.util.Map;
35
36 import org.apache.commons.logging.Log;
37 import org.apache.commons.logging.LogFactory;
38
39 /***
40 * Cookie management policy class. The cookie policy provides corresponding
41 * cookie management interfrace for a given type or version of cookie.
42 * <p>RFC 2109 specification is used per default. Other supported specification
43 * can be chosen when appropriate or set default when desired
44 * <p>The following specifications are provided:
45 * <ul>
46 * <li><tt>BROWSER_COMPATIBILITY</tt>: compatible with the common cookie
47 * management practices (even if they are not 100% standards compliant)
48 * <li><tt>NETSCAPE</tt>: Netscape cookie draft compliant
49 * <li><tt>RFC_2109</tt>: RFC2109 compliant (default)
50 * <li><tt>IGNORE_COOKIES</tt>: do not automcatically process cookies
51 * </ul>
52 *
53 * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
54 * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
55 *
56 * @since 2.0
57 */
58 public abstract class CookiePolicy {
59
60 private static Map SPECS = Collections.synchronizedMap(new HashMap());
61
62 /***
63 * The policy that provides high degree of compatibilty
64 * with common cookie management of popular HTTP agents.
65 *
66 * @since 3.0
67 */
68 public static final String BROWSER_COMPATIBILITY = "compatibility";
69
70 /***
71 * The Netscape cookie draft compliant policy.
72 *
73 * @since 3.0
74 */
75 public static final String NETSCAPE = "netscape";
76
77 /***
78 * The RFC 2109 compliant policy.
79 *
80 * @since 3.0
81 */
82 public static final String RFC_2109 = "rfc2109";
83
84 /***
85 * The RFC 2965 compliant policy.
86 *
87 * @since 3.0
88 */
89 public static final String RFC_2965 = "rfc2965";
90
91 /***
92 * The policy that ignores cookies.
93 *
94 * @since 3.0
95 */
96 public static final String IGNORE_COOKIES = "ignoreCookies";
97
98 /***
99 * The default cookie policy.
100 *
101 * @since 3.0
102 */
103 public static final String DEFAULT = "default";
104
105 static {
106 CookiePolicy.registerCookieSpec(DEFAULT, RFC2109Spec.class);
107 CookiePolicy.registerCookieSpec(RFC_2109, RFC2109Spec.class);
108 CookiePolicy.registerCookieSpec(RFC_2965, RFC2965Spec.class);
109 CookiePolicy.registerCookieSpec(BROWSER_COMPATIBILITY, CookieSpecBase.class);
110 CookiePolicy.registerCookieSpec(NETSCAPE, NetscapeDraftSpec.class);
111 CookiePolicy.registerCookieSpec(IGNORE_COOKIES, IgnoreCookiesSpec.class);
112 }
113
114 /***
115 * The <tt>COMPATIBILITY</tt> policy provides high compatibilty
116 * with common cookie management of popular HTTP agents.
117 *
118 * @deprecated Use {@link #BROWSER_COMPATIBILITY}
119 */
120 public static final int COMPATIBILITY = 0;
121
122 /***
123 * The <tt>NETSCAPE_DRAFT</tt> Netscape draft compliant policy.
124 *
125 * @deprecated Use {@link #NETSCAPE}
126 */
127 public static final int NETSCAPE_DRAFT = 1;
128
129 /***
130 * The <tt>RFC2109</tt> RFC 2109 compliant policy.
131 *
132 * @deprecated Use {@link #RFC_2109}
133 */
134 public static final int RFC2109 = 2;
135
136 /***
137 * The <tt>RFC2965</tt> RFC 2965 compliant policy.
138 *
139 * @deprecated Use {@link #RFC_2965}
140 */
141 public static final int RFC2965 = 3;
142
143 /***
144 * The default cookie policy.
145 *
146 * @deprecated Use {@link #DEFAULT}
147 */
148 private static int defaultPolicy = RFC2109;
149
150 /*** Log object. */
151 protected static final Log LOG = LogFactory.getLog(CookiePolicy.class);
152
153 /***
154 * Registers a new {@link CookieSpec cookie specification} with the given identifier.
155 * If a specification with the given ID already exists it will be overridden.
156 * This ID is the same one used to retrieve the {@link CookieSpec cookie specification}
157 * from {@link #getCookieSpec(String)}.
158 *
159 * @param id the identifier for this specification
160 * @param clazz the {@link CookieSpec cookie specification} class to register
161 *
162 * @see #getCookieSpec(String)
163 *
164 * @since 3.0
165 */
166 public static void registerCookieSpec(final String id, final Class clazz) {
167 if (id == null) {
168 throw new IllegalArgumentException("Id may not be null");
169 }
170 if (clazz == null) {
171 throw new IllegalArgumentException("Cookie spec class may not be null");
172 }
173 SPECS.put(id.toLowerCase(), clazz);
174 }
175
176 /***
177 * Unregisters the {@link CookieSpec cookie specification} with the given ID.
178 *
179 * @param id the ID of the {@link CookieSpec cookie specification} to unregister
180 *
181 * @since 3.0
182 */
183 public static void unregisterCookieSpec(final String id) {
184 if (id == null) {
185 throw new IllegalArgumentException("Id may not be null");
186 }
187 SPECS.remove(id.toLowerCase());
188 }
189
190 /***
191 * Gets the {@link CookieSpec cookie specification} with the given ID.
192 *
193 * @param id the {@link CookieSpec cookie specification} ID
194 *
195 * @return {@link CookieSpec cookie specification}
196 *
197 * @throws IllegalStateException if a policy with the ID cannot be found
198 *
199 * @since 3.0
200 */
201 public static CookieSpec getCookieSpec(final String id)
202 throws IllegalStateException {
203
204 if (id == null) {
205 throw new IllegalArgumentException("Id may not be null");
206 }
207 Class clazz = (Class)SPECS.get(id.toLowerCase());
208
209 if (clazz != null) {
210 try {
211 return (CookieSpec)clazz.newInstance();
212 } catch (Exception e) {
213 LOG.error("Error initializing cookie spec: " + id, e);
214 throw new IllegalStateException(id +
215 " cookie spec implemented by " +
216 clazz.getName() + " could not be initialized");
217 }
218 } else {
219 throw new IllegalStateException("Unsupported cookie spec " + id);
220 }
221 }
222
223 /***
224 * @return default cookie policy
225 *
226 * @deprecated Use {@link #getDefaultSpec()}
227 *
228 * @see #getDefaultSpec()
229 */
230 public static int getDefaultPolicy() {
231 return defaultPolicy;
232 }
233
234
235 /***
236 * @param policy new default cookie policy
237 *
238 * @deprecated Use {@link CookiePolicy#registerCookieSpec(String, Class)}
239 * @see #DEFAULT
240 */
241 public static void setDefaultPolicy(int policy) {
242 defaultPolicy = policy;
243 }
244
245 /***
246 * @param policy cookie policy to get the CookieSpec for
247 * @return cookie specification interface for the given policy
248 *
249 * @deprecated Use {@link CookiePolicy#getCookieSpec(String)}
250 */
251 public static CookieSpec getSpecByPolicy(int policy) {
252 switch(policy) {
253 case COMPATIBILITY:
254 return new CookieSpecBase();
255 case NETSCAPE_DRAFT:
256 return new NetscapeDraftSpec();
257 case RFC2109:
258 return new RFC2109Spec();
259 case RFC2965:
260 return new RFC2965Spec();
261 default:
262 return getDefaultSpec();
263 }
264 }
265
266
267 /***
268 * Returns {@link CookieSpec cookie specification} registered as {@link #DEFAULT}.
269 * If no default {@link CookieSpec cookie specification} has been registered,
270 * {@link RFC2109Spec RFC2109 specification} is returned.
271 *
272 * @return default {@link CookieSpec cookie specification}
273 *
274 * @see #DEFAULT
275 */
276 public static CookieSpec getDefaultSpec() {
277 try {
278 return getCookieSpec(DEFAULT);
279 } catch (IllegalStateException e) {
280 LOG.warn("Default cookie policy is not registered");
281 return new RFC2109Spec();
282 }
283 }
284
285
286 /***
287 * Gets the CookieSpec for a particular cookie version.
288 *
289 * <p>Supported versions:
290 * <ul>
291 * <li><tt>version 0</tt> corresponds to the Netscape draft
292 * <li><tt>version 1</tt> corresponds to the RFC 2109
293 * <li>Any other cookie value coresponds to the default spec
294 * <ul>
295 *
296 * @param ver the cookie version to get the spec for
297 * @return cookie specification interface intended for processing
298 * cookies with the given version
299 *
300 * @deprecated Use {@link CookiePolicy#getCookieSpec(String)}
301 */
302 public static CookieSpec getSpecByVersion(int ver) {
303 switch(ver) {
304 case 0:
305 return new NetscapeDraftSpec();
306 case 1:
307 return new RFC2109Spec();
308 default:
309 return getDefaultSpec();
310 }
311 }
312
313 /***
314 * @return cookie specification interface that provides high compatibilty
315 * with common cookie management of popular HTTP agents
316 *
317 * @deprecated Use {@link CookiePolicy#getCookieSpec(String)}
318 */
319 public static CookieSpec getCompatibilitySpec() {
320 return getSpecByPolicy(COMPATIBILITY);
321 }
322
323 /***
324 * Obtains the currently registered cookie policy names.
325 *
326 * Note that the DEFAULT policy (if present) is likely to be the same
327 * as one of the other policies, but does not have to be.
328 *
329 * @return array of registered cookie policy names
330 *
331 * @since 3.1
332 */
333 public static String[] getRegisteredCookieSpecs(){
334 return (String[]) SPECS.keySet().toArray(new String [SPECS.size()]);
335 }
336
337 }