1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.handler.codec.http2;
17
18 import java.util.Collections;
19 import java.util.Set;
20 import java.util.TreeSet;
21
22
23
24
25
26
27
28
29
30
31
32 public class DefaultCookie implements Cookie {
33
34 private static final Set<String> RESERVED_NAMES = new TreeSet<String>(CaseIgnoringComparator.INSTANCE);
35
36 static {
37 RESERVED_NAMES.add("Domain");
38 RESERVED_NAMES.add("Path");
39 RESERVED_NAMES.add("Comment");
40 RESERVED_NAMES.add("CommentURL");
41 RESERVED_NAMES.add("Discard");
42 RESERVED_NAMES.add("Port");
43 RESERVED_NAMES.add("Max-Age");
44 RESERVED_NAMES.add("Expires");
45 RESERVED_NAMES.add("Version");
46 RESERVED_NAMES.add("Secure");
47 RESERVED_NAMES.add("HTTPOnly");
48 }
49
50 private final String name;
51 private String value;
52 private String domain;
53 private String path;
54 private String comment;
55 private String commentUrl;
56 private boolean discard;
57 private Set<Integer> ports = Collections.emptySet();
58 private Set<Integer> unmodifiablePorts = ports;
59 private int maxAge = -1;
60 private int version;
61 private boolean secure;
62 private boolean httpOnly;
63
64
65
66
67 public DefaultCookie(String name, String value) {
68 if (name == null) {
69 throw new NullPointerException("name");
70 }
71 name = name.trim();
72 if (name.length() == 0) {
73 throw new IllegalArgumentException("empty name");
74 }
75
76 for (int i = 0; i < name.length(); i ++) {
77 char c = name.charAt(i);
78 if (c > 127) {
79 throw new IllegalArgumentException(
80 "name contains non-ascii character: " + name);
81 }
82
83
84 switch (c) {
85 case '\t': case '\n': case 0x0b: case '\f': case '\r':
86 case ' ': case ',': case ';': case '=':
87 throw new IllegalArgumentException(
88 "name contains one of the following prohibited characters: " +
89 "=,; \\t\\r\\n\\v\\f: " + name);
90 }
91 }
92
93 if (RESERVED_NAMES.contains(name)) {
94 throw new IllegalArgumentException("reserved name: " + name);
95 }
96
97 this.name = name;
98 setValue(value);
99 }
100
101 public String getName() {
102 return name;
103 }
104
105 public String getValue() {
106 return value;
107 }
108
109 public void setValue(String value) {
110 if (value == null) {
111 throw new NullPointerException("value");
112 }
113 this.value = value;
114 }
115
116 public String getDomain() {
117 return domain;
118 }
119
120 public void setDomain(String domain) {
121 this.domain = validateValue("domain", domain);
122 }
123
124 public String getPath() {
125 return path;
126 }
127
128 public void setPath(String path) {
129 this.path = validateValue("path", path);
130 }
131
132 public String getComment() {
133 return comment;
134 }
135
136 public void setComment(String comment) {
137 this.comment = validateValue("comment", comment);
138 }
139
140 public String getCommentUrl() {
141 return commentUrl;
142 }
143
144 public void setCommentUrl(String commentUrl) {
145 this.commentUrl = validateValue("commentUrl", commentUrl);
146 }
147
148 public boolean isDiscard() {
149 return discard;
150 }
151
152 public void setDiscard(boolean discard) {
153 this.discard = discard;
154 }
155
156 public Set<Integer> getPorts() {
157 if (unmodifiablePorts == null) {
158 unmodifiablePorts = Collections.unmodifiableSet(ports);
159 }
160 return unmodifiablePorts;
161 }
162
163 public void setPorts(int... ports) {
164 if (ports == null) {
165 throw new NullPointerException("ports");
166 }
167
168 int[] portsCopy = ports.clone();
169 if (portsCopy.length == 0) {
170 unmodifiablePorts = this.ports = Collections.emptySet();
171 } else {
172 Set<Integer> newPorts = new TreeSet<Integer>();
173 for (int p: portsCopy) {
174 if (p <= 0 || p > 65535) {
175 throw new IllegalArgumentException("port out of range: " + p);
176 }
177 newPorts.add(Integer.valueOf(p));
178 }
179 this.ports = newPorts;
180 unmodifiablePorts = null;
181 }
182 }
183
184 public void setPorts(Iterable<Integer> ports) {
185 Set<Integer> newPorts = new TreeSet<Integer>();
186 for (int p: ports) {
187 if (p <= 0 || p > 65535) {
188 throw new IllegalArgumentException("port out of range: " + p);
189 }
190 newPorts.add(Integer.valueOf(p));
191 }
192 if (newPorts.isEmpty()) {
193 unmodifiablePorts = this.ports = Collections.emptySet();
194 } else {
195 this.ports = newPorts;
196 unmodifiablePorts = null;
197 }
198 }
199
200 public int getMaxAge() {
201 return maxAge;
202 }
203
204 public void setMaxAge(int maxAge) {
205 if (maxAge < -1) {
206 throw new IllegalArgumentException(
207 "maxAge must be either -1, 0, or a positive integer: " +
208 maxAge);
209 }
210 this.maxAge = maxAge;
211 }
212
213 public int getVersion() {
214 return version;
215 }
216
217 public void setVersion(int version) {
218 this.version = version;
219 }
220
221 public boolean isSecure() {
222 return secure;
223 }
224
225 public void setSecure(boolean secure) {
226 this.secure = secure;
227 }
228
229 public boolean isHttpOnly() {
230 return httpOnly;
231 }
232
233 public void setHttpOnly(boolean httpOnly) {
234 this.httpOnly = httpOnly;
235 }
236
237 @Override
238 public int hashCode() {
239 return getName().hashCode();
240 }
241
242 @Override
243 public boolean equals(Object o) {
244 if (!(o instanceof Cookie)) {
245 return false;
246 }
247
248 Cookie that = (Cookie) o;
249 if (!getName().equalsIgnoreCase(that.getName())) {
250 return false;
251 }
252
253 if (getPath() == null && that.getPath() != null) {
254 return false;
255 } else if (that.getPath() == null) {
256 return false;
257 }
258 if (!getPath().equals(that.getPath())) {
259 return false;
260 }
261
262 if (getDomain() == null && that.getDomain() != null) {
263 return false;
264 } else if (that.getDomain() == null) {
265 return false;
266 }
267 if (!getDomain().equalsIgnoreCase(that.getDomain())) {
268 return false;
269 }
270
271 return true;
272 }
273
274 public int compareTo(Cookie c) {
275 int v;
276 v = getName().compareToIgnoreCase(c.getName());
277 if (v != 0) {
278 return v;
279 }
280
281 if (getPath() == null && c.getPath() != null) {
282 return -1;
283 } else if (c.getPath() == null) {
284 return 1;
285 }
286 v = getPath().compareTo(c.getPath());
287 if (v != 0) {
288 return v;
289 }
290
291 if (getDomain() == null && c.getDomain() != null) {
292 return -1;
293 } else if (c.getDomain() == null) {
294 return 1;
295 }
296 v = getDomain().compareToIgnoreCase(c.getDomain());
297 return v;
298 }
299
300 @Override
301 public String toString() {
302 StringBuilder buf = new StringBuilder();
303 buf.append(getName());
304 buf.append('=');
305 buf.append(getValue());
306 if (getDomain() != null) {
307 buf.append(", domain=");
308 buf.append(getDomain());
309 }
310 if (getPath() != null) {
311 buf.append(", path=");
312 buf.append(getPath());
313 }
314 if (getComment() != null) {
315 buf.append(", comment=");
316 buf.append(getComment());
317 }
318 if (getMaxAge() >= 0) {
319 buf.append(", maxAge=");
320 buf.append(getMaxAge());
321 buf.append('s');
322 }
323 if (isSecure()) {
324 buf.append(", secure");
325 }
326 if (isHttpOnly()) {
327 buf.append(", HTTPOnly");
328 }
329 return buf.toString();
330 }
331
332 private static String validateValue(String name, String value) {
333 if (value == null) {
334 return null;
335 }
336 value = value.trim();
337 if (value.length() == 0) {
338 return null;
339 }
340 for (int i = 0; i < value.length(); i ++) {
341 char c = value.charAt(i);
342 switch (c) {
343 case '\r': case '\n': case '\f': case 0x0b: case ';':
344 throw new IllegalArgumentException(
345 name + " contains one of the following prohibited characters: " +
346 ";\\r\\n\\f\\v (" + value + ')');
347 }
348 }
349 return value;
350 }
351 }