org.surfnet.oaaas.model.TokenResponseCacheImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.surfnet.oaaas.model.TokenResponseCacheImpl.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.
 */
package org.surfnet.oaaas.model;

import org.springframework.util.Assert;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Very simple - but highly effective - TokenResponseCache implementation. Please carefully monitor the performance / cache hit-ratio
 * in production as the maxSize in combination with the expireTimeSeconds is important. If the maxSize is too small and the expireTimeSeconds to low
 * it will result in a cache that with each addition will try to make space (e.g. effectively only removing the oldest entry each time).
 */
public class TokenResponseCacheImpl implements TokenResponseCache {

    private Map<String, CacheEntry> cache = new ConcurrentHashMap<String, CacheEntry>();
    private int maxSize;
    private long expireTime;

    public TokenResponseCacheImpl(int maxSize, long expireTimeSeconds) {
        this.maxSize = maxSize;
        this.expireTime = expireTimeSeconds * 1000;
        invariant();
    }

    private void invariant() {
        Assert.isTrue(maxSize > 0, "Maxsize must be greater then 0");
        Assert.isTrue(expireTime < ((1000 * 60 * 60 * 24) + 1), "Maximal expireTime is one day");
        Assert.isTrue(expireTime > 0, "ExpireTimeMilliseconds must be greater then 0");
    }

    @Override
    public VerifyTokenResponse getVerifyToken(String accessToken) {
        VerifyTokenResponse response = null;
        if (accessToken != null) {
            CacheEntry cacheEntry = cache.get(accessToken);
            if (cacheEntry != null) {
                if (isExpired(cacheEntry)) {
                    cache.remove(accessToken);
                } else {
                    response = cacheEntry.value;
                }
            }
        }
        return response;
    }

    private boolean isExpired(CacheEntry cacheEntry) {
        return cacheEntry.expireBy < System.currentTimeMillis();
    }

    @Override
    public void storeVerifyToken(String accessToken, VerifyTokenResponse tokenResponse) {
        if (accessToken != null && tokenResponse != null) {
            if (cache.size() == maxSize) {
                cleanUpCache();
            }
            cache.put(accessToken, new CacheEntry(tokenResponse, System.currentTimeMillis() + expireTime));
        }
    }

    private void cleanUpCache() {
        Set<Map.Entry<String, CacheEntry>> entries = cache.entrySet();
        long ago = Long.MAX_VALUE;
        String oldestKey = null;
        for (Map.Entry<String, CacheEntry> entry : entries) {
            if (isExpired(entry.getValue())) {
                cache.remove(entry.getKey());
            } else if (entry.getValue().expireBy < ago) {
                oldestKey = entry.getKey();
                ago = entry.getValue().expireBy;
            }
        }
        if (oldestKey != null) {
            cache.remove(oldestKey);
        }
    }

    private class CacheEntry {
        private VerifyTokenResponse value;
        private long expireBy;

        CacheEntry(VerifyTokenResponse verifyTokenResponse, long expireBy) {
            this.value = verifyTokenResponse;
            this.expireBy = expireBy;
        }
    }
}