001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2010–2011 ApexIdentity Inc. 015 * Portions Copyright 2011-2015 ForgeRock AS. 016 */ 017 018package org.forgerock.http.protocol; 019 020import java.util.ArrayList; 021import java.util.Date; 022import java.util.List; 023 024/** 025 * An HTTP cookie. For more information, see the original <a href= 026 * "http://web.archive.org/web/20070805052634/http://wp.netscape.com/newsref/std/cookie_spec.html" 027 * > Netscape specification</a>, <a 028 * href="http://www.ietf.org/rfc/rfc2109.txt">RFC 2109</a> and <a 029 * href="http://www.ietf.org/rfc/rfc2965.txt">RFC 2965</a>. 030 */ 031public class Cookie { 032 /** The name of the cookie. */ 033 private String name; 034 035 /** The value of the cookie. */ 036 private String value; 037 038 /** The intended use of a cookie. */ 039 private String comment; 040 041 /** URL identifying the intended use of a cookie. */ 042 private String commentURL; 043 044 /** 045 * Directs the user agent to discard the cookie unconditionally when it 046 * terminates. 047 */ 048 private Boolean discard; 049 050 /** The domain for which the cookie is valid. */ 051 private String domain; 052 053 /** 054 * The lifetime of the cookie, expressed as the date and time of expiration. 055 */ 056 private Date expires; 057 058 /** 059 * Directs the user agent to make the cookie inaccessible to client side 060 * script. 061 */ 062 private Boolean httpOnly; 063 064 /** The lifetime of the cookie, expressed in seconds. */ 065 private Integer maxAge; 066 067 /** The subset of URLs on the origin server to which this cookie applies. */ 068 private String path; 069 070 /** Restricts the port(s) to which a cookie may be returned. */ 071 private final List<Integer> port = new ArrayList<>(); 072 073 /** 074 * Directs the user agent to use only secure means to send back this cookie. 075 */ 076 private Boolean secure; 077 078 /** 079 * The version of the state management mechanism to which this cookie 080 * conforms. 081 */ 082 private Integer version; 083 084 /** 085 * Creates a new uninitialized cookie. 086 */ 087 public Cookie() { 088 // Empty cookie. 089 } 090 091 @Override 092 public boolean equals(final Object obj) { 093 if (this == obj) { 094 return true; 095 } 096 if (!(obj instanceof Cookie)) { 097 return false; 098 } 099 final Cookie other = (Cookie) obj; 100 return objectsAreEqual(comment, other.comment) 101 && objectsAreEqual(commentURL, other.commentURL) 102 && objectsAreEqual(discard, other.discard) 103 && objectsAreEqual(domain, other.domain) 104 && objectsAreEqual(expires, other.expires) 105 && objectsAreEqual(httpOnly, other.httpOnly) 106 && objectsAreEqual(maxAge, other.maxAge) 107 && objectsAreEqual(name, other.name) 108 && objectsAreEqual(path, other.path) 109 && objectsAreEqual(port, other.port) 110 && objectsAreEqual(secure, other.secure) 111 && objectsAreEqual(value, other.value) 112 && objectsAreEqual(version, other.version); 113 } 114 115 /** 116 * Returns the intended use of a cookie. 117 * 118 * @return The intended use of a cookie. 119 */ 120 public String getComment() { 121 return comment; 122 } 123 124 /** 125 * Returns the URL identifying the intended use of a cookie. 126 * 127 * @return The URL identifying the intended use of a cookie. 128 */ 129 public String getCommentURL() { 130 return commentURL; 131 } 132 133 /** 134 * Returns {@code true} if the user agent should discard the cookie 135 * unconditionally when it terminates. 136 * 137 * @return {@code true} if the user agent should discard the cookie 138 * unconditionally when it terminates. 139 */ 140 public Boolean getDiscard() { 141 return discard; 142 } 143 144 /** 145 * Returns the domain for which the cookie is valid. 146 * 147 * @return The domain for which the cookie is valid. 148 */ 149 public String getDomain() { 150 return domain; 151 } 152 153 /** 154 * Returns the lifetime of the cookie, expressed as the date and time of 155 * expiration. 156 * 157 * @return The lifetime of the cookie, expressed as the date and time of 158 * expiration. 159 */ 160 public Date getExpires() { 161 return expires; 162 } 163 164 /** 165 * Returns {@code true} if the user agent should make the cookie 166 * inaccessible to client side script. 167 * 168 * @return {@code true} if the user agent should make the cookie 169 * inaccessible to client side script. 170 */ 171 public Boolean isHttpOnly() { 172 return httpOnly == null ? false : httpOnly; 173 } 174 175 /** 176 * Returns the lifetime of the cookie, expressed in seconds. 177 * 178 * @return The lifetime of the cookie, expressed in seconds. 179 */ 180 public Integer getMaxAge() { 181 return maxAge; 182 } 183 184 /** 185 * Returns name of the cookie. 186 * 187 * @return The name of the cookie. 188 */ 189 public String getName() { 190 return name; 191 } 192 193 /** 194 * Returns the subset of URLs on the origin server to which this cookie 195 * applies. 196 * 197 * @return The subset of URLs on the origin server to which this cookie 198 * applies. 199 */ 200 public String getPath() { 201 return path; 202 } 203 204 /** 205 * Returns the restricted list of port(s) to which a cookie may be returned. 206 * 207 * @return The restricted list of port(s) to which a cookie may be returned. 208 */ 209 public List<Integer> getPort() { 210 return port; 211 } 212 213 /** 214 * Returns {@code true} if the user agent should use only secure means to 215 * send back this cookie. 216 * 217 * @return {@code true} if the user agent should use only secure means to 218 * send back this cookie. 219 */ 220 public Boolean isSecure() { 221 return secure == null ? false : secure; 222 } 223 224 /** 225 * Returns the value of the cookie. 226 * 227 * @return The value of the cookie. 228 */ 229 public String getValue() { 230 return value; 231 } 232 233 /** 234 * Returns the version of the state management mechanism to which this 235 * cookie conforms. 236 * 237 * @return The version of the state management mechanism to which this 238 * cookie conforms. 239 */ 240 public Integer getVersion() { 241 return version; 242 } 243 244 @Override 245 public int hashCode() { 246 final int prime = 31; 247 int result = 1; 248 result = prime * result + (comment == null ? 0 : comment.hashCode()); 249 result = prime * result + (commentURL == null ? 0 : commentURL.hashCode()); 250 result = prime * result + (discard == null ? 0 : discard.hashCode()); 251 result = prime * result + (domain == null ? 0 : domain.hashCode()); 252 result = prime * result + (expires == null ? 0 : expires.hashCode()); 253 result = prime * result + (httpOnly == null ? 0 : httpOnly.hashCode()); 254 result = prime * result + (maxAge == null ? 0 : maxAge.hashCode()); 255 result = prime * result + (name == null ? 0 : name.hashCode()); 256 result = prime * result + (path == null ? 0 : path.hashCode()); 257 result = prime * result + (port == null ? 0 : port.hashCode()); 258 result = prime * result + (secure == null ? 0 : secure.hashCode()); 259 result = prime * result + (value == null ? 0 : value.hashCode()); 260 result = prime * result + (version == null ? 0 : version.hashCode()); 261 return result; 262 } 263 264 /** 265 * Sets the intended use of a cookie. 266 * 267 * @param comment 268 * The intended use of a cookie. 269 * @return This cookie. 270 */ 271 public Cookie setComment(final String comment) { 272 this.comment = comment; 273 return this; 274 } 275 276 /** 277 * Sets the URL identifying the intended use of a cookie. 278 * 279 * @param commentURL 280 * The URL identifying the intended use of a cookie. 281 * @return This cookie. 282 */ 283 public Cookie setCommentURL(final String commentURL) { 284 this.commentURL = commentURL; 285 return this; 286 } 287 288 /** 289 * Sets the value indicating whether the user agent should discard the 290 * cookie unconditionally when it terminates. 291 * 292 * @param discard 293 * {@code true} if the user agent should discard the cookie 294 * unconditionally when it terminates. 295 * @return This cookie. 296 */ 297 public Cookie setDiscard(final Boolean discard) { 298 this.discard = discard; 299 return this; 300 } 301 302 /** 303 * Sets the domain for which the cookie is valid. 304 * 305 * @param domain 306 * The domain for which the cookie is valid. 307 * @return This cookie. 308 */ 309 public Cookie setDomain(final String domain) { 310 this.domain = domain; 311 return this; 312 } 313 314 /** 315 * Sets the lifetime of the cookie, expressed as the date and time of 316 * expiration. 317 * 318 * @param expires 319 * The lifetime of the cookie, expressed as the date and time of 320 * expiration. 321 * @return This cookie. 322 */ 323 public Cookie setExpires(final Date expires) { 324 this.expires = expires; 325 return this; 326 } 327 328 /** 329 * Sets the value indicating whether the user agent should make the cookie 330 * inaccessible to client side script. 331 * 332 * @param httpOnly 333 * {@code true} if the user agent should make the cookie 334 * inaccessible to client side script. 335 * @return this; 336 */ 337 public Cookie setHttpOnly(final Boolean httpOnly) { 338 this.httpOnly = httpOnly; 339 return this; 340 } 341 342 /** 343 * Sets the lifetime of the cookie, expressed in seconds. 344 * 345 * @param maxAge 346 * The lifetime of the cookie, expressed in seconds. 347 * @return This cookie. 348 */ 349 public Cookie setMaxAge(final Integer maxAge) { 350 this.maxAge = maxAge; 351 return this; 352 } 353 354 /** 355 * Sets the name of the cookie. 356 * 357 * @param name 358 * The name of the cookie. 359 * @return This cookie. 360 */ 361 public Cookie setName(final String name) { 362 this.name = name; 363 return this; 364 } 365 366 /** 367 * Sets the subset of URLs on the origin server to which this cookie 368 * applies. 369 * 370 * @param path 371 * The subset of URLs on the origin server to which this cookie 372 * applies. 373 * @return This cookie. 374 */ 375 public Cookie setPath(final String path) { 376 this.path = path; 377 return this; 378 } 379 380 /** 381 * Sets the value indicating whether the user agent should use only secure 382 * means to send back this cookie. 383 * 384 * @param secure 385 * {@code true} if the user agent should use only secure means to 386 * send back this cookie. 387 * @return This cookie. 388 */ 389 public Cookie setSecure(final Boolean secure) { 390 this.secure = secure; 391 return this; 392 } 393 394 /** 395 * Sets the value of the cookie. 396 * 397 * @param value 398 * The value of the cookie. 399 * @return This cookie. 400 */ 401 public Cookie setValue(final String value) { 402 this.value = value; 403 return this; 404 } 405 406 /** 407 * Sets the version of the state management mechanism to which this cookie 408 * conforms. 409 * 410 * @param version 411 * The version of the state management mechanism to which this 412 * cookie conforms. 413 * @return This cookie. 414 */ 415 public Cookie setVersion(final Integer version) { 416 this.version = version; 417 return this; 418 } 419 420 @Override 421 public String toString() { 422 final StringBuilder builder = new StringBuilder(); 423 builder.append("["); 424 if (name != null) { 425 builder.append("name=").append(name).append(" "); 426 } 427 if (value != null) { 428 builder.append("value=").append(value).append(" "); 429 } 430 if (comment != null) { 431 builder.append("comment=").append(comment).append(" "); 432 } 433 if (commentURL != null) { 434 builder.append("commentURL=").append(commentURL).append(" "); 435 } 436 if (discard != null) { 437 builder.append("discard=").append(discard).append(" "); 438 } 439 if (domain != null) { 440 builder.append("domain=").append(domain).append(" "); 441 } 442 if (expires != null) { 443 builder.append("expires=").append(expires).append(" "); 444 } 445 if (httpOnly != null) { 446 builder.append("httpOnly=").append(httpOnly).append(" "); 447 } 448 if (maxAge != null) { 449 builder.append("maxAge=").append(maxAge).append(" "); 450 } 451 if (path != null) { 452 builder.append("path=").append(path).append(" "); 453 } 454 if (port != null) { 455 builder.append("port=").append(port).append(" "); 456 } 457 if (secure != null) { 458 builder.append("secure=").append(secure).append(" "); 459 } 460 if (version != null) { 461 builder.append("version=").append(version); 462 } 463 builder.append("]"); 464 return builder.toString(); 465 } 466 467 private static boolean objectsAreEqual(final Object o1, final Object o2) { 468 if (o1 == null) { 469 return o2 == null; 470 } else { 471 return o1.equals(o2); 472 } 473 } 474 475}