InMemoryCookieStore.java revision 51b1b6997fd3f980076b8081f7f1165ccc2a4008
151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it
651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as
751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation.  Oracle designates this
851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided
951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code.
1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT
1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that
1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code).
1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version
1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation,
1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any
2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions.
2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage java.net;
2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.net.URI;
2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.net.CookieStore;
3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.net.HttpCookie;
3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.net.URISyntaxException;
3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.List;
3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Map;
3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.ArrayList;
3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.HashMap;
3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Collections;
3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Iterator;
3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.concurrent.locks.ReentrantLock;
3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/**
4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A simple in-memory java.net.CookieStore implementation
4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author Edward Wang
4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.6
4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiclass InMemoryCookieStore implements CookieStore {
4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // the in-memory representation of cookies
4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private List<HttpCookie> cookieJar = null;
4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // the cookies are indexed by its domain and associated uri (if present)
5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // CAUTION: when a cookie removed from main data structure (i.e. cookieJar),
5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //          it won't be cleared in domainIndex & uriIndex. Double-check the
5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //          presence of cookie when retrieve one form index store.
5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Map<String, List<HttpCookie>> domainIndex = null;
5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Map<URI, List<HttpCookie>> uriIndex = null;
5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // use ReentrantLock instead of syncronized for scalability
5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private ReentrantLock lock = null;
5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The default ctor
6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public InMemoryCookieStore() {
6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        cookieJar = new ArrayList<HttpCookie>();
6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        domainIndex = new HashMap<String, List<HttpCookie>>();
6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        uriIndex = new HashMap<URI, List<HttpCookie>>();
6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        lock = new ReentrantLock(false);
7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Add one cookie into cookie store.
7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void add(URI uri, HttpCookie cookie) {
7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // pre-condition : argument can't be null
7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (cookie == null) {
7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NullPointerException("cookie is null");
7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        lock.lock();
8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // remove the ole cookie if there has had one
8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            cookieJar.remove(cookie);
8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // add new cookie if it has a non-zero max-age
8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (cookie.getMaxAge() != 0) {
8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                cookieJar.add(cookie);
9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // and add it to domain index
9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (cookie.getDomain() != null) {
9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    addIndex(domainIndex, cookie.getDomain(), cookie);
9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (uri != null) {
9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // add it to uri index, too
9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    addIndex(uriIndex, getEffectiveURI(uri), cookie);
9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } finally {
10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            lock.unlock();
10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Get all cookies, which:
10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *  1) given uri domain-matches with, or, associated with
10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     given uri when added to the cookie store.
10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *  3) not expired.
11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * See RFC 2965 sec. 3.3.4 for more detail.
11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public List<HttpCookie> get(URI uri) {
11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // argument can't be null
11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (uri == null) {
11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NullPointerException("uri is null");
11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        List<HttpCookie> cookies = new ArrayList<HttpCookie>();
11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean secureLink = "https".equalsIgnoreCase(uri.getScheme());
12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        lock.lock();
12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // check domainIndex first
12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            getInternal1(cookies, domainIndex, uri.getHost(), secureLink);
12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // check uriIndex then
12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            getInternal2(cookies, uriIndex, getEffectiveURI(uri), secureLink);
12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } finally {
12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            lock.unlock();
12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return cookies;
13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Get all cookies in cookie store, except those have expired
13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public List<HttpCookie> getCookies() {
13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        List<HttpCookie> rt;
13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        lock.lock();
14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Iterator<HttpCookie> it = cookieJar.iterator();
14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while (it.hasNext()) {
14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (it.next().hasExpired()) {
14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    it.remove();
14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } finally {
14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            rt = Collections.unmodifiableList(cookieJar);
14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            lock.unlock();
15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return rt;
15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Get all URIs, which are associated with at least one cookie
15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * of this cookie store.
15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public List<URI> getURIs() {
16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        List<URI> uris = new ArrayList<URI>();
16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        lock.lock();
16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Iterator<URI> it = uriIndex.keySet().iterator();
16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while (it.hasNext()) {
16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                URI uri = it.next();
16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                List<HttpCookie> cookies = uriIndex.get(uri);
16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (cookies == null || cookies.size() == 0) {
16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // no cookies list or an empty list associated with
17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // this uri entry, delete it
17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    it.remove();
17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } finally {
17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            uris.addAll(uriIndex.keySet());
17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            lock.unlock();
17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return uris;
18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Remove a cookie from store
18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean remove(URI uri, HttpCookie ck) {
18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // argument can't be null
18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (ck == null) {
18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NullPointerException("cookie is null");
19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean modified = false;
19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        lock.lock();
19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            modified = cookieJar.remove(ck);
19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } finally {
19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            lock.unlock();
19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return modified;
20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Remove all cookies in this cookie store.
20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean removeAll() {
20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        lock.lock();
20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            cookieJar.clear();
21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            domainIndex.clear();
21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            uriIndex.clear();
21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } finally {
21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            lock.unlock();
21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return true;
21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /* ---------------- Private operations -------------- */
22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /*
22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This is almost the same as HttpCookie.domainMatches except for
22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * one difference: It won't reject cookies when the 'H' part of the
22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * domain contains a dot ('.').
22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * I.E.: RFC 2965 section 3.3.2 says that if host is x.y.domain.com
22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * and the cookie domain is .domain.com, then it should be rejected.
23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * However that's not how the real world works. Browsers don't reject and
23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * some sites, like yahoo.com do actually expect these cookies to be
23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * passed along.
23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * And should be used for 'old' style cookies (aka Netscape type of cookies)
23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private boolean netscapeDomainMatches(String domain, String host)
23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (domain == null || host == null) {
23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // if there's no embedded dot in domain and domain is not .local
24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean isLocalDomain = ".local".equalsIgnoreCase(domain);
24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int embeddedDotInDomain = domain.indexOf('.');
24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (embeddedDotInDomain == 0) {
24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            embeddedDotInDomain = domain.indexOf('.', 1);
24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!isLocalDomain && (embeddedDotInDomain == -1 || embeddedDotInDomain == domain.length() - 1)) {
24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // if the host name contains no dot and the domain name is .local
25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int firstDotInHost = host.indexOf('.');
25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (firstDotInHost == -1 && isLocalDomain) {
25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return true;
25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int domainLength = domain.length();
25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int lengthDiff = host.length() - domainLength;
25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (lengthDiff == 0) {
26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // if the host name and the domain name are just string-compare euqal
26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return host.equalsIgnoreCase(domain);
26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (lengthDiff > 0) {
26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // need to check H & D component
26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            String H = host.substring(0, lengthDiff);
26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            String D = host.substring(lengthDiff);
26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (D.equalsIgnoreCase(domain));
26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (lengthDiff == -1) {
26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // if domain is actually .host
27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (domain.charAt(0) == '.' &&
27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    host.equalsIgnoreCase(domain.substring(1)));
27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return false;
27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void getInternal1(List<HttpCookie> cookies, Map<String, List<HttpCookie>> cookieIndex,
27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            String host, boolean secureLink) {
27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Use a separate list to handle cookies that need to be removed so
28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // that there is no conflict with iterators.
28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ArrayList<HttpCookie> toRemove = new ArrayList<HttpCookie>();
28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (Map.Entry<String, List<HttpCookie>> entry : cookieIndex.entrySet()) {
28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            String domain = entry.getKey();
28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            List<HttpCookie> lst = entry.getValue();
28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (HttpCookie c : lst) {
28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if ((c.getVersion() == 0 && netscapeDomainMatches(domain, host)) ||
28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        (c.getVersion() == 1 && HttpCookie.domainMatches(domain, host))) {
28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if ((cookieJar.indexOf(c) != -1)) {
28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        // the cookie still in main cookie store
29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (!c.hasExpired()) {
29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            // don't add twice and make sure it's the proper
29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            // security level
29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            if ((secureLink || !c.getSecure()) &&
29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                    !cookies.contains(c)) {
29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                cookies.add(c);
29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            }
29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        } else {
29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            toRemove.add(c);
29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    } else {
30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        // the cookie has beed removed from main store,
30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        // so also remove it from domain indexed store
30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        toRemove.add(c);
30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Clear up the cookies that need to be removed
30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (HttpCookie c : toRemove) {
30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                lst.remove(c);
31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                cookieJar.remove(c);
31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            toRemove.clear();
31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // @param cookies           [OUT] contains the found cookies
31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // @param cookieIndex       the index
31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // @param comparator        the prediction to decide whether or not
32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //                          a cookie in index should be returned
32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private <T> void getInternal2(List<HttpCookie> cookies,
32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                Map<T, List<HttpCookie>> cookieIndex,
32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                Comparable<T> comparator, boolean secureLink)
32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (T index : cookieIndex.keySet()) {
32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (comparator.compareTo(index) == 0) {
32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                List<HttpCookie> indexedCookies = cookieIndex.get(index);
32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // check the list of cookies associated with this domain
32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (indexedCookies != null) {
33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    Iterator<HttpCookie> it = indexedCookies.iterator();
33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    while (it.hasNext()) {
33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        HttpCookie ck = it.next();
33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (cookieJar.indexOf(ck) != -1) {
33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            // the cookie still in main cookie store
33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            if (!ck.hasExpired()) {
33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                // don't add twice
33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                if ((secureLink || !ck.getSecure()) &&
33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                        !cookies.contains(ck))
33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                    cookies.add(ck);
34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            } else {
34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                it.remove();
34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                cookieJar.remove(ck);
34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            }
34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        } else {
34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            // the cookie has beed removed from main store,
34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            // so also remove it from domain indexed store
34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            it.remove();
34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } // end of indexedCookies != null
35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } // end of comparator.compareTo(index) == 0
35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } // end of cookieIndex iteration
35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // add 'cookie' indexed by 'index' into 'indexStore'
35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private <T> void addIndex(Map<T, List<HttpCookie>> indexStore,
35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                              T index,
35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                              HttpCookie cookie)
35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (index != null) {
36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            List<HttpCookie> cookies = indexStore.get(index);
36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (cookies != null) {
36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // there may already have the same cookie, so remove it first
36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                cookies.remove(cookie);
36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                cookies.add(cookie);
36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                cookies = new ArrayList<HttpCookie>();
36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                cookies.add(cookie);
37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                indexStore.put(index, cookies);
37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //
37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // for cookie purpose, the effective uri should only be http://host
37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // the path will be taken into account when path-match algorithm applied
37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //
38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private URI getEffectiveURI(URI uri) {
38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        URI effectiveURI = null;
38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            effectiveURI = new URI("http",
38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                   uri.getHost(),
38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                   null,  // path component
38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                   null,  // query component
38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                   null   // fragment component
38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                  );
38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (URISyntaxException ignored) {
39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            effectiveURI = uri;
39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return effectiveURI;
39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
396