/*
* ******************************************************************************
* Cloud Foundry
* Copyright (c) [2009-2017] Pivotal Software, Inc. All Rights Reserved.
*
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
* You may not use this product except in compliance with the License.
*
* This product includes a number of subcomponents with
* separate copyright notices and license terms. Your use of these
* subcomponents is subject to the terms and conditions of the
* subcomponent's license, as noted in the LICENSE file.
* *******************************************************************************
*/
package org.cloudfoundry.identity.uaa.cache;
import com.google.common.base.Ticker;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.cloudfoundry.identity.uaa.util.TimeService;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.TimeUnit;
public class ExpiringUrlCache implements UrlContentCache {
private static Log logger = LogFactory.getLog(ExpiringUrlCache.class);
private final long expiringTimeMillis;
private final int maxEntries;
private final TimeService ticker;
protected Cache<String, CacheEntry> cache = null;
public ExpiringUrlCache(long expiringTimeMillis, TimeService ticker, int maxEntries) {
this.expiringTimeMillis = expiringTimeMillis;
this.ticker = ticker;
this.maxEntries = maxEntries;
cache = CacheBuilder
.newBuilder()
.expireAfterWrite(expiringTimeMillis, TimeUnit.MILLISECONDS)
.maximumSize(maxEntries)
.ticker(Ticker.systemTicker())
.build();
}
@Override
public byte[] getUrlContent(String uri, final RestTemplate template) {
try {
final URI netUri = new URI(uri);
CacheEntry entry = cache.getIfPresent(uri);
byte[] metadata = entry != null ? entry.getData() : null;
long now = ticker.getCurrentTimeMillis();
if (metadata == null || (now - entry.getTimeEntered()) > this.expiringTimeMillis) {
logger.debug("Fetching metadata for "+uri);
metadata = template.getForObject(netUri, byte[].class);
cache.put(uri, new CacheEntry(now, metadata));
}
return metadata;
} catch (RestClientException x) {
logger.warn("Unable to fetch metadata for "+uri, x);
return null;
} catch (URISyntaxException e) {
throw new IllegalArgumentException(e);
}
}
@Override
public void clear() {
cache.invalidateAll();
}
@Override
public long size() {
return cache.size();
}
static class CacheEntry {
private final long timeEntered;
private final byte[] data;
public CacheEntry(long timeEntered, byte[] data) {
this.timeEntered = timeEntered;
this.data = data;
}
public long getTimeEntered() {
return timeEntered;
}
public byte[] getData() {
return data;
}
}
}