1 /*
2 * Copyright (c) 2002-2025 Gargoyle Software Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 * https://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 package org.htmlunit;
16
17 import java.io.Serializable;
18 import java.util.Collections;
19 import java.util.Date;
20 import java.util.Iterator;
21 import java.util.LinkedHashSet;
22 import java.util.Objects;
23 import java.util.Set;
24
25 import org.htmlunit.util.Cookie;
26
27 /**
28 * Manages cookies for a {@link WebClient}. This class is thread-safe.
29 * You can disable Cookies by calling setCookiesEnabled(false). The
30 * CookieManager itself takes care of this and ignores all cookie request if
31 * disabled. If you override this your methods have to do the same.
32 *
33 * @author Daniel Gredler
34 * @author Ahmed Ashour
35 * @author Nicolas Belisle
36 * @author Ronald Brill
37 */
38 public class CookieManager implements Serializable {
39
40 /** Whether or not cookies are enabled. */
41 private boolean cookiesEnabled_;
42
43 /** The cookies added to this cookie manager. */
44 private final Set<Cookie> cookies_ = new LinkedHashSet<>();
45
46 /**
47 * Creates a new instance.
48 */
49 public CookieManager() {
50 cookiesEnabled_ = true;
51 }
52
53 /**
54 * Enables/disables cookie support. Cookies are enabled by default.
55 * @param enabled {@code true} to enable cookie support, {@code false} otherwise
56 */
57 public synchronized void setCookiesEnabled(final boolean enabled) {
58 cookiesEnabled_ = enabled;
59 }
60
61 /**
62 * Returns {@code true} if cookies are enabled. Cookies are enabled by default.
63 * @return {@code true} if cookies are enabled, {@code false} otherwise
64 */
65 public synchronized boolean isCookiesEnabled() {
66 return cookiesEnabled_;
67 }
68
69 /**
70 * Returns the currently configured cookies, in an unmodifiable set.
71 * If disabled, this returns an empty set.
72 * @return the currently configured cookies, in an unmodifiable set
73 */
74 public synchronized Set<Cookie> getCookies() {
75 if (!isCookiesEnabled()) {
76 return Collections.emptySet();
77 }
78
79 final Set<Cookie> copy = new LinkedHashSet<>(cookies_);
80 return Collections.unmodifiableSet(copy);
81 }
82
83 /**
84 * Clears all cookies that have expired before supplied date.
85 * If disabled, this returns false.
86 * @param date the date to use for comparison when clearing expired cookies
87 * @return whether any cookies were found expired, and were cleared
88 */
89 public synchronized boolean clearExpired(final Date date) {
90 if (!isCookiesEnabled()) {
91 return false;
92 }
93
94 if (date == null) {
95 return false;
96 }
97
98 boolean foundExpired = false;
99 for (final Iterator<Cookie> iter = cookies_.iterator(); iter.hasNext();) {
100 final Cookie cookie = iter.next();
101 if (cookie.getExpires() != null && date.after(cookie.getExpires())) {
102 iter.remove();
103 foundExpired = true;
104 }
105 }
106 return foundExpired;
107 }
108
109 /**
110 * Returns the currently configured cookie with the specified name, or {@code null} if one does not exist.
111 * If disabled, this returns null.
112 * @param name the name of the cookie to return
113 * @return the currently configured cookie with the specified name, or {@code null} if one does not exist
114 */
115 public synchronized Cookie getCookie(final String name) {
116 if (!isCookiesEnabled()) {
117 return null;
118 }
119
120 for (final Cookie cookie : cookies_) {
121 if (Objects.equals(cookie.getName(), name)) {
122 return cookie;
123 }
124 }
125 return null;
126 }
127
128 /**
129 * Adds the specified cookie.
130 * If disabled, this does nothing.
131 * @param cookie the cookie to add
132 */
133 public synchronized void addCookie(final Cookie cookie) {
134 if (!isCookiesEnabled()) {
135 return;
136 }
137
138 cookies_.remove(cookie);
139
140 // don't add expired cookie
141 if (cookie.getExpires() == null || cookie.getExpires().after(new Date())) {
142 cookies_.add(cookie);
143 }
144 }
145
146 /**
147 * Removes the specified cookie.
148 * If disabled, this does nothing.
149 * @param cookie the cookie to remove
150 */
151 public synchronized void removeCookie(final Cookie cookie) {
152 if (!isCookiesEnabled()) {
153 return;
154 }
155
156 cookies_.remove(cookie);
157 }
158
159 /**
160 * Removes all cookies.
161 * If disabled, this does nothing.
162 */
163 public synchronized void clearCookies() {
164 if (!isCookiesEnabled()) {
165 return;
166 }
167
168 cookies_.clear();
169 }
170 }