package org.arquillian.cube.impl.shrinkwrap.asset;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.concurrent.TimeUnit;
import org.jboss.shrinkwrap.api.asset.UrlAsset;
/**
* Class that extends from UrlAsset which basically stores the URL content in temp directory.
* Every time that same URL is requested to download, first of all it checks if it has been already downloaded previously
* and in this case, and the among of time since it was downloaded has not expired, then the cache content is used.
*/
public class CacheUrlAsset extends UrlAsset {
static String TEMP_LOCATION = System.getProperty("java.io.tmpdir");
private long expirationTime = 1;
private TimeUnit timeUnit = TimeUnit.HOURS;
/**
* Create a new resource with a <code>URL</code> source with default time to live.
*
* @param url
* A valid URL
*
* @throws IllegalArgumentException
* <Code>URL</code> can not be null
*/
public CacheUrlAsset(URL url) {
super(url);
}
public CacheUrlAsset(URL url, long expirationTime, TimeUnit timeUnit) {
super(url);
this.expirationTime = expirationTime;
this.timeUnit = timeUnit;
}
@Override
public InputStream openStream() {
final URL source = this.getSource();
String fileName = getFileName(source);
File file = new File(TEMP_LOCATION, fileName);
try {
if (!file.exists() || !file.isFile() || isExpired(file)) {
InputStream is = super.openStream();
Files.copy(is, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
return new BufferedInputStream(new FileInputStream(file), 8192);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private boolean isExpired(File file) throws IOException {
final BasicFileAttributes fileAttributes = Files.readAttributes(file.toPath(), BasicFileAttributes.class);
final long to = fileAttributes.lastModifiedTime().to(TimeUnit.MILLISECONDS);
final long currentTime = System.currentTimeMillis();
final long expirationTime = TimeUnit.MILLISECONDS.convert(this.expirationTime, this.timeUnit);
if (to + expirationTime < currentTime) {
return true;
}
return false;
}
private String getFileName(URL source) {
final String path = source.getPath();
String fileName;
if (path != null) {
fileName = path.substring(path.lastIndexOf('/') + 1, path.length());
} else {
throw new IllegalArgumentException(
String.format("URL %s does not contain a valid filename to download.", source.toString()));
}
return fileName;
}
}