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; } }