com.apigee.sdk.apm.http.impl.client.cache.CacheInvalidator.java Source code

Java tutorial

Introduction

Here is the source code for com.apigee.sdk.apm.http.impl.client.cache.CacheInvalidator.java

Source

/*
 * ====================================================================
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 */
package com.apigee.sdk.apm.http.impl.client.cache;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;

import com.apigee.sdk.apm.http.annotation.ThreadSafe;
import com.apigee.sdk.apm.http.client.cache.HeaderConstants;
import com.apigee.sdk.apm.http.client.cache.HttpCacheEntry;
import com.apigee.sdk.apm.http.client.cache.HttpCacheStorage;

/**
 * Given a particular HttpRequest, flush any cache entries that this request
 * would invalidate.
 * 
 * @since 4.1
 */
@ThreadSafe
// so long as the cache implementation is thread-safe
class CacheInvalidator {

    private final HttpCacheStorage storage;
    private final URIExtractor uriExtractor;

    private final Log log = LogFactory.getLog(getClass());

    /**
     * Create a new {@link CacheInvalidator} for a given {@link HttpCache} and
     * {@link URIExtractor}.
     * 
     * @param uriExtractor
     *            Provides identifiers for the keys to store cache entries
     * @param storage
     *            the cache to store items away in
     */
    public CacheInvalidator(final URIExtractor uriExtractor, final HttpCacheStorage storage) {
        this.uriExtractor = uriExtractor;
        this.storage = storage;
    }

    /**
     * Remove cache entries from the cache that are no longer fresh or have been
     * invalidated in some way.
     * 
     * @param host
     *            The backend host we are talking to
     * @param req
     *            The HttpRequest to that host
     */
    public void flushInvalidatedCacheEntries(HttpHost host, HttpRequest req) throws IOException {
        if (requestShouldNotBeCached(req)) {
            log.debug("Request should not be cached");

            String theUri = uriExtractor.getURI(host, req);

            HttpCacheEntry parent = storage.getEntry(theUri);

            log.debug("parent entry: " + parent);

            if (parent != null) {
                for (String variantURI : parent.getVariantURIs()) {
                    storage.removeEntry(variantURI);
                }
                storage.removeEntry(theUri);
            }
            URL reqURL;
            try {
                reqURL = new URL(theUri);
            } catch (MalformedURLException mue) {
                log.error("Couldn't transform request into valid URL");
                return;
            }
            Header clHdr = req.getFirstHeader("Content-Location");
            if (clHdr != null) {
                String contentLocation = clHdr.getValue();
                if (!flushAbsoluteUriFromSameHost(reqURL, contentLocation)) {
                    flushRelativeUriFromSameHost(reqURL, contentLocation);
                }
            }
            Header lHdr = req.getFirstHeader("Location");
            if (lHdr != null) {
                flushAbsoluteUriFromSameHost(reqURL, lHdr.getValue());
            }
        }
    }

    protected void flushUriIfSameHost(URL requestURL, URL targetURL) throws IOException {
        URL canonicalTarget = new URL(uriExtractor.canonicalizeUri(targetURL.toString()));
        if (canonicalTarget.getAuthority().equalsIgnoreCase(requestURL.getAuthority())) {
            storage.removeEntry(canonicalTarget.toString());
        }
    }

    protected void flushRelativeUriFromSameHost(URL reqURL, String relUri) throws IOException {
        URL relURL;
        try {
            relURL = new URL(reqURL, relUri);
        } catch (MalformedURLException e) {
            log.debug("Invalid relative URI", e);
            return;
        }
        flushUriIfSameHost(reqURL, relURL);
    }

    protected boolean flushAbsoluteUriFromSameHost(URL reqURL, String uri) throws IOException {
        URL absURL;
        try {
            absURL = new URL(uri);
        } catch (MalformedURLException mue) {
            return false;
        }
        flushUriIfSameHost(reqURL, absURL);
        return true;
    }

    protected boolean requestShouldNotBeCached(HttpRequest req) {
        String method = req.getRequestLine().getMethod();
        return notGetOrHeadRequest(method);
    }

    private boolean notGetOrHeadRequest(String method) {
        return !(HeaderConstants.GET_METHOD.equals(method) || HeaderConstants.HEAD_METHOD.equals(method));
    }
}