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  package org.apache.http.impl.client;
28  
29  import java.io.Serializable;
30  import java.util.ArrayList;
31  import java.util.Date;
32  import java.util.Iterator;
33  import java.util.List;
34  import java.util.TreeSet;
35  import java.util.concurrent.locks.ReadWriteLock;
36  import java.util.concurrent.locks.ReentrantReadWriteLock;
37  
38  import org.apache.http.annotation.Contract;
39  import org.apache.http.annotation.ThreadingBehavior;
40  import org.apache.http.client.CookieStore;
41  import org.apache.http.cookie.Cookie;
42  import org.apache.http.cookie.CookieIdentityComparator;
43  
44  /**
45   * Default implementation of {@link CookieStore}
46   *
47   *
48   * @since 4.0
49   */
50  @Contract(threading = ThreadingBehavior.SAFE)
51  public class BasicCookieStore implements CookieStore, Serializable {
52  
53      private static final long serialVersionUID = -7581093305228232025L;
54  
55      private final TreeSet<Cookie> cookies;
56      private final ReadWriteLock lock;
57  
58      public BasicCookieStore() {
59          super();
60          this.cookies = new TreeSet<Cookie>(new CookieIdentityComparator());
61          this.lock = new ReentrantReadWriteLock();
62      }
63  
64      /**
65       * Adds an {@link Cookie HTTP cookie}, replacing any existing equivalent cookies.
66       * If the given cookie has already expired it will not be added, but existing
67       * values will still be removed.
68       *
69       * @param cookie the {@link Cookie cookie} to be added
70       *
71       * @see #addCookies(Cookie[])
72       *
73       */
74      @Override
75      public void addCookie(final Cookie cookie) {
76          if (cookie != null) {
77              lock.writeLock().lock();
78              try {
79                  // first remove any old cookie that is equivalent
80                  cookies.remove(cookie);
81                  if (!cookie.isExpired(new Date())) {
82                      cookies.add(cookie);
83                  }
84              } finally {
85                  lock.writeLock().unlock();
86              }
87          }
88      }
89  
90      /**
91       * Adds an array of {@link Cookie HTTP cookies}. Cookies are added individually and
92       * in the given array order. If any of the given cookies has already expired it will
93       * not be added, but existing values will still be removed.
94       *
95       * @param cookies the {@link Cookie cookies} to be added
96       *
97       * @see #addCookie(Cookie)
98       *
99       */
100     public void addCookies(final Cookie[] cookies) {
101         if (cookies != null) {
102             for (final Cookie cookie : cookies) {
103                 this.addCookie(cookie);
104             }
105         }
106     }
107 
108     /**
109      * Returns an immutable array of {@link Cookie cookies} that this HTTP
110      * state currently contains.
111      *
112      * @return an array of {@link Cookie cookies}.
113      */
114     @Override
115     public List<Cookie> getCookies() {
116         lock.readLock().lock();
117         try {
118             //create defensive copy so it won't be concurrently modified
119             return new ArrayList<Cookie>(cookies);
120         } finally {
121             lock.readLock().unlock();
122         }
123     }
124 
125     /**
126      * Removes all of {@link Cookie cookies} in this HTTP state
127      * that have expired by the specified {@link java.util.Date date}.
128      *
129      * @return true if any cookies were purged.
130      *
131      * @see Cookie#isExpired(Date)
132      */
133     @Override
134     public boolean clearExpired(final Date date) {
135         if (date == null) {
136             return false;
137         }
138         lock.writeLock().lock();
139         try {
140             boolean removed = false;
141             for (final Iterator<Cookie> it = cookies.iterator(); it.hasNext(); ) {
142                 if (it.next().isExpired(date)) {
143                     it.remove();
144                     removed = true;
145                 }
146             }
147             return removed;
148         } finally {
149             lock.writeLock().unlock();
150         }
151     }
152 
153     /**
154      * Clears all cookies.
155      */
156     @Override
157     public void clear() {
158         lock.writeLock().lock();
159         try {
160             cookies.clear();
161         } finally {
162             lock.writeLock().unlock();
163         }
164     }
165 
166     @Override
167     public String toString() {
168         lock.readLock().lock();
169         try {
170             return cookies.toString();
171         } finally {
172             lock.readLock().unlock();
173         }
174     }
175 
176 }