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

Added support for textgrid: URIs everywhere.

parent 0ce49e68
No related branches found
No related tags found
No related merge requests found
......@@ -10,6 +10,7 @@
import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.TGCrudService;
import info.textgrid.services.aggregator.GenericExceptionMapper;
import info.textgrid.services.aggregator.ITextGridRep;
import info.textgrid.services.aggregator.ITextGridRep.TGOSupplier;
import info.textgrid.services.aggregator.TextGridRepProvider;
import info.textgrid.services.aggregator.teicorpus.TEICorpusSerializer;
......@@ -46,9 +47,10 @@
import org.apache.cxf.jaxrs.model.wadl.Description;
import com.google.common.base.Stopwatch;
import com.google.common.cache.Cache;
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;
......@@ -71,7 +73,7 @@ public class HTML {
@Context
private ServletContext servlet;
private LoadingCache<URI, XsltExecutable> stylesheets;
private Cache<URI, XsltExecutable> stylesheets;
private XsltExecutable getToHtml() {
if (toHtml == null) {
......@@ -93,7 +95,12 @@ private XsltExecutable getToHtml() {
public HTML(final ITextGridRep repository) throws IOException {
this.repository = repository;
xsltProcessor = new Processor(false);
stylesheets = CacheBuilder.newBuilder().maximumSize(50).weakValues()
xsltProcessor.getUnderlyingConfiguration().setURIResolver(
new TGUriResolver(repository));
// xsltProcessor.getUnderlyingConfiguration().setAllowExternalFunctions(
// false); // we run external stylesheets
xsltProcessor.getUnderlyingConfiguration().setCompileWithTracing(true);
stylesheets = CacheBuilder.newBuilder().maximumSize(50).softValues()
.removalListener(new RemovalListener<URI, XsltExecutable>() {
@Override
......@@ -127,6 +134,76 @@ public XsltExecutable load(final URI url) throws Exception {
}
/**
* Returns an appropriate stylesheet for the given URI.
*
* Basically, we try the following options in order:
* <ol>
* <li>The stylesheet is cached -> return the cached version.
* <li>The stylesheet is public or external -> load & cache it.
* <li>The stylesheet is non-public TextGrid internal -> load & do not cache
* it.
* </ol>
*
* @param uri
* the URI of the stylesheet to load
* @param sid
* the session ID to use, or null.
* @param forceLoad
* TODO
* @throws IOException
* if an error occurs reading the stylesheet.
* @throws SaxonApiException
* if saxon fails to compile the stylesheet.
*/
protected XsltExecutable getStylesheet(final URI uri, final String sid,
final boolean forceLoad) throws SaxonApiException, IOException {
XsltExecutable executable = null;
// (1) try cached version, if it exists
if (!forceLoad) {
executable = stylesheets.getIfPresent(uri);
}
if (executable == null) {
final XsltCompiler compiler = xsltProcessor.newXsltCompiler();
if (TGUriResolver.isResolveable(uri)) {
// (2/3) it's a TextGrid object, load it from TG-crud.
final TGOSupplier<InputStream> xsltSupplier = repository.read(uri, sid);
executable = compiler.compile(new StreamSource(xsltSupplier
.getInput(), uri.toString()));
if (isPublic(xsltSupplier.getMetadata())) {
// (2) it's public -> we can cache it.
stylesheets.put(uri, executable);
logger.log(Level.INFO, "Cached public stylesheet {0}", uri);
} else {
logger.log(Level.INFO, "Loaded private stylesheet {0}", uri);
}
} 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);
}
} else {
logger.log(Level.INFO, "Reusing cached stylesheed {0}", uri);
}
return executable;
}
private static boolean isPublic(final ObjectType metadata) {
try {
return metadata.getGeneric().getGenerated().getAvailability()
.contains("public");
} catch (final NullPointerException e) {
return false;
}
}
@GET
@Path(value = "/{object}")
@Produces(value = "text/html")
......@@ -145,6 +222,9 @@ public StreamingOutput get(
SaxonApiException, ExecutionException {
logger.fine("HTML called for root object: " + uri);
final Stopwatch stopwatch = new Stopwatch();
stopwatch.start();
final TGCrudService crud = repository.getCRUDService();
final MetadataContainerType container = crud.readMetadata(sid, null,
uri.toString());
......@@ -170,16 +250,18 @@ public StreamingOutput get(
} else {
tei = repository.getContent(uri, sid);
}
logger.info("we have an input document after " + stopwatch.toString());
final XsltTransformer transformer;
if (xsluri == null || "".equals(xsluri)) {
transformer = getToHtml().load();
} else {
if (refreshStylesheet) {
stylesheets.refresh(xsluri);
}
transformer = stylesheets.get(xsluri).load();
transformer = getStylesheet(xsluri, sid, refreshStylesheet).load();
if (sid != null) {
transformer.setURIResolver(new TGUriResolver(repository, sid));
} // otherwise default public URI resolver
}
transformer.setSource(new StreamSource(tei));
transformer.setParameter(new QName("graphicsURLPattern"),
new XdmAtomicValue(repository.getCRUDRestEndpoint()
......@@ -190,6 +272,7 @@ public StreamingOutput get(
transformer.setParameter(new QName("cssFile"), new XdmAtomicValue(css));
}
logger.info("we're ready to transform after " + stopwatch.toString());
return new StreamingOutput() {
@Override
......@@ -198,8 +281,9 @@ public void write(final OutputStream output) throws IOException,
transformer.setDestination(xsltProcessor.newSerializer(output));
try {
transformer.transform();
logger.info("Finished transformation to HTML for "
+ uri);
logger.info(MessageFormat
.format("Finished transformation to HTML for {0} after {1}",
uri, stopwatch.toString()));
} catch (final SaxonApiException e) {
throw new WebApplicationException(e);
}
......
package info.textgrid.services.aggregator.html;
import info.textgrid.services.aggregator.ITextGridRep;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;
import javax.xml.transform.URIResolver;
import javax.xml.transform.stream.StreamSource;
import com.google.common.base.Optional;
import com.ibm.icu.text.MessageFormat;
public class TGUriResolver implements URIResolver {
private final Optional<String> sid;
private final String crudRestEndpoint;
final static Logger logger = Logger
.getLogger("info.textgrid.services.aggregator.html.URIResolver");
public TGUriResolver(final ITextGridRep repository,
final Optional<String> sid) {
super();
crudRestEndpoint = repository.getCRUDRestEndpoint();
this.sid = sid;
}
public TGUriResolver(final ITextGridRep repository) {
this(repository, Optional.<String> absent());
}
public TGUriResolver(final ITextGridRep repository, final String sid) {
this(repository, sid == null || "".equals(sid) ? Optional
.<String> absent() : Optional.of(sid));
}
public static boolean isResolveable(final URI uri) {
final String scheme = uri.getScheme();
return "textgrid".equals(scheme) || "hdl".equals(scheme);
}
@Override
public Source resolve(final String href, final String base) throws TransformerException {
logger.info(MessageFormat.format(
"Trying to resolve href={0}, base={1}", href, base));
try {
final URI uri = new URI(href).resolve(base);
if (isResolveable(uri)) {
final StringBuilder resolved = new StringBuilder(
crudRestEndpoint);
resolved.append('/').append(uri.getScheme()).append(':')
.append(uri.getSchemeSpecificPart()).append("/data");
if (sid.isPresent()) {
resolved.append("?sessionId=").append(sid.get());
}
if (uri.getFragment() != null) {
resolved.append('#').append(uri.getFragment());
}
final URL url = new URL(resolved.toString());
logger.log(Level.INFO,
MessageFormat.format("Resolved {0} to {1}", uri, url));
return new StreamSource(url.openStream(), href);
} else {
logger.log(Level.INFO, "Did not resolve {0}", uri);
return null;
}
} catch (final URISyntaxException e) {
throw new TransformerException(e);
} catch (final MalformedURLException e) {
throw new TransformerException(e);
} catch (final IOException e) {
throw new TransformerException(e);
}
}
}
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