com.gargoylesoftware.htmlunit.CookieManager.java Source code

Java tutorial

Introduction

Here is the source code for com.gargoylesoftware.htmlunit.CookieManager.java

Source

/*
 * Copyright (c) 2002-2016 Gargoyle Software Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.gargoylesoftware.htmlunit;

import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.cookie.CookieOrigin;

import com.gargoylesoftware.htmlunit.httpclient.HtmlUnitBrowserCompatCookieSpec;
import com.gargoylesoftware.htmlunit.util.Cookie;
import com.gargoylesoftware.htmlunit.util.UrlUtils;

/**
 * Manages cookies for a {@link WebClient}. This class is thread-safe.
 * You can disable Cookies by calling setCookiesEnabled(false). The
 * CookieManager itself takes care of this and ignores all cookie request if
 * disabled. If you override this your methods have to do the same.
 *
 * @author Daniel Gredler
 * @author Ahmed Ashour
 * @author Nicolas Belisle
 * @author Ronald Brill
 */
public class CookieManager implements Serializable {

    /** Whether or not cookies are enabled. */
    private boolean cookiesEnabled_;

    /** The cookies added to this cookie manager. */
    private final Set<Cookie> cookies_ = new LinkedHashSet<>();

    /**
     * Creates a new instance.
     */
    public CookieManager() {
        cookiesEnabled_ = true;
    }

    /**
     * Enables/disables cookie support. Cookies are enabled by default.
     * @param enabled {@code true} to enable cookie support, {@code false} otherwise
     */
    public synchronized void setCookiesEnabled(final boolean enabled) {
        cookiesEnabled_ = enabled;
    }

    /**
     * Returns {@code true} if cookies are enabled. Cookies are enabled by default.
     * @return {@code true} if cookies are enabled, {@code false} otherwise
     */
    public synchronized boolean isCookiesEnabled() {
        return cookiesEnabled_;
    }

    /**
     * Returns the currently configured cookies, in an unmodifiable set.
     * If disabled, this returns an empty set.
     * @return the currently configured cookies, in an unmodifiable set
     */
    public synchronized Set<Cookie> getCookies() {
        if (!isCookiesEnabled()) {
            return Collections.<Cookie>emptySet();
        }

        final Set<Cookie> copy = new LinkedHashSet<>();
        copy.addAll(cookies_);
        return Collections.unmodifiableSet(copy);
    }

    /**
     * Helper that builds a CookieOrigin.
     * @param url the url to be used
     * @return the new CookieOrigin
     */
    public CookieOrigin buildCookieOrigin(final URL url) {
        final URL normalizedUrl = replaceForCookieIfNecessary(url);

        return new CookieOrigin(normalizedUrl.getHost(), getPort(normalizedUrl), normalizedUrl.getPath(),
                "https".equals(normalizedUrl.getProtocol()));
    }

    /**
     * Clears all cookies that have expired before supplied date.
     * If disabled, this returns false.
     * @param date the date to use for comparison when clearing expired cookies
     * @return whether any cookies were found expired, and were cleared
     */
    public synchronized boolean clearExpired(final Date date) {
        if (!isCookiesEnabled()) {
            return false;
        }

        if (date == null) {
            return false;
        }

        boolean foundExpired = false;
        for (final Iterator<Cookie> iter = cookies_.iterator(); iter.hasNext();) {
            final Cookie cookie = iter.next();
            if (cookie.getExpires() != null && date.after(cookie.getExpires())) {
                iter.remove();
                foundExpired = true;
            }
        }
        return foundExpired;
    }

    /**
     * Gets the port of the URL.
     * This functionality is implemented here as protected method to allow subclass to change it
     * as workaround to <a href="http://code.google.com/p/googleappengine/issues/detail?id=4784">
     * Google App Engine bug 4784</a>.
     * @param url the URL
     * @return the port use to connect the server
     */
    protected int getPort(final URL url) {
        if (url.getPort() != -1) {
            return url.getPort();
        }
        return url.getDefaultPort();
    }

    /**
     * {@link org.apache.commons.httpclient.cookie.CookieSpec#match(String, int, String, boolean, Cookie[])} doesn't
     * like empty hosts and negative ports, but these things happen if we're dealing with a local file. This method
     * allows us to work around this limitation in HttpClient by feeding it a bogus host and port.
     *
     * @param url the URL to replace if necessary
     * @return the replacement URL, or the original URL if no replacement was necessary
     */
    public URL replaceForCookieIfNecessary(URL url) {
        final String protocol = url.getProtocol();
        final boolean file = "file".equals(protocol);
        if (file) {
            try {
                url = UrlUtils.getUrlWithNewHostAndPort(url,
                        HtmlUnitBrowserCompatCookieSpec.LOCAL_FILESYSTEM_DOMAIN, 0);
            } catch (final MalformedURLException e) {
                throw new RuntimeException(e);
            }
        }
        return url;
    }

    /**
     * Returns the currently configured cookie with the specified name, or {@code null} if one does not exist.
     * If disabled, this returns null.
     * @param name the name of the cookie to return
     * @return the currently configured cookie with the specified name, or {@code null} if one does not exist
     */
    public synchronized Cookie getCookie(final String name) {
        if (!isCookiesEnabled()) {
            return null;
        }

        for (Cookie cookie : cookies_) {
            if (StringUtils.equals(cookie.getName(), name)) {
                return cookie;
            }
        }
        return null;
    }

    /**
     * Adds the specified cookie.
     * If disabled, this does nothing.
     * @param cookie the cookie to add
     */
    public synchronized void addCookie(final Cookie cookie) {
        if (!isCookiesEnabled()) {
            return;
        }

        cookies_.remove(cookie);

        // don't add expired cookie
        if (cookie.getExpires() == null || cookie.getExpires().after(new Date())) {
            cookies_.add(cookie);
        }
    }

    /**
     * Removes the specified cookie.
     * If disabled, this does nothing.
     * @param cookie the cookie to remove
     */
    public synchronized void removeCookie(final Cookie cookie) {
        if (!isCookiesEnabled()) {
            return;
        }

        cookies_.remove(cookie);
    }

    /**
     * Removes all cookies.
     * If disabled, this does nothing.
     */
    public synchronized void clearCookies() {
        if (!isCookiesEnabled()) {
            return;
        }

        cookies_.clear();
    }
}