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