From 0ce49e687f7548a9f5a1c04bef072fb70386f571 Mon Sep 17 00:00:00 2001
From: Thorsten Vitt <thorsten.vitt@uni-wuerzburg.de>
Date: Thu, 29 Aug 2013 13:10:24 +0000
Subject: [PATCH] Added support for third-party stylesheets

git-svn-id: https://develop.sub.uni-goettingen.de/repos/textgrid/trunk/services/aggregator@14380 7c539038-3410-0410-b1ec-0f2a7bf1c452
---
 .../services/aggregator/html/HTML.java        | 62 +++++++++++++++++--
 1 file changed, 56 insertions(+), 6 deletions(-)

diff --git a/src/main/java/info/textgrid/services/aggregator/html/HTML.java b/src/main/java/info/textgrid/services/aggregator/html/HTML.java
index 44d76ac..a7eaf59 100644
--- a/src/main/java/info/textgrid/services/aggregator/html/HTML.java
+++ b/src/main/java/info/textgrid/services/aggregator/html/HTML.java
@@ -20,6 +20,8 @@
 import java.net.URI;
 import java.net.URL;
 import java.text.MessageFormat;
+import java.util.concurrent.ExecutionException;
+import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import javax.servlet.ServletContext;
@@ -34,8 +36,6 @@
 import javax.ws.rs.core.StreamingOutput;
 import javax.xml.transform.stream.StreamSource;
 
-import org.apache.cxf.jaxrs.model.wadl.Description;
-
 import net.sf.saxon.s9api.Processor;
 import net.sf.saxon.s9api.QName;
 import net.sf.saxon.s9api.SaxonApiException;
@@ -44,6 +44,13 @@
 import net.sf.saxon.s9api.XsltExecutable;
 import net.sf.saxon.s9api.XsltTransformer;
 
+import org.apache.cxf.jaxrs.model.wadl.Description;
+
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.cache.RemovalListener;
+import com.google.common.cache.RemovalNotification;
 import com.google.common.io.FileBackedOutputStream;
 
 @Path("/html")
@@ -64,6 +71,8 @@ public class HTML {
 	@Context
 	private ServletContext servlet;
 
+	private LoadingCache<URI, XsltExecutable> stylesheets;
+
 	private XsltExecutable getToHtml() {
 		if (toHtml == null) {
 			try {
@@ -84,6 +93,38 @@ private XsltExecutable getToHtml() {
 	public HTML(final ITextGridRep repository) throws IOException {
 		this.repository = repository;
 		xsltProcessor = new Processor(false);
+		stylesheets = CacheBuilder.newBuilder().maximumSize(50).weakValues()
+				.removalListener(new RemovalListener<URI, XsltExecutable>() {
+
+					@Override
+					public void onRemoval(
+							final RemovalNotification<URI, XsltExecutable> notification) {
+						logger.info(MessageFormat
+								.format("Removed stylesheet {0} from cache, reason: {1}",
+										notification.getKey(),
+										notification.getCause()));
+					}
+				})
+.build(new CacheLoader<URI, XsltExecutable>() {
+
+					@Override
+					public XsltExecutable load(final URI url) throws Exception {
+						final XsltCompiler compiler = xsltProcessor
+								.newXsltCompiler();
+						try {
+							final XsltExecutable executable = compiler
+									.compile(new StreamSource(url.toString()));
+							logger.log(Level.INFO,
+									"Successfully loaded stylesheet {0}", url);
+							return executable;
+						} catch (final Exception e) {
+							logger.log(Level.SEVERE, MessageFormat.format(
+									"Failed to load stylesheet {0}", url), e);
+							throw e;
+						}
+					}
+				});
+
 	}
 
 	@GET
@@ -94,13 +135,14 @@ public StreamingOutput get(
 			@PathParam("object") final URI uri,
 			@Description("If given, an alternative XSLT stylesheet to use")
 			@QueryParam("stylesheet") final URI xsluri,
+			@Description("If true and a stylesheet has been given, force reloading the stylesheet, do not cache") @QueryParam("refreshStylesheet") final boolean refreshStylesheet,
 			@Description("Session ID to access protected resources")
 			@QueryParam("sid") final String sid,
 			@Description("URL of the CSS that should be referenced in the HTML that is created")
 			@QueryParam("css") final URI css) throws ObjectNotFoundFault,
 			MetadataParseFault, IoFault, AuthFault,
 			ProtocolNotImplementedFault, WebApplicationException, IOException,
-			SaxonApiException {
+			SaxonApiException, ExecutionException {
 		logger.fine("HTML called for root object: " + uri);
 
 		final TGCrudService crud = repository.getCRUDService();
@@ -129,7 +171,15 @@ public StreamingOutput get(
 			tei = repository.getContent(uri, sid);
 		}
 
-		final XsltTransformer transformer = getToHtml().load();
+		final XsltTransformer transformer;
+		if (xsluri == null || "".equals(xsluri)) {
+			transformer = getToHtml().load();
+		} else {
+			if (refreshStylesheet) {
+				stylesheets.refresh(xsluri);
+			}
+			transformer = stylesheets.get(xsluri).load();
+		}
 		transformer.setSource(new StreamSource(tei));
 		transformer.setParameter(new QName("graphicsURLPattern"),
 				new XdmAtomicValue(repository.getCRUDRestEndpoint()
@@ -148,8 +198,8 @@ public void write(final OutputStream output) throws IOException,
 				transformer.setDestination(xsltProcessor.newSerializer(output));
 				try {
 					transformer.transform();
-					logger.fine("Finished transformation to HTML for "
-							+ rootObject);
+					logger.info("Finished transformation to HTML for "
+ + uri);
 				} catch (final SaxonApiException e) {
 					throw new WebApplicationException(e);
 				}
-- 
GitLab