com.webstersmalley.tv.comms.CachingComms Maven / Gradle / Ivy
/*
* Copyright 2013 Webster Smalley
*
* 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 com.webstersmalley.tv.comms;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
@Repository("cachingComms")
public class CachingComms implements Comms {
private final Logger logger = LoggerFactory.getLogger(getClass());
private Comms targetComms;
private String cacheFolder;
private long validationTimeout;
public void setTargetComms(Comms targetComms) {
this.targetComms = targetComms;
}
public void setCacheFolder(String cacheFolder) {
this.cacheFolder = cacheFolder;
}
public void setValidationTimeout(long validationTimeout) {
this.validationTimeout = validationTimeout;
}
protected void createFolderIfNeeded() {
File f = new File(cacheFolder);
if (f.exists()) {
if (!f.isDirectory()) {
throw new RuntimeException("Cache folder " + cacheFolder + " exists, but is not a directory");
}
} else {
if (!f.mkdirs()) {
throw new RuntimeException("Couldn't write to folder: " + cacheFolder);
}
}
}
protected long getAgeOfFile(String filename) throws IOException {
File f = new File(cacheFolder + "/" + filename);
if (!f.exists()) {
return Long.MAX_VALUE;
}
Path p = FileSystems.getDefault().getPath(cacheFolder, filename);
BasicFileAttributes attributes =
Files.readAttributes(p, BasicFileAttributes.class);
FileTime creationTime = attributes.lastModifiedTime();
return (System.currentTimeMillis() - creationTime.toMillis()) / 1000;
}
public String getURLAsString(String resource) {
try {
String cacheFilename = DigestUtils.md5Hex(resource);
String contents;
long age = getAgeOfFile(cacheFilename);
if (age > validationTimeout) {
logger.debug("serving: {} from target comms", resource);
contents = targetComms.getURLAsString(resource);
createFolderIfNeeded();
FileOutputStream fos = new FileOutputStream(cacheFolder + "/" + cacheFilename);
IOUtils.write(contents, fos);
fos.flush();
fos.close();
} else {
logger.debug("serving: {} from cache ({})", resource, cacheFilename);
FileInputStream fis = new FileInputStream(cacheFolder + "/" + cacheFilename);
contents = IOUtils.toString(fis);
fis.close();
}
return contents;
} catch (IOException e) {
logger.error("Error getting url: " + e.getMessage(), e);
throw new RuntimeException("Error getting url: " + e.getMessage(), e);
}
}
@Override
public String getResourceByRawHttp(URL url, String request) {
try {
String cacheFilename = DigestUtils.md5Hex(url.toExternalForm() + request);
String contents;
long age = getAgeOfFile(cacheFilename);
if (age > validationTimeout) {
logger.debug("serving: {} from target comms (will write to cache file: {})", url, cacheFilename);
contents = targetComms.getResourceByRawHttp(url, request);
createFolderIfNeeded();
OutputStream fos = new BufferedOutputStream(new FileOutputStream(cacheFolder + "/" + cacheFilename));
IOUtils.write(contents, fos);
fos.flush();
fos.close();
} else {
logger.debug("serving: {} from cache ({})", url, cacheFilename);
FileInputStream fis = new FileInputStream(cacheFolder + "/" + cacheFilename);
contents = IOUtils.toString(fis);
fis.close();
}
return contents;
} catch (IOException e) {
logger.error("Error getting url: " + e.getMessage(), e);
throw new RuntimeException("Error getting url: " + e.getMessage(), e);
}
}
}