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-2014 ForgeRock AS. 016 */ 017 018package org.forgerock.openig.http; 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<Integer>(); 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) && objectsAreEqual(domain, other.domain) 103 && objectsAreEqual(expires, other.expires) 104 && objectsAreEqual(httpOnly, other.httpOnly) 105 && objectsAreEqual(maxAge, other.maxAge) && objectsAreEqual(name, other.name) 106 && objectsAreEqual(path, other.path) && objectsAreEqual(port, other.port) 107 && objectsAreEqual(secure, other.secure) && objectsAreEqual(value, other.value) 108 && objectsAreEqual(version, other.version); 109 } 110 111 /** 112 * Returns the intended use of a cookie. 113 * 114 * @return The intended use of a cookie. 115 */ 116 public String getComment() { 117 return comment; 118 } 119 120 /** 121 * Returns the URL identifying the intended use of a cookie. 122 * 123 * @return The URL identifying the intended use of a cookie. 124 */ 125 public String getCommentURL() { 126 return commentURL; 127 } 128 129 /** 130 * Returns {@code true} if the user agent should discard the cookie 131 * unconditionally when it terminates. 132 * 133 * @return {@code true} if the user agent should discard the cookie 134 * unconditionally when it terminates. 135 */ 136 public Boolean getDiscard() { 137 return discard; 138 } 139 140 /** 141 * Returns the domain for which the cookie is valid. 142 * 143 * @return The domain for which the cookie is valid. 144 */ 145 public String getDomain() { 146 return domain; 147 } 148 149 /** 150 * Returns the lifetime of the cookie, expressed as the date and time of 151 * expiration. 152 * 153 * @return The lifetime of the cookie, expressed as the date and time of 154 * expiration. 155 */ 156 public Date getExpires() { 157 return expires; 158 } 159 160 /** 161 * Returns {@code true} if the user agent should make the cookie 162 * inaccessible to client side script. 163 * 164 * @return {@code true} if the user agent should make the cookie 165 * inaccessible to client side script. 166 */ 167 public Boolean getHttpOnly() { 168 return httpOnly; 169 } 170 171 /** 172 * Returns the lifetime of the cookie, expressed in seconds. 173 * 174 * @return The lifetime of the cookie, expressed in seconds. 175 */ 176 public Integer getMaxAge() { 177 return maxAge; 178 } 179 180 /** 181 * Returns name of the cookie. 182 * 183 * @return The name of the cookie. 184 */ 185 public String getName() { 186 return name; 187 } 188 189 /** 190 * Returns the subset of URLs on the origin server to which this cookie 191 * applies. 192 * 193 * @return The subset of URLs on the origin server to which this cookie 194 * applies. 195 */ 196 public String getPath() { 197 return path; 198 } 199 200 /** 201 * Returns the restricted list of port(s) to which a cookie may be returned. 202 * 203 * @return The restricted list of port(s) to which a cookie may be returned. 204 */ 205 public List<Integer> getPort() { 206 return port; 207 } 208 209 /** 210 * Returns {@code true} if the user agent should use only secure means to 211 * send back this cookie. 212 * 213 * @return {@code true} if the user agent should use only secure means to 214 * send back this cookie. 215 */ 216 public Boolean getSecure() { 217 return secure; 218 } 219 220 /** 221 * Returns the value of the cookie. 222 * 223 * @return The value of the cookie. 224 */ 225 public String getValue() { 226 return value; 227 } 228 229 /** 230 * Returns the version of the state management mechanism to which this 231 * cookie conforms. 232 * 233 * @return The version of the state management mechanism to which this 234 * cookie conforms. 235 */ 236 public Integer getVersion() { 237 return version; 238 } 239 240 @Override 241 public int hashCode() { 242 final int prime = 31; 243 int result = 1; 244 result = prime * result + (comment == null ? 0 : comment.hashCode()); 245 result = prime * result + (commentURL == null ? 0 : commentURL.hashCode()); 246 result = prime * result + (discard == null ? 0 : discard.hashCode()); 247 result = prime * result + (domain == null ? 0 : domain.hashCode()); 248 result = prime * result + (expires == null ? 0 : expires.hashCode()); 249 result = prime * result + (httpOnly == null ? 0 : httpOnly.hashCode()); 250 result = prime * result + (maxAge == null ? 0 : maxAge.hashCode()); 251 result = prime * result + (name == null ? 0 : name.hashCode()); 252 result = prime * result + (path == null ? 0 : path.hashCode()); 253 result = prime * result + (port == null ? 0 : port.hashCode()); 254 result = prime * result + (secure == null ? 0 : secure.hashCode()); 255 result = prime * result + (value == null ? 0 : value.hashCode()); 256 result = prime * result + (version == null ? 0 : version.hashCode()); 257 return result; 258 } 259 260 /** 261 * Sets the intended use of a cookie. 262 * 263 * @param comment 264 * The intended use of a cookie. 265 * @return This cookie. 266 */ 267 public Cookie setComment(final String comment) { 268 this.comment = comment; 269 return this; 270 } 271 272 /** 273 * Sets the URL identifying the intended use of a cookie. 274 * 275 * @param commentURL 276 * The URL identifying the intended use of a cookie. 277 * @return This cookie. 278 */ 279 public Cookie setCommentURL(final String commentURL) { 280 this.commentURL = commentURL; 281 return this; 282 } 283 284 /** 285 * Sets the value indicating whether the user agent should discard the 286 * cookie unconditionally when it terminates. 287 * 288 * @param discard 289 * {@code true} if the user agent should discard the cookie 290 * unconditionally when it terminates. 291 * @return This cookie. 292 */ 293 public Cookie setDiscard(final Boolean discard) { 294 this.discard = discard; 295 return this; 296 } 297 298 /** 299 * Sets the domain for which the cookie is valid. 300 * 301 * @param domain 302 * The domain for which the cookie is valid. 303 * @return This cookie. 304 */ 305 public Cookie setDomain(final String domain) { 306 this.domain = domain; 307 return this; 308 } 309 310 /** 311 * Sets the lifetime of the cookie, expressed as the date and time of 312 * expiration. 313 * 314 * @param expires 315 * The lifetime of the cookie, expressed as the date and time of 316 * expiration. 317 * @return This cookie. 318 */ 319 public Cookie setExpires(final Date expires) { 320 this.expires = expires; 321 return this; 322 } 323 324 /** 325 * Sets the value indicating whether the user agent should make the cookie 326 * inaccessible to client side script. 327 * 328 * @param httpOnly 329 * {@code true} if the user agent should make the cookie 330 * inaccessible to client side script. 331 * @return this; 332 */ 333 public Cookie setHttpOnly(final Boolean httpOnly) { 334 this.httpOnly = httpOnly; 335 return this; 336 } 337 338 /** 339 * Sets the lifetime of the cookie, expressed in seconds. 340 * 341 * @param maxAge 342 * The lifetime of the cookie, expressed in seconds. 343 * @return This cookie. 344 */ 345 public Cookie setMaxAge(final Integer maxAge) { 346 this.maxAge = maxAge; 347 return this; 348 } 349 350 /** 351 * Sets the name of the cookie. 352 * 353 * @param name 354 * The name of the cookie. 355 * @return This cookie. 356 */ 357 public Cookie setName(final String name) { 358 this.name = name; 359 return this; 360 } 361 362 /** 363 * Sets the subset of URLs on the origin server to which this cookie 364 * applies. 365 * 366 * @param path 367 * The subset of URLs on the origin server to which this cookie 368 * applies. 369 * @return This cookie. 370 */ 371 public Cookie setPath(final String path) { 372 this.path = path; 373 return this; 374 } 375 376 /** 377 * Sets the value indicating whether the user agent should use only secure 378 * means to send back this cookie. 379 * 380 * @param secure 381 * {@code true} if the user agent should use only secure means to 382 * send back this cookie. 383 * @return This cookie. 384 */ 385 public Cookie setSecure(final Boolean secure) { 386 this.secure = secure; 387 return this; 388 } 389 390 /** 391 * Sets the value of the cookie. 392 * 393 * @param value 394 * The value of the cookie. 395 * @return This cookie. 396 */ 397 public Cookie setValue(final String value) { 398 this.value = value; 399 return this; 400 } 401 402 /** 403 * Sets the version of the state management mechanism to which this cookie 404 * conforms. 405 * 406 * @param version 407 * The version of the state management mechanism to which this 408 * cookie conforms. 409 * @return This cookie. 410 */ 411 public Cookie setVersion(final Integer version) { 412 this.version = version; 413 return this; 414 } 415 416 @Override 417 public String toString() { 418 final StringBuilder builder = new StringBuilder(); 419 builder.append("["); 420 if (name != null) { 421 builder.append("name=").append(name).append(" "); 422 } 423 if (value != null) { 424 builder.append("value=").append(value).append(" "); 425 } 426 if (comment != null) { 427 builder.append("comment=").append(comment).append(" "); 428 } 429 if (commentURL != null) { 430 builder.append("commentURL=").append(commentURL).append(" "); 431 } 432 if (discard != null) { 433 builder.append("discard=").append(discard).append(" "); 434 } 435 if (domain != null) { 436 builder.append("domain=").append(domain).append(" "); 437 } 438 if (expires != null) { 439 builder.append("expires=").append(expires).append(" "); 440 } 441 if (httpOnly != null) { 442 builder.append("httpOnly=").append(httpOnly).append(" "); 443 } 444 if (maxAge != null) { 445 builder.append("maxAge=").append(maxAge).append(" "); 446 } 447 if (path != null) { 448 builder.append("path=").append(path).append(" "); 449 } 450 if (port != null) { 451 builder.append("port=").append(port).append(" "); 452 } 453 if (secure != null) { 454 builder.append("secure=").append(secure).append(" "); 455 } 456 if (version != null) { 457 builder.append("version=").append(version); 458 } 459 builder.append("]"); 460 return builder.toString(); 461 } 462 463 private static boolean objectsAreEqual(final Object o1, final Object o2) { 464 if (o1 == null) { 465 return o2 == null; 466 } else { 467 return o1.equals(o2); 468 } 469 } 470 471}