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

Refactored PDF export

parent bf475f1c
No related branches found
No related tags found
No related merge requests found
......@@ -121,7 +121,7 @@ protected Source loadSource(final boolean bufferRequired)
rootURIs, format);
throw new WebApplicationException(
GenericExceptionMapper.toResponse(
Status.UNSUPPORTED_MEDIA_TYPE, errorMsg, ""));
Status.UNSUPPORTED_MEDIA_TYPE, errorMsg, "").build());
}
}
......
......@@ -91,7 +91,7 @@ public Response toResponse(final Exception exception) {
.getSimpleName(), exception.getMessage(), status
.getStatusCode(), status.toString()), exception);
final Response response = toResponse(status, message, Throwables.getStackTraceAsString(exception));
final Response response = toResponse(status, message, Throwables.getStackTraceAsString(exception)).build();
return response;
}
......@@ -102,12 +102,12 @@ public Response toResponse(final Exception exception) {
* @param detail a detail message, e.g., a stack trace. Will be HTML-escaped and displayed in a preformatted way below the status msg.
* @return the generated response.
*/
public static Response toResponse(final Status status,
public static ResponseBuilder toResponse(final Status status,
final String message, final String detail) {
final ResponseBuilder builder = Response.status(status);
builder.type(MediaType.APPLICATION_XHTML_XML_TYPE);
builder.entity(prepareXHTMLMessage(status, message, detail));
return builder.build();
return builder;
}
public static String prepareXHTMLMessage(final Status status,
......
......@@ -7,6 +7,7 @@
import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.ProtocolNotImplementedFault;
import info.textgrid.services.aggregator.epub.EPUBSerializer;
import info.textgrid.services.aggregator.html.HTMLWriter;
import info.textgrid.services.aggregator.pdf.PDF;
import info.textgrid.services.aggregator.teicorpus.TEICorpusExporter;
import info.textgrid.services.aggregator.zip.ZipResult;
......@@ -146,6 +147,21 @@ public Response getZIP(
return zipResult.createResponse().build();
}
@GET
@Path(value = "/pdf/{object}")
@Produces("application/pdf")
public Response getPDF(
@PathParam("object") final URI uri,
@QueryParam("sid") final String sid,
@Context final Request request
) throws MetadataParseFault, ObjectNotFoundFault, IoFault, AuthFault, ProtocolNotImplementedFault, IOException, SaxonApiException {
final PDF pdf = new PDF(repository, getStylesheetManager(), request, uri);
pdf.sid(sid);
return pdf.createResponse().build();
}
@GET
@Path(value = "/version")
@Produces("text/html")
......
......@@ -221,7 +221,7 @@ public PrivateResourceException(final XsltExecutable xsltExecutable) {
}
private URL resolveInternalPath(final String path)
URL resolveInternalPath(final String path)
throws MalformedURLException {
URL stylesheet;
if (servlet == null) {
......
......@@ -63,7 +63,7 @@ public void write(final OutputStream outputStream)
info.getProperty("git.branch", "?"),
info.getProperty("git.commit.time", "?"),
info.getProperty("git.build.time", "?"));
out.printf(
"<p>TextGridRep Configuration Endpoint: <a href='%1$s'>%1$s</a></p>\n\n",
repository.getCONF_ENDPOINT());
......@@ -74,7 +74,7 @@ public void write(final OutputStream outputStream)
out.println("</td></tr></table>");
out.printf("<p>Using TG-crud version: <strong>%s</strong>\n",
repository.getCRUDService().getVersion());
out.println("</body></html>");
out.close();
outputStream.close();
......
package info.textgrid.services.aggregator.pdf;
import info.textgrid._import.RewriteMethod;
import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.AuthFault;
import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.IoFault;
import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.MetadataParseFault;
import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.ObjectNotFoundFault;
import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.ProtocolNotImplementedFault;
import info.textgrid.services.aggregator.AbstractExporter;
import info.textgrid.services.aggregator.GenericExceptionMapper;
import info.textgrid.services.aggregator.ITextGridRep;
import info.textgrid.services.aggregator.ITextGridRep.TGOSupplier;
import info.textgrid.services.aggregator.RESTUtils;
import info.textgrid.services.aggregator.StylesheetManager;
import info.textgrid.services.aggregator.XSLTErrorListener;
import info.textgrid.utils.linkrewriter.ConfigurableXMLRewriter;
import info.textgrid.utils.linkrewriter.ImportMapping;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.io.OutputStream;
import java.net.URI;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.Set;
import java.util.logging.Logger;
import javax.servlet.ServletContext;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.Response.Status;
import javax.xml.stream.XMLStreamException;
import javax.xml.transform.stream.StreamSource;
import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.XsltCompiler;
import net.sf.saxon.s9api.XsltExecutable;
import net.sf.saxon.s9api.XsltTransformer;
import org.apache.commons.io.FileUtils;
......@@ -51,31 +49,34 @@
"This is currently highly experimental, and it requires LaTeX and " +
"the TEI stylesheets to be installed on the machine onto which " +
"this service is deployed.")
public class PDF {
public class PDF extends AbstractExporter {
private static final String TO_PDF_XSL = "/WEB-INF/xml/tei/stylesheet/latex2/tei.xsl";
private static final URI TO_PDF_XSL = URI.create("/WEB-INF/xml/tei/stylesheet/latex2/tei.xsl");
final Logger logger = Logger
.getLogger("info.textgrid.services.aggregator.pdf");
private XsltExecutable teiToLatex;
private final Processor xsltProcessor;
private final ITextGridRep repository;
@Context
private ServletContext servlet;
public PDF(final ITextGridRep repository) {
this.repository = repository;
xsltProcessor = new Processor(false);
private StylesheetManager stylesheetManager;
private File workingDir;
public PDF(final ITextGridRep repository, final StylesheetManager manager, final Request request, final URI uri) {
super(repository, request, uri.toString());
this.stylesheetManager = manager;
this.setFileExtension("pdf");
this.setMediaType("application/pdf");
}
@GET
@Path("/{uri}")
@Produces("application/pdf")
public Response get(
@Description("The TextGrid URI of a TEI document to transform") @PathParam("uri") final URI uri,
@Description("Session ID to access protected resources") @QueryParam("sid") final String sid) {
final File workingDir = Files.createTempDir();
public ResponseBuilder createResponse() throws MetadataParseFault, ObjectNotFoundFault, IoFault, AuthFault, ProtocolNotImplementedFault, IOException, SaxonApiException {
super.createResponse();
if (isNotModified())
return getResponseBuilder();
workingDir = Files.createTempDir();
try {
// First step: Rewrite with a non-initalized mapping to a temporary
......@@ -86,10 +87,10 @@ public Response get(
mapping, true);
rewriter.configure(URI.create("internal:tei#tei"));
rewriter.recordMissingReferences();
final TGOSupplier<InputStream> textSupplier = repository.read(uri, sid);
final TGOSupplier<InputStream> textSupplier = getContent();
final String rootObjectFormat = textSupplier.getMetadata().getGeneric().getProvided().getFormat();
if (!rootObjectFormat.startsWith("text/xml"))
return GenericExceptionMapper.toResponse(Status.UNSUPPORTED_MEDIA_TYPE, "PDF generation currently supports only text/xml documents. The requested document, " + uri + ", has an invalid document type, however:", rootObjectFormat);
return GenericExceptionMapper.toResponse(Status.UNSUPPORTED_MEDIA_TYPE, "PDF generation currently supports only text/xml documents. The requested documen has an invalid document type, however:", rootObjectFormat);
final FileBackedOutputStream buffer = new FileBackedOutputStream(
1024 * 1024);
......@@ -107,7 +108,7 @@ public Response get(
&& mapping
.getImportObjectForTextGridURI(missingReference) == null) {
final TGOSupplier<InputStream> supplier = repository.read(
missingURI, sid);
missingURI, getSid().get());
final String format = supplier.getMetadata().getGeneric()
.getProvided().getFormat();
String fileName = null;
......@@ -140,9 +141,9 @@ public Response get(
buffer.close();
// now generate the TeX
final XsltTransformer transformer = getTeiToLatex().load();
final XsltTransformer transformer = stylesheetManager.getStylesheet(TO_PDF_XSL, getSid(), false, true).load();
final File tex = new File(workingDir, "data.tex");
transformer.setDestination(xsltProcessor.newSerializer(tex));
transformer.setDestination(stylesheetManager.xsltProcessor.newSerializer(tex));
transformer.setSource(new StreamSource(teiFile));
transformer.setErrorListener(new XSLTErrorListener(logger));
transformer.transform();
......@@ -154,22 +155,12 @@ public Response get(
if (latexProcess.waitFor() != 0) {
final File logFile = new File(workingDir, "data.log");
if (logFile.canRead())
return GenericExceptionMapper.toResponse(Status.INTERNAL_SERVER_ERROR, "The requested document, " + uri + ", was transformed to a file LaTeX failed to deal with. Below is the LaTeX log file.",
return GenericExceptionMapper.toResponse(Status.INTERNAL_SERVER_ERROR, "The requested document was transformed to a file LaTeX failed to deal with. Below is the LaTeX log file.",
Files.toString(logFile, Charset.forName("UTF-8")));
else
throw new IllegalStateException("LaTeX process failed, no log file found.");
}
final Response response = RESTUtils
.attachmentResponse(
textSupplier.getMetadata().getGeneric()
.getProvided().getTitle().get(0)
.concat(".pdf"))
.type("application/pdf")
.entity(new FileInputStream(
new File(workingDir, "data.pdf"))).build();
FileUtils.deleteDirectory(workingDir);
return response;
return getResponseBuilder();
} catch (final IOException e) {
throw new WebApplicationException(e);
......@@ -182,24 +173,24 @@ public Response get(
}
}
public XsltExecutable getTeiToLatex() {
if (teiToLatex == null) {
try {
final URL stylesheet = servlet.getResource(TO_PDF_XSL);
final XsltCompiler xsltCompiler = xsltProcessor
.newXsltCompiler();
teiToLatex = xsltCompiler.compile(new StreamSource(stylesheet
.toString()));
} catch (final MalformedURLException e) {
throw new IllegalStateException(
"Failed to initialize TEI to LaTeX stylesheet", e);
} catch (final SaxonApiException e) {
throw new IllegalStateException(
"Failed to initialize TEI to LaTeX stylesheet", e);
}
@Override
public void write(OutputStream output) throws IOException {
try {
Files.copy(new File(workingDir, "data.pdf"), output);
} finally {
FileUtils.deleteDirectory(workingDir);
workingDir = null;
}
return teiToLatex;
}
@Override
protected void finalize() throws Throwable {
if (workingDir != null && workingDir.exists())
FileUtils.deleteDirectory(workingDir);
super.finalize();
}
}
......@@ -9,6 +9,7 @@
import net.sf.saxon.s9api.XsltExecutable;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import com.google.common.base.Optional;
......@@ -27,6 +28,8 @@ public void setUp() {
public void testGetInternalStylesheet() throws SaxonApiException, IOException {
testGetStylesheet(INTERNAL_XSL);
}
@Ignore("Need a stable available XSLT")
@Test
public void testGetHttpStylesheet() throws SaxonApiException, IOException {
URI teiStylesheet = URI.create("http://www.tei-c.org/Vault/P5/2.5.0/xml/tei/stylesheet/html/html.xsl");
......
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