Skip to content
Snippets Groups Projects
Commit 6dba75be authored by Thorsten Vitt's avatar Thorsten Vitt
Browse files

Adjusted StylesheetManager to Cache API.

parent a4b9ca4f
No related branches found
No related tags found
No related merge requests found
......@@ -11,6 +11,8 @@
import java.net.URL;
import java.text.MessageFormat;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
......@@ -23,6 +25,7 @@
import net.sf.saxon.s9api.XsltExecutable;
import com.google.common.base.Optional;
import com.google.common.base.Throwables;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
......@@ -35,7 +38,8 @@
/**
* Manages and caches XSLT stylesheets across service calls, also maintains
* processor policies etc. All stylesheets invoked throughout the service should
* be invoked through the manager's {@link #getStylesheet(URI, Optional, boolean, boolean)} method.
* be invoked through the manager's
* {@link #getStylesheet(URI, Optional, boolean, boolean)} method.
*/
public class StylesheetManager {
private static final Logger logger = Logger
......@@ -132,25 +136,50 @@ public XsltExecutable load(final URI url) throws Exception {
public XsltExecutable getStylesheet(final URI uri,
final Optional<String> sid, final boolean forceLoad,
final boolean frequentlyUsed) throws SaxonApiException, IOException {
XsltExecutable executable = null;
// (1) try cached version, if it exists
if (!forceLoad) {
executable = stylesheets.getIfPresent(uri);
if (frequentlyUsed)
importantStylesheets.add(uri);
try {
if (forceLoad)
stylesheets.invalidate(uri);
return stylesheets.get(uri, new StylesheetLoader(uri, sid));
} catch (final ExecutionException e) {
final Throwable cause = e.getCause();
if (cause instanceof PrivateResourceException)
return ((PrivateResourceException) cause).getXsltExecutable();
else {
Throwables.propagateIfPossible(cause, SaxonApiException.class,
IOException.class);
return null; // will never be reached
}
}
if (executable == null) {
if (frequentlyUsed)
importantStylesheets.add(uri);
}
final XsltCompiler compiler = xsltProcessor.newXsltCompiler();
private final class StylesheetLoader implements Callable<XsltExecutable> {
private final URI uri;
private final Optional<String> sid;
// (2) it's internal, load & cache it from the servlet
private StylesheetLoader(final URI uri, final Optional<String> sid) {
this.uri = uri;
this.sid = sid;
}
@Override
public XsltExecutable call() throws Exception {
final XsltCompiler compiler = xsltProcessor.newXsltCompiler();
final XsltExecutable executable;
if (uri.getScheme() == null || uri.getScheme() == "file") {
// (1) Internal
final URL resource = resolveInternalPath(uri.getPath());
executable = compiler.compile(new StreamSource(resource.openStream(), resource.toExternalForm()));
stylesheets.put(uri, executable);
logger.log(Level.INFO, "Cached internal stylesheet {0}", resource);
executable = compiler.compile(new StreamSource(resource
.openStream(), resource.toExternalForm()));
logger.log(Level.INFO, "Cached internal stylesheet {0}",
resource);
return executable;
} else if (TGUriResolver.isResolveable(uri)) {
// (3/4) it's a TextGrid object, load it from TG-crud.
......@@ -161,26 +190,39 @@ public XsltExecutable getStylesheet(final URI uri,
if (isPublic(xsltSupplier.getMetadata())) {
// (3) it's public -> we can cache it.
stylesheets.put(uri, executable);
logger.log(Level.INFO, "Cached public stylesheet {0}", uri);
return executable;
} else {
// (4) it's private -> no caching
logger.log(Level.INFO, "Loaded private stylesheet {0}", uri);
throw new PrivateResourceException(executable);
}
} else {
// (2) it's non-TextGrid -- load & cache it.
executable = compiler.compile(new StreamSource(uri.toString()));
stylesheets.put(uri, executable);
logger.log(Level.INFO, "Cached external stylesheet {0}", uri);
return executable;
}
} else {
logger.log(Level.INFO, "Reusing cached stylesheed {0}", uri);
}
}
private static class PrivateResourceException extends Exception {
return executable;
private static final long serialVersionUID = -3506322226718139009L;
private XsltExecutable xsltExecutable;
public XsltExecutable getXsltExecutable() {
return xsltExecutable;
}
public PrivateResourceException(final XsltExecutable xsltExecutable) {
super("The source object is private and will not be cached.");
this.xsltExecutable = xsltExecutable;
}
}
private URL resolveInternalPath(final String path) throws MalformedURLException {
private URL resolveInternalPath(final String path)
throws MalformedURLException {
URL stylesheet;
if (servlet == null) {
logger.info("No servlet context, trying fallback property");
......@@ -192,7 +234,8 @@ private URL resolveInternalPath(final String path) throws MalformedURLException
} else {
stylesheet = servlet.getResource(path);
}
logger.fine("Resolved internal stylesheet: " + stylesheet.toExternalForm());
logger.fine("Resolved internal stylesheet: "
+ stylesheet.toExternalForm());
return stylesheet;
}
......@@ -208,7 +251,9 @@ private static boolean isPublic(final ObjectType metadata) {
@Override
protected void finalize() throws Throwable {
if (stylesheets != null)
logger.log(Level.INFO, "Shutting down stylesheet manager. Stats: {0}", stylesheets.stats());
logger.log(Level.INFO,
"Shutting down stylesheet manager. Stats: {0}",
stylesheets.stats());
super.finalize();
}
......@@ -216,5 +261,4 @@ public CacheStats stats() {
return stylesheets.stats();
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment