View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.hc.client5.http.impl.cookie;
29  
30  import java.io.Serializable;
31  import java.time.Instant;
32  import java.util.Date;
33  import java.util.HashMap;
34  import java.util.Locale;
35  import java.util.Map;
36  
37  import org.apache.hc.client5.http.cookie.SetCookie;
38  import org.apache.hc.client5.http.utils.DateUtils;
39  import org.apache.hc.core5.util.Args;
40  
41  /**
42   * Default implementation of {@link SetCookie}.
43   *
44   * @since 4.0
45   */
46  public final class BasicClientCookie implements SetCookie, Cloneable, Serializable {
47  
48      private static final long serialVersionUID = -3869795591041535538L;
49  
50      /**
51       * Default Constructor taking a name and a value. The value may be null.
52       *
53       * @param name The name.
54       * @param value The value.
55       */
56      public BasicClientCookie(final String name, final String value) {
57          super();
58          Args.notNull(name, "Name");
59          this.name = name;
60          this.attribs = new HashMap<>();
61          this.value = value;
62      }
63  
64      /**
65       * Returns the name.
66       *
67       * @return String name The name
68       */
69      @Override
70      public String getName() {
71          return this.name;
72      }
73  
74      /**
75       * Returns the value.
76       *
77       * @return String value The current value.
78       */
79      @Override
80      public String getValue() {
81          return this.value;
82      }
83  
84      /**
85       * Sets the value
86       *
87       * @param value
88       */
89      @Override
90      public void setValue(final String value) {
91          this.value = value;
92      }
93  
94      /**
95       * Returns the expiration {@link Date} of the cookie, or {@code null}
96       * if none exists.
97       * <p><strong>Note:</strong> the object returned by this method is
98       * considered immutable. Changing it (e.g. using setTime()) could result
99       * in undefined behaviour. Do so at your peril. </p>
100      * @return Expiration {@link Date}, or {@code null}.
101      *
102      * @see #setExpiryDate(java.util.Date)
103      *
104      * @deprecated Use {@link #getExpiryInstant()}
105      */
106     @Deprecated
107     @Override
108     public Date getExpiryDate() {
109         return DateUtils.toDate(cookieExpiryDate);
110     }
111 
112     /**
113      * {@inheritDoc}
114      */
115     @Override
116     public Instant getExpiryInstant() {
117         return cookieExpiryDate;
118     }
119 
120     /**
121      * Sets expiration date.
122      * <p><strong>Note:</strong> the object returned by this method is considered
123      * immutable. Changing it (e.g. using setTime()) could result in undefined
124      * behaviour. Do so at your peril.</p>
125      *
126      * @param expiryDate the {@link Date} after which this cookie is no longer valid.
127      *
128      * @deprecated Use {{@link #setExpiryDate(Instant)}}
129      *
130      */
131     @Deprecated
132     @Override
133     public void setExpiryDate (final Date expiryDate) {
134         cookieExpiryDate = DateUtils.toInstant(expiryDate);
135     }
136 
137     /**
138      * Sets expiration date.
139      * <p><strong>Note:</strong> the object returned by this method is considered
140      * immutable. Changing it (e.g. using setTime()) could result in undefined behaviour. Do so at
141      * your peril.</p>
142      *
143      * @param expiryInstant the {@link Instant} after which this cookie is no longer valid.
144      * @see #getExpiryInstant()
145      * @since 5.2
146      */
147     @Override
148     public void setExpiryDate (final Instant expiryInstant) {
149         cookieExpiryDate = expiryInstant;
150     }
151 
152 
153     /**
154      * Returns {@code false} if the cookie should be discarded at the end
155      * of the "session"; {@code true} otherwise.
156      *
157      * @return {@code false} if the cookie should be discarded at the end
158      *         of the "session"; {@code true} otherwise
159      */
160     @Override
161     public boolean isPersistent() {
162         return (null != cookieExpiryDate);
163     }
164 
165 
166     /**
167      * Returns domain attribute of the cookie.
168      *
169      * @return the value of the domain attribute
170      *
171      * @see #setDomain(java.lang.String)
172      */
173     @Override
174     public String getDomain() {
175         return cookieDomain;
176     }
177 
178     /**
179      * Sets the domain attribute.
180      *
181      * @param domain The value of the domain attribute
182      *
183      * @see #getDomain
184      */
185     @Override
186     public void setDomain(final String domain) {
187         if (domain != null) {
188             cookieDomain = domain.toLowerCase(Locale.ROOT);
189         } else {
190             cookieDomain = null;
191         }
192     }
193 
194 
195     /**
196      * Returns the path attribute of the cookie
197      *
198      * @return The value of the path attribute.
199      *
200      * @see #setPath(java.lang.String)
201      */
202     @Override
203     public String getPath() {
204         return cookiePath;
205     }
206 
207     /**
208      * Sets the path attribute.
209      *
210      * @param path The value of the path attribute
211      *
212      * @see #getPath
213      *
214      */
215     @Override
216     public void setPath(final String path) {
217         cookiePath = path;
218     }
219 
220     /**
221      * @return {@code true} if this cookie should only be sent over secure connections.
222      * @see #setSecure(boolean)
223      */
224     @Override
225     public boolean isSecure() {
226         return isSecure;
227     }
228 
229     /**
230      * Sets the secure attribute of the cookie.
231      * <p>
232      * When {@code true} the cookie should only be sent
233      * using a secure protocol (https).  This should only be set when
234      * the cookie's originating server used a secure protocol to set the
235      * cookie's value.
236      *
237      * @param secure The value of the secure attribute
238      *
239      * @see #isSecure()
240      */
241     @Override
242     public void setSecure (final boolean secure) {
243         isSecure = secure;
244     }
245 
246     /**
247      * Sets the http-only attribute of the cookie.
248      *
249      * @param httpOnly true if this cookie is to be marked as
250      * {@code httpOnly}, false otherwise
251      *
252      * @since 5.2
253      */
254     @Override
255     public void setHttpOnly(final boolean httpOnly) {
256         this.httpOnly = httpOnly;
257     }
258 
259     /**
260      * Returns true if this cookie has expired.
261      * @param date Current time
262      *
263      * @return {@code true} if the cookie has expired.
264      *
265      * @deprecated Use {@link #isExpired(Instant)}
266      */
267     @Deprecated
268     @Override
269     public boolean isExpired(final Date date) {
270         Args.notNull(date, "Date");
271         return (cookieExpiryDate != null
272             && cookieExpiryDate.compareTo(DateUtils.toInstant(date)) <= 0);
273     }
274 
275     /**
276      * Returns true if this cookie has expired.
277      * @param instant Current time
278      *
279      * @return {@code true} if the cookie has expired.
280      */
281     @Override
282     public boolean isExpired(final Instant instant) {
283         Args.notNull(instant, "Instant");
284         return (cookieExpiryDate != null
285                 && cookieExpiryDate.compareTo(instant) <= 0);
286     }
287 
288     /**
289      * @since 4.4
290      *
291      * @deprecated Use {@link #getCreationInstant()}.
292      */
293     @Deprecated
294     @Override
295     public Date getCreationDate() {
296         return DateUtils.toDate(creationDate);
297     }
298 
299     /**
300      * @since 5.2
301      */
302     @Override
303     public Instant getCreationInstant() {
304         return creationDate;
305     }
306 
307     /**
308      * @return true if this Cookie has been marked as {@code httpOnly}, false otherwise
309      * @see #setHttpOnly(boolean)
310      * @since 5.2
311      */
312     @Override
313     public boolean isHttpOnly() {
314         return httpOnly;
315     }
316 
317     /**
318      * @since 4.4
319      * @deprecated Use {@link #setCreationDate(Instant)}
320      */
321     @Deprecated
322     public void setCreationDate(final Date creationDate) {
323         this.creationDate = DateUtils.toInstant(creationDate);
324     }
325 
326     /**
327      * @since 5.2
328      */
329     public void setCreationDate(final Instant creationDate) {
330         this.creationDate = creationDate;
331     }
332 
333     public void setAttribute(final String name, final String value) {
334         this.attribs.put(name, value);
335     }
336 
337     @Override
338     public String getAttribute(final String name) {
339         return this.attribs.get(name);
340     }
341 
342     @Override
343     public boolean containsAttribute(final String name) {
344         return this.attribs.containsKey(name);
345     }
346 
347     /**
348      * @since 4.4
349      */
350     public boolean removeAttribute(final String name) {
351         return this.attribs.remove(name) != null;
352     }
353 
354     @Override
355     public Object clone() throws CloneNotSupportedException {
356         final BasicClientCookie clone = (BasicClientCookie) super.clone();
357         clone.attribs = new HashMap<>(this.attribs);
358         return clone;
359     }
360 
361     @Override
362     public String toString() {
363         final StringBuilder buffer = new StringBuilder();
364         buffer.append("[name: ");
365         buffer.append(this.name);
366         buffer.append("; ");
367         buffer.append("value: ");
368         buffer.append(this.value);
369         buffer.append("; ");
370         buffer.append("domain: ");
371         buffer.append(this.cookieDomain);
372         buffer.append("; ");
373         buffer.append("path: ");
374         buffer.append(this.cookiePath);
375         buffer.append("; ");
376         buffer.append("expiry: ");
377         buffer.append(this.cookieExpiryDate);
378         buffer.append("]");
379         return buffer.toString();
380     }
381 
382    // ----------------------------------------------------- Instance Variables
383 
384     /** Cookie name */
385     private final String name;
386 
387     /** Cookie attributes as specified by the origin server */
388     private Map<String, String> attribs;
389 
390     /** Cookie value */
391     private String value;
392 
393     /** Domain attribute. */
394     private String  cookieDomain;
395 
396     /** Expiration {@link Instant}. */
397     private Instant cookieExpiryDate;
398 
399     /** Path attribute. */
400     private String cookiePath;
401 
402     /** My secure flag. */
403     private boolean isSecure;
404 
405     private Instant creationDate;
406 
407     /** The {@code httpOnly} flag. */
408     private boolean httpOnly;
409 
410 }
411