All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.codehaus.httpcache4j.cache.Vary Maven / Gradle / Ivy

There is a newer version: 5.1.1
Show newest version
/*
 * Copyright (c) 2008, The Codehaus. All Rights Reserved.
 *
 *   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 org.codehaus.httpcache4j.cache;

import java.io.Serializable;
import java.text.Collator;
import java.util.*;

import org.codehaus.httpcache4j.HTTPRequest;
import org.codehaus.httpcache4j.Header;
import org.codehaus.httpcache4j.HeaderConstants;
import org.codehaus.httpcache4j.Headers;
import org.codehaus.httpcache4j.mutable.MutableHeaders;
import org.codehaus.httpcache4j.preference.Preference;

/**
 * Represents a HTTP Variation.
 * We need to store a different version of the response if the request varies on
 * E.G Accept headers.
 * Implementors of storage engines needs to have knowledge of this class.
 * See {@link Key} for how it's used.
 *
 * @author Erlend Hamnaberg
 */
public final class Vary implements Serializable {
    public static final Vary ALL = new Vary(Collections.singletonMap("ALL", "true"));
    private final Map varyHeaders;

    /**
     * Default constructor (no variations)
     */
    public Vary() {
        this(Collections.emptyMap());
    }

    /**
     * Constructor
     *
     * @param headers the vary headers as keys from the response, with request headers as values.
     */
    public Vary(final Map headers) {
        Objects.requireNonNull(headers, "Headers may not be null");
        Map h = new TreeMap(new VaryComparator());
        for (Map.Entry entry : headers.entrySet()) {
            String value = normalizeValue(entry.getKey(), entry.getValue());
            h.put(entry.getKey(), value);
        }
        varyHeaders = Collections.unmodifiableMap(h);
    }

    public Vary(Headers headers) {
        Map h = new TreeMap(new VaryComparator());
        for (Header header : headers) {
            String value = normalizeValue(header.getName(), header.getValue());
            h.put(header.getName(), value);
        }
        varyHeaders = Collections.unmodifiableMap(h);
    }

    private String normalizeValue(String name, String value) {
        if (name.toLowerCase().startsWith("accept")) {
            List parse = Preference.parse(new Header(name, value));
            value = Preference.toHeader(name, parse).getValue();
        }
        return value;
    }

    public int size() {
        return varyHeaders.size();
    }

    public boolean isEmpty() {
        return varyHeaders.isEmpty();
    }

    /**
     * Analyses the headers in the given request to figure out if this {@link Vary variation} matches.
     *
     * @param request the request to analyse
     * @return {@code true} if the request matches the variance. {@code false} if not.
     */
    //todo: cleanup this
    public boolean matches(final HTTPRequest request) {
        if (varyHeaders.containsKey("ALL")) return false;
        Headers headers = request.getAllHeaders();

        for (Map.Entry varyEntry : varyHeaders.entrySet()) {
            if (request.getChallenge().isPresent() && varyEntry.getKey().equals(HeaderConstants.AUTHORIZATION)) {
                if (!request.getChallenge().get().getIdentifier().equals(varyEntry.getValue())) {
                    return false;
                }
            }
            else {
                List
requestHeaderValue = headers.getHeaders(varyEntry.getKey()); boolean valid = requestHeaderValue.isEmpty() ? varyEntry.getValue() == null : headers.getFirstHeader(varyEntry.getKey()).get().getValue().equals(varyEntry.getValue()); if (!valid) { return false; } } } List preferences = new ArrayList<>(); preferences.addAll(headers.getAccept()); preferences.addAll(headers.getAcceptCharset()); preferences.addAll(headers.getAcceptLanguage()); return !(varyHeaders.isEmpty() && !preferences.isEmpty()); } @Override public String toString() { MutableHeaders headers = new MutableHeaders(); for (Map.Entry entry : varyHeaders.entrySet()) { headers.add(entry.getKey(), entry.getValue()); } return headers.toHeaders().toString(); } public Map getVaryHeaders() { return varyHeaders; } public static Vary parse(String value) { Headers headers = Headers.parse(value); return new Vary(headers); } public boolean equals(final Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Vary vary = (Vary) o; if (varyHeaders != null ? !varyHeaders.equals(vary.varyHeaders) : vary.varyHeaders != null) { return false; } return true; } public int hashCode() { return varyHeaders.hashCode(); } public static class VaryComparator implements Comparator, Serializable { private static final long serialVersionUID = 7826440288680033131L; private transient Collator collator = getCollator(); private Collator getCollator() { if (collator == null) { collator = Collator.getInstance(Locale.UK); } return collator; } public int compare(String one, String two) { return getCollator().compare(one, two); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy