/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.atomojo.server.xproc;
import com.xmlcalabash.core.XProcConfiguration;
import com.xmlcalabash.core.XProcRuntime;
import com.xmlcalabash.runtime.XPipeline;
import java.io.File;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.logging.Logger;
import net.sf.saxon.s9api.SaxonApiException;
/**
*
* @author alex
*/
public class XProcCache {
static Logger LOG = Logger.getLogger(XProcCache.class.getName());
public static String ATTR = "xproc.cache";
static class PipelineInfo {
List<XPipeline> compiled;
long timestamp;
URI location;
File checkFile;
PipelineInfo(URI location) {
this.location = location;
compiled = new ArrayList<XPipeline>();
timestamp = -1;
checkFile = null;
if (location.getScheme().equals("file")) {
// check file date
checkFile = new File(location.getSchemeSpecificPart());
} else if (location.getScheme().equals("jar")) {
String part = location.getSchemeSpecificPart();
int bang = part.indexOf('!');
if (bang>0) {
URI uri = URI.create(part.substring(0,bang));
if (uri.getScheme().equals("file")) {
checkFile = new File(uri.getSchemeSpecificPart());
}
}
}
}
}
protected Map<URI,PipelineInfo> instances;
protected XProcConfiguration config;
protected XProcRuntime runtime;
public XProcCache() {
config = new XProcConfiguration();
runtime = new XProcRuntime(config);
instances = new TreeMap<URI,PipelineInfo>();
}
public XProcRuntime getRuntime() {
return runtime;
}
public XPipelineContext get(URI location)
throws SaxonApiException
{
PipelineInfo info = null;
synchronized (instances) {
info = instances.get(location);
if (info==null) {
info = new PipelineInfo(location);
instances.put(location,info);
}
}
if (info.timestamp>0 && info.checkFile!=null) {
LOG.info("Checking file: "+info.checkFile+" "+info.checkFile.lastModified()+" vs "+info.timestamp);
if (info.checkFile.lastModified()>info.timestamp) {
LOG.info("Pipeline modified, clearing: "+info.location);
synchronized (info) {
info.compiled.clear();
}
}
}
synchronized (info) {
if (info.compiled.size()>0) {
return new XPipelineContext(location,info.compiled.remove(info.compiled.size()-1),info.timestamp);
}
}
XPipeline pipeline = runtime.load(location.toString());
if (info.timestamp<0) {
synchronized (info) {
info.timestamp = System.currentTimeMillis();
}
}
return new XPipelineContext(location,pipeline,info.timestamp);
}
public void release(XPipelineContext context)
{
context.getPipeline().reset();
PipelineInfo info = null;
synchronized (instances) {
info = instances.get(context.getLocation());
if (info==null) {
return;
}
}
synchronized (info) {
if (info.timestamp==context.getTimestamp()) {
info.compiled.add(context.getPipeline());
}
}
}
public void clear(URI location)
{
List<XPipeline> compiled = null;
synchronized (instances) {
instances.remove(location);
}
}
public void clear()
{
instances = new TreeMap<URI,PipelineInfo>();
}
}