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-2014 ForgeRock AS.
016 */
017
018package org.forgerock.openig.http;
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.openig.header.CookieHeader;
029import org.forgerock.openig.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 the request to read cookies from.
046     */
047    public RequestCookies(final Request request) {
048        this.request = request;
049    }
050
051    @Override
052    public boolean containsKey(final Object key) {
053        return get(key) != null;
054    }
055
056    @Override
057    public boolean containsValue(final Object value) {
058        return cookies().containsValue(value);
059    }
060
061    @Override
062    public Set<Entry<String, List<Cookie>>> entrySet() {
063        return cookies().entrySet();
064    }
065
066    @Override
067    public List<Cookie> get(final Object key) {
068        final ArrayList<Cookie> list = new ArrayList<Cookie>();
069        if (key instanceof String) {
070            final String s = (String) key;
071            for (final Cookie cookie : new CookieHeader(request).getCookies()) {
072                if (s.equalsIgnoreCase(cookie.getName())) {
073                    list.add(cookie);
074                }
075            }
076        }
077        return list.size() > 0 ? list : null;
078    }
079
080    @Override
081    public boolean isEmpty() {
082        return new CookieHeader(request).getCookies().isEmpty();
083    }
084
085    @Override
086    public Set<String> keySet() {
087        return cookies().keySet();
088    }
089
090    @Override
091    public int size() {
092        return new CookieHeader(request).getCookies().size();
093    }
094
095    @Override
096    public String toString() {
097        return cookies().toString();
098    }
099
100    @Override
101    public Collection<List<Cookie>> values() {
102        return cookies().values();
103    }
104
105    private Map<String, List<Cookie>> cookies() {
106        final Map<String, List<Cookie>> cookies =
107                new TreeMap<String, List<Cookie>>(String.CASE_INSENSITIVE_ORDER);
108        for (final Cookie cookie : new CookieHeader(request).getCookies()) {
109            List<Cookie> list = cookies.get(cookie.getName());
110            if (list == null) {
111                cookies.put(cookie.getName(), list = new ArrayList<Cookie>(1));
112            }
113            list.add(cookie);
114        }
115        return cookies;
116    }
117
118}