BasicCookieStore no longer synchronizes on reads
BasicCookieStore uses a ReentrantReadWriteLock to avoid synchronization on getCookies/toString while maintaining thread safety. Closes PR #81
This commit is contained in:
parent
9efcba8730
commit
a10967a427
|
@ -32,6 +32,8 @@ import java.util.Date;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
|
||||||
import org.apache.hc.core5.annotation.Contract;
|
import org.apache.hc.core5.annotation.Contract;
|
||||||
import org.apache.hc.core5.annotation.ThreadingBehavior;
|
import org.apache.hc.core5.annotation.ThreadingBehavior;
|
||||||
|
@ -48,10 +50,12 @@ public class BasicCookieStore implements CookieStore, Serializable {
|
||||||
private static final long serialVersionUID = -7581093305228232025L;
|
private static final long serialVersionUID = -7581093305228232025L;
|
||||||
|
|
||||||
private final TreeSet<Cookie> cookies;
|
private final TreeSet<Cookie> cookies;
|
||||||
|
private final ReadWriteLock lock;
|
||||||
|
|
||||||
public BasicCookieStore() {
|
public BasicCookieStore() {
|
||||||
super();
|
super();
|
||||||
this.cookies = new TreeSet<>(new CookieIdentityComparator());
|
this.cookies = new TreeSet<>(new CookieIdentityComparator());
|
||||||
|
this.lock = new ReentrantReadWriteLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -65,12 +69,17 @@ public class BasicCookieStore implements CookieStore, Serializable {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public synchronized void addCookie(final Cookie cookie) {
|
public void addCookie(final Cookie cookie) {
|
||||||
if (cookie != null) {
|
if (cookie != null) {
|
||||||
// first remove any old cookie that is equivalent
|
lock.writeLock().lock();
|
||||||
cookies.remove(cookie);
|
try {
|
||||||
if (!cookie.isExpired(new Date())) {
|
// first remove any old cookie that is equivalent
|
||||||
cookies.add(cookie);
|
cookies.remove(cookie);
|
||||||
|
if (!cookie.isExpired(new Date())) {
|
||||||
|
cookies.add(cookie);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
lock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,10 +94,10 @@ public class BasicCookieStore implements CookieStore, Serializable {
|
||||||
* @see #addCookie(Cookie)
|
* @see #addCookie(Cookie)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public synchronized void addCookies(final Cookie[] cookies) {
|
public void addCookies(final Cookie[] cookies) {
|
||||||
if (cookies != null) {
|
if (cookies != null) {
|
||||||
for (final Cookie cooky : cookies) {
|
for (final Cookie cookie : cookies) {
|
||||||
this.addCookie(cooky);
|
this.addCookie(cookie);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,9 +109,14 @@ public class BasicCookieStore implements CookieStore, Serializable {
|
||||||
* @return an array of {@link Cookie cookies}.
|
* @return an array of {@link Cookie cookies}.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public synchronized List<Cookie> getCookies() {
|
public List<Cookie> getCookies() {
|
||||||
//create defensive copy so it won't be concurrently modified
|
lock.readLock().lock();
|
||||||
return new ArrayList<>(cookies);
|
try {
|
||||||
|
//create defensive copy so it won't be concurrently modified
|
||||||
|
return new ArrayList<>(cookies);
|
||||||
|
} finally {
|
||||||
|
lock.readLock().unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -114,31 +128,46 @@ public class BasicCookieStore implements CookieStore, Serializable {
|
||||||
* @see Cookie#isExpired(Date)
|
* @see Cookie#isExpired(Date)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean clearExpired(final Date date) {
|
public boolean clearExpired(final Date date) {
|
||||||
if (date == null) {
|
if (date == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
boolean removed = false;
|
lock.writeLock().lock();
|
||||||
for (final Iterator<Cookie> it = cookies.iterator(); it.hasNext();) {
|
try {
|
||||||
if (it.next().isExpired(date)) {
|
boolean removed = false;
|
||||||
it.remove();
|
for (final Iterator<Cookie> it = cookies.iterator(); it.hasNext(); ) {
|
||||||
removed = true;
|
if (it.next().isExpired(date)) {
|
||||||
|
it.remove();
|
||||||
|
removed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return removed;
|
||||||
|
} finally {
|
||||||
|
lock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
return removed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears all cookies.
|
* Clears all cookies.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public synchronized void clear() {
|
public void clear() {
|
||||||
cookies.clear();
|
lock.writeLock().lock();
|
||||||
|
try {
|
||||||
|
cookies.clear();
|
||||||
|
} finally {
|
||||||
|
lock.writeLock().unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized String toString() {
|
public String toString() {
|
||||||
return cookies.toString();
|
lock.readLock().lock();
|
||||||
|
try {
|
||||||
|
return cookies.toString();
|
||||||
|
} finally {
|
||||||
|
lock.readLock().unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue