/*
* Copyright 2013 Esri.
*
* 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.esri.gpt.control.georss.dcatcache;
import com.esri.gpt.framework.collection.StringAttributeMap;
import com.esri.gpt.framework.context.ApplicationConfiguration;
import com.esri.gpt.framework.context.ApplicationContext;
import com.esri.gpt.framework.util.Val;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Pattern;
/**
* DCAT cache.
*/
public class DcatCache {
private static final Pattern CACHE_NAME_PATTERN = Pattern.compile("cache[^.]*\\.dcat",Pattern.CASE_INSENSITIVE);
private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd hh-mm");
private static DcatCache instance;
private File root;
/**
* Gets instance of the cache.
* @return singleton instance of the cache
*/
public static DcatCache getInstance() {
if (instance==null) {
ApplicationContext appCtx = ApplicationContext.getInstance();
ApplicationConfiguration appCfg = appCtx.getConfiguration();
StringAttributeMap parameters = appCfg.getCatalogConfiguration().getParameters();
String dcatCachePath = Val.chkStr(parameters.getValue("dcat.cache.path"),getDefaultDCATPath());
File root = new File(dcatCachePath);
instance = new DcatCache(root);
}
return instance;
}
/**
* Gets default DCAT cache path.
* @return default DCAT cache path
*/
private static String getDefaultDCATPath() {
File home = new File(System.getProperty("user.home"));
return new File(home, "dcat/cache").getAbsolutePath();
}
/**
* Creates cache stream from the latest cache data.
* @return input stream
* @throws FileNotFoundException if cache data file not found
*/
public InputStream createInputCacheStream() throws FileNotFoundException {
File [] cacheFiles = listCacheFiles();
File latestCache = findLatest(cacheFiles);
if (latestCache==null) {
throw new FileNotFoundException("No recent cache found.");
}
return new FileInputStream(latestCache);
}
/**
* Creates output stream to write into the cache.
* @return output stream
* @throws FileNotFoundException if can not create stream
*/
public OutputStream createOutputCacheStream() throws FileNotFoundException {
File file = new File(root,"cache-"+SDF.format(new Date())+".temp");
return new CacheOutputStream(file);
}
/**
* Creates instance of the cache.
* @param root root folder of the cache
*/
public DcatCache(File root) {
this.root = root;
}
/**
* Lists all cache files.
* @return array of cache files
*/
private File[] listCacheFiles() {
return root.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return CACHE_NAME_PATTERN.matcher(name).matches();
}
});
}
/**
* Finds the latest file.
* @param files array of files
* @return latest file or <code>null</code> if no latest file available
*/
private File findLatest(File [] files) {
File latest = null;
if (files!=null) {
for (File f: files) {
if (latest==null || f.lastModified()>latest.lastModified()) {
latest = f;
}
}
}
return latest;
}
/**
* Purges outdated files.
* @param files list of files
* @param latest latest file
*/
private void purgeOutdatedFiles(File [] files, File latest) {
for (File f: files) {
if (!f.equals(latest)) {
f.delete();
}
}
}
/**
* Cache output stream
*/
private class CacheOutputStream extends OutputStream {
private File file;
private FileOutputStream fileOutputStream;
/**
* Creates instance of the stream.
* @param file file representing the stream
* @throws FileNotFoundException if creating stream fails
*/
public CacheOutputStream(File file) throws FileNotFoundException {
this.file = file;
this.file.getParentFile().mkdirs();
this.fileOutputStream = new FileOutputStream(file);
}
@Override
public void write(int b) throws IOException {
fileOutputStream.write(b);
}
@Override
public void close() throws IOException {
fileOutputStream.close();
String name = file.getName();
name = name.replaceAll("\\.[^.]+$", ".dcat");
file.renameTo(new File(file.getParentFile(), name));
File[] files = listCacheFiles();
purgeOutdatedFiles(files, findLatest(files));
}
}
}