Added basic session support.
[jsvc.git] / src / dolda / jsvc / util / Cookie.java
CommitLineData
141e5e3c
FT
1package dolda.jsvc.util;
2
3import dolda.jsvc.*;
4import java.util.*;
5import java.text.*;
6import java.io.*;
7
8public class Cookie {
d5dd6a2d 9 private final static Map<Request, MultiMap<String, Cookie>> cache = new WeakHashMap<Request, MultiMap<String, Cookie>>();
141e5e3c
FT
10 public final static DateFormat datefmt;
11 static {
12 datefmt = new SimpleDateFormat("EEE, dd-MMM-yyyy HH:mm:ss z", Locale.ENGLISH);
13 datefmt.setCalendar(Calendar.getInstance(TimeZone.getTimeZone("UTC")));
14 }
15 public final String name;
16 public String value;
17 public Date expires;
18 public String domain, path;
19 public boolean secure;
20
21 public Cookie(String name, String value, Date expires, String domain, String path, boolean secure) {
22 if(!Http.istoken(name))
23 throw(new RuntimeException("Invalid cookie name: `" + name + "'"));
24 this.name = name;
25 this.value = value;
26 this.expires = expires;
27 this.domain = domain;
28 this.path = path;
29 this.secure = secure;
30 }
31
32 public Cookie(String name) {
33 this(name, null, null, null, null, false);
34 }
35
36 public Cookie(String name, String value) {
37 this(name, value, null, null, null, false);
38 }
39
40 public String format() {
41 StringBuilder buf = new StringBuilder();
42 buf.append(Http.tokenquote(name));
43 buf.append('=');
44 buf.append(Http.tokenquote(value));
45 if(domain != null)
46 buf.append("; Domain=" + Http.tokenquote(domain));
47 if(path != null)
48 buf.append("; Path=" + Http.tokenquote(path));
49 if(expires != null)
50 buf.append("; Expires=" + Http.tokenquote(datefmt.format(expires)));
51 if(secure)
52 buf.append("; Secure");
53 return(buf.toString());
54 }
55
56 public void addto(Request req) {
57 req.outheaders().add("Set-Cookie", format());
58 }
59
60 public static MultiMap<String, Cookie> parse(Request req) {
61 MultiMap<String, Cookie> ret = new WrappedMultiMap<String, Cookie>(new TreeMap<String, Collection<Cookie>>());
62 for(String in : req.inheaders().values("Cookie")) {
63 try {
64 StringReader r = new StringReader(in);
65 Cookie c = null;
66 while(true) {
67 String k = Http.tokenunquote(r);
68 String v = Http.tokenunquote(r);
69 if(k == null)
70 break;
71 if(k.equals("$Version")) {
72 if(Integer.parseInt(v) != 1)
73 throw(new Http.EncodingException("Unknown cookie format version"));
74 } else if(k.equals("$Path")) {
75 if(c != null)
76 c.path = v;
77 } else if(k.equals("$Domain")) {
78 if(c != null)
79 c.domain = v;
80 } else {
81 c = new Cookie(k, v);
82 ret.add(k, c);
83 }
84 }
85 } catch(IOException e) {
86 throw(new Error(e));
87 }
88 }
89 return(ret);
90 }
91
d5dd6a2d
FT
92 public static MultiMap<String, Cookie> get(Request req) {
93 synchronized(cache) {
94 MultiMap<String, Cookie> ret = cache.get(req);
95 if(ret == null) {
96 ret = parse(req);
97 cache.put(req, ret);
98 }
99 return(ret);
100 }
101 }
102
141e5e3c
FT
103 public String toString() {
104 StringBuilder buf = new StringBuilder();
105 buf.append("Cookie(");
106 buf.append(format());
107 buf.append(")");
108 return(buf.toString());
109 }
110}