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

Response headers & Last-Modified

parent 23397ff1
Branches refactor-html
Tags deployed-services-2013-09-06
No related merge requests found
...@@ -28,7 +28,8 @@ ...@@ -28,7 +28,8 @@
import javax.ws.rs.QueryParam; import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException; import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context; import javax.ws.rs.core.Context;
import javax.ws.rs.core.StreamingOutput; import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.xml.transform.stream.StreamSource; import javax.xml.transform.stream.StreamSource;
import net.sf.saxon.s9api.Processor; import net.sf.saxon.s9api.Processor;
...@@ -199,7 +200,7 @@ private static boolean isPublic(final ObjectType metadata) { ...@@ -199,7 +200,7 @@ private static boolean isPublic(final ObjectType metadata) {
@GET @GET
@Path(value = "/{object}") @Path(value = "/{object}")
@Produces(value = "text/xml") @Produces(value = "text/xml")
public StreamingOutput get( public Response get(
@Description("The TextGrid URI of the TEI document or aggregation to transform") @Description("The TextGrid URI of the TEI document or aggregation to transform")
@PathParam("object") final URI uri, @PathParam("object") final URI uri,
@Description("If given, an alternative XSLT stylesheet to use") @Description("If given, an alternative XSLT stylesheet to use")
...@@ -211,17 +212,17 @@ public StreamingOutput get( ...@@ -211,17 +212,17 @@ public StreamingOutput get(
@QueryParam("sid") final String sid, @QueryParam("sid") final String sid,
@Description("If true, pass the information the stylesheet that its result will be embedded into some website") @QueryParam("embedded") final boolean embedded, @Description("If true, pass the information the stylesheet that its result will be embedded into some website") @QueryParam("embedded") final boolean embedded,
@Description("URL of the CSS that should be referenced in the HTML that is created") @Description("URL of the CSS that should be referenced in the HTML that is created")
@QueryParam("css") final URI css) throws ObjectNotFoundFault, @QueryParam("css") final URI css,
@Context final Request request) throws ObjectNotFoundFault,
MetadataParseFault, IoFault, AuthFault, MetadataParseFault, IoFault, AuthFault,
ProtocolNotImplementedFault, WebApplicationException, IOException, ProtocolNotImplementedFault, WebApplicationException, IOException,
SaxonApiException, ExecutionException { SaxonApiException, ExecutionException {
logger.fine("HTML called for root object: " + uri); logger.fine("HTML called for root object: " + uri);
final HTMLWriter writer = new HTMLWriter(this, uri, xsluri, final HTMLWriter writer = new HTMLWriter(this, uri, xsluri,
refreshStylesheet, pi, embedded, css, sid); refreshStylesheet, pi, embedded, css, sid, request);
writer.loadSource(); return writer.createResponse().build();
writer.loadStylesheet();
return writer;
} }
} }
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
import info.textgrid.services.aggregator.ITextGridRep; import info.textgrid.services.aggregator.ITextGridRep;
import info.textgrid.services.aggregator.ITextGridRep.TGOSupplier; import info.textgrid.services.aggregator.ITextGridRep.TGOSupplier;
import info.textgrid.services.aggregator.teicorpus.TEICorpusSerializer; import info.textgrid.services.aggregator.teicorpus.TEICorpusSerializer;
import info.textgrid.utils.export.filenames.DefaultFilenamePolicy;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
...@@ -21,6 +22,11 @@ ...@@ -21,6 +22,11 @@
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.ws.rs.WebApplicationException; import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.StreamingOutput; import javax.ws.rs.core.StreamingOutput;
import javax.xml.transform.Source; import javax.xml.transform.Source;
...@@ -111,6 +117,10 @@ private enum SourceType { ...@@ -111,6 +117,10 @@ private enum SourceType {
private String actualStylesheet; private String actualStylesheet;
private TGOSupplier<InputStream> content;
private Request request;
// Constructor and configuration // Constructor and configuration
public HTMLWriter(final HTML service, final URI rootURI) { public HTMLWriter(final HTML service, final URI rootURI) {
...@@ -125,7 +135,7 @@ public HTMLWriter(final HTML service, final URI rootURI) { ...@@ -125,7 +135,7 @@ public HTMLWriter(final HTML service, final URI rootURI) {
public HTMLWriter(final HTML service, final URI rootURI, public HTMLWriter(final HTML service, final URI rootURI,
final URI stylesheetURI, final boolean refreshStylesheet, final URI stylesheetURI, final boolean refreshStylesheet,
final boolean readStylesheetPI, final boolean embedded, final boolean readStylesheetPI, final boolean embedded,
final URI css, final String sid) { final URI css, final String sid, final Request request) {
this(service, rootURI); this(service, rootURI);
...@@ -135,6 +145,7 @@ public HTMLWriter(final HTML service, final URI rootURI, ...@@ -135,6 +145,7 @@ public HTMLWriter(final HTML service, final URI rootURI,
this.embedded = embedded; this.embedded = embedded;
this.css = Optional.fromNullable(css); this.css = Optional.fromNullable(css);
this.sid(sid); this.sid(sid);
this.request = request;
} }
public HTMLWriter sid(final String sid) { public HTMLWriter sid(final String sid) {
...@@ -173,9 +184,7 @@ protected HTMLWriter loadSource() throws ObjectNotFoundFault, ...@@ -173,9 +184,7 @@ protected HTMLWriter loadSource() throws ObjectNotFoundFault,
MetadataParseFault, MetadataParseFault,
IoFault, ProtocolNotImplementedFault, AuthFault, IOException { IoFault, ProtocolNotImplementedFault, AuthFault, IOException {
TGOSupplier<InputStream> content = null; metadata = getContent().getMetadata();
content = service.repository.read(rootURI, sid.orNull());
metadata = content.getMetadata();
final String format = metadata.getGeneric().getProvided().getFormat(); final String format = metadata.getGeneric().getProvided().getFormat();
if (format.contains("aggregation")) { if (format.contains("aggregation")) {
sourceType = SourceType.AGGREGATION; sourceType = SourceType.AGGREGATION;
...@@ -202,11 +211,11 @@ protected HTMLWriter loadSource() throws ObjectNotFoundFault, ...@@ -202,11 +211,11 @@ protected HTMLWriter loadSource() throws ObjectNotFoundFault,
} else if (sourceType == SourceType.XML && readStylesheetPI) { } else if (sourceType == SourceType.XML && readStylesheetPI) {
final FileBackedOutputStream xmlBuffer = new FileBackedOutputStream( final FileBackedOutputStream xmlBuffer = new FileBackedOutputStream(
1024 * 1024, true); 1024 * 1024, true);
ByteStreams.copy(content, xmlBuffer); ByteStreams.copy(getContent(), xmlBuffer);
detectEmbeddedStylesheet(xmlBuffer.getSupplier().getInput()); detectEmbeddedStylesheet(xmlBuffer.getSupplier().getInput());
this.source = new StreamSource(xmlBuffer.getSupplier().getInput()); this.source = new StreamSource(xmlBuffer.getSupplier().getInput());
} else { } else {
this.source = new StreamSource(content.getInput(), this.source = new StreamSource(getContent().getInput(),
rootURI.toString()); rootURI.toString());
} }
logger.log(Level.INFO, MessageFormat.format("Fetched source for {0}, type={1}, after {2}", rootURI, sourceType, stopwatch.toString())); logger.log(Level.INFO, MessageFormat.format("Fetched source for {0}, type={1}, after {2}", rootURI, sourceType, stopwatch.toString()));
...@@ -214,6 +223,14 @@ protected HTMLWriter loadSource() throws ObjectNotFoundFault, ...@@ -214,6 +223,14 @@ protected HTMLWriter loadSource() throws ObjectNotFoundFault,
return this; return this;
} }
private TGOSupplier<InputStream> getContent() {
if (content == null) {
content = service.repository.read(rootURI, sid.orNull());
logger.info(MessageFormat.format("Fetched source for {0} up to metadata after {1}", rootURI, stopwatch));
}
return content;
}
private void detectEmbeddedStylesheet(final InputStream input) { private void detectEmbeddedStylesheet(final InputStream input) {
try { try {
final Source associatedStylesheet = TransformerFactory final Source associatedStylesheet = TransformerFactory
...@@ -302,4 +319,30 @@ public void write(final OutputStream out) throws IOException, ...@@ -302,4 +319,30 @@ public void write(final OutputStream out) throws IOException,
stopwatch.stop(); stopwatch.stop();
} }
public ResponseBuilder createResponse() throws ObjectNotFoundFault, MetadataParseFault, IoFault, ProtocolNotImplementedFault, AuthFault, IOException, SaxonApiException {
if (!refreshStylesheet && request != null) {
final ResponseBuilder builder = request.evaluatePreconditions(getContent().getMetadata().getGeneric().getGenerated().getLastModified().toGregorianCalendar().getTime());
if (builder != null) {
logger.info(MessageFormat.format("Aborting: client already has HTML for {0} (after {1})", rootURI, stopwatch));
return builder;
} else {
logger.info("Creating new transformation.");
}
}
loadSource();
loadStylesheet();
final ResponseBuilder builder = Response.ok();
builder.type(MediaType.TEXT_XML_TYPE);
builder.lastModified(getContent().getMetadata().getGeneric().getGenerated().getLastModified().toGregorianCalendar().getTime());
final CacheControl cacheControl = new CacheControl();
cacheControl.setPrivate(sid.isPresent());
cacheControl.setMaxAge(86400); // one day
builder.cacheControl(cacheControl);
builder.header("Content-Disposition", "inline;filename=\"" + DefaultFilenamePolicy.INSTANCE.getFilename(getContent().getMetadata(), false) + ".html\"");
builder.entity(this);
return builder;
}
} }
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