001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2010–2011 ApexIdentity Inc.
015 * Portions Copyright 2011-2015 ForgeRock AS.
016 */
017
018package org.forgerock.http.protocol;
019
020import java.util.AbstractMap;
021import java.util.ArrayList;
022import java.util.Collection;
023import java.util.List;
024import java.util.Map;
025import java.util.Set;
026import java.util.TreeMap;
027
028import org.forgerock.http.header.CookieHeader;
029import org.forgerock.http.util.UnmodifiableCollection;
030
031/**
032 * Exposes incoming request cookies.
033 */
034public class RequestCookies extends AbstractMap<String, List<Cookie>> implements
035        Map<String, List<Cookie>>, UnmodifiableCollection {
036    // TODO: maybe some intelligent caching so each call to get doesn't re-parse the cookies
037
038    /** The request to read cookies from. */
039    private final Request request;
040
041    /**
042     * Constructs a new request cookies object that reads cookies from the
043     * specified request.
044     *
045     * @param request
046     *            the request to read cookies from.
047     */
048    public RequestCookies(final Request request) {
049        this.request = request;
050    }
051
052    @Override
053    public boolean containsKey(final Object key) {
054        return get(key) != null;
055    }
056
057    @Override
058    public boolean containsValue(final Object value) {
059        return cookies().containsValue(value);
060    }
061
062    @Override
063    public Set<Entry<String, List<Cookie>>> entrySet() {
064        return cookies().entrySet();
065    }
066
067    @Override
068    public List<Cookie> get(final Object key) {
069        final ArrayList<Cookie> list = new ArrayList<>();
070        if (key instanceof String) {
071            final String s = (String) key;
072            for (final Cookie cookie : CookieHeader.valueOf(request).getCookies()) {
073                if (s.equalsIgnoreCase(cookie.getName())) {
074                    list.add(cookie);
075                }
076            }
077        }
078        return list.size() > 0 ? list : null;
079    }
080
081    @Override
082    public boolean isEmpty() {
083        return CookieHeader.valueOf(request).getCookies().isEmpty();
084    }
085
086    @Override
087    public Set<String> keySet() {
088        return cookies().keySet();
089    }
090
091    @Override
092    public int size() {
093        return CookieHeader.valueOf(request).getCookies().size();
094    }
095
096    @Override
097    public String toString() {
098        return cookies().toString();
099    }
100
101    @Override
102    public Collection<List<Cookie>> values() {
103        return cookies().values();
104    }
105
106    private Map<String, List<Cookie>> cookies() {
107        final Map<String, List<Cookie>> cookies = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
108        for (final Cookie cookie : CookieHeader.valueOf(request).getCookies()) {
109            List<Cookie> list = cookies.get(cookie.getName());
110            if (list == null) {
111                cookies.put(cookie.getName(), list = new ArrayList<>(1));
112            }
113            list.add(cookie);
114        }
115        return cookies;
116    }
117
118}