Support media in DocBook servlet.
[gpl/argeo-suite.git] / publishing / org.argeo.publishing.ui / src / org / argeo / publishing / servlet / DbkServlet.java
index fe4ca32af7c03aef6d312b819844b7920821d7f2..d977377b3a6d4078455faec18fd77579744cf962 100644 (file)
@@ -2,15 +2,18 @@ package org.argeo.publishing.servlet;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
-import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URLDecoder;
 import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 
+import javax.jcr.Node;
 import javax.jcr.Repository;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
+import javax.jcr.nodetype.NodeType;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
@@ -27,24 +30,29 @@ import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 import javax.xml.transform.stream.StreamSource;
 
-import org.apache.xalan.xsltc.trax.SmartTransformerFactoryImpl;
+import org.apache.commons.io.IOUtils;
+import org.apache.xalan.processor.TransformerFactoryImpl;
 import org.argeo.cms.servlet.ServletAuthUtils;
+import org.argeo.docbook.DbkUtils;
 import org.argeo.jcr.Jcr;
 import org.argeo.jcr.JcrException;
+import org.argeo.jcr.JcrUtils;
 import org.w3c.dom.Document;
 
+/**
+ * A servlet transforming a dbk:* JCR node into HTML, using the DocBook XSL.
+ */
 public class DbkServlet extends HttpServlet {
        private static final long serialVersionUID = 6906020513498289335L;
 
        private Repository repository;
 
-       private DocumentBuilderFactory factory;
+       private DocumentBuilderFactory documentBuilderFactory;
        private TransformerFactory transformerFactory;
        private Templates docBoookTemplates;
 
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-               resp.setContentType("text/html; charset=utf-8");
 
                Session session = null;
                try {
@@ -55,62 +63,60 @@ public class DbkServlet extends HttpServlet {
                                pathInfo = pathInfo.substring(1);
                        String path = URLDecoder.decode(pathInfo, StandardCharsets.UTF_8);
 
-                       byte[] arr;
-                       try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
-                               session.exportDocumentView(path, out, true, false);
-                               arr = out.toByteArray();
-                               System.out.println(new String(arr, StandardCharsets.UTF_8));
-                       } catch (RepositoryException e) {
-                               throw new JcrException(e);
-                       }
-
-                       try (InputStream in = new ByteArrayInputStream(arr);
-                                       ByteArrayOutputStream out = new ByteArrayOutputStream();) {
-//                     Source xsl = new StreamSource(new File("/usr/share/sgml/docbook/xsl-stylesheets/xhtml/docbook.xsl"));
-//                     Source xsl = new StreamSource(
-//                                     Files.newBufferedReader(Paths.get("/home/mbaudier/Downloads/docbook-xsl-1.79.2/xhtml/docbook.xsl"),
-//                                                     StandardCharsets.US_ASCII),
-//                                     "file:///home/mbaudier/Downloads/docbook-xsl-1.79.2/xhtml/docbook.xsl");
-                               Source xsl = new StreamSource(
-                                               new File(System.getProperty("user.home") + "/Downloads/docbook-xsl-1.79.2/html/docbook.xsl"));
-//                             if (docBoookTemplates == null) {
-//                                     try {
-//                                             docBoookTemplates = transformerFactory.newTemplates(xsl);
-//                                     } catch (TransformerConfigurationException e) {
-//                                             throw new ServletException("Cannot instantiate XSL " + xsl, e);
-//                                     }
-//                             }
-
-//                     Source xmlInput = new StreamSource(new File("/home/mbaudier/dev/git/gpl/argeo-qa/doc/platform/argeo-platform.dbk.xml"));
-//                     Source xmlInput = new StreamSource(in);
-                               Result xmlOutput = new StreamResult(out);
-
-//                             DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-////                   DocumentBuilderFactory factory = new org.apache.xerces.jaxp.DocumentBuilderFactoryImpl();
-//                             factory.setXIncludeAware(true);
-//                             factory.setNamespaceAware(true);
-                               DocumentBuilder docBuilder = factory.newDocumentBuilder();
-//                     Document doc = docBuilder
-//                                     .parse(new File("/home/mbaudier/dev/git/gpl/argeo-qa/doc/platform/argeo-platform.dbk.xml"));
-                               Document doc = docBuilder.parse(in);
-                               Source xmlInput = new DOMSource(doc);
-
-//                     SAXParserFactory factory = SAXParserFactory.newInstance();
-//                     SAXParser saxParser = factory.newSAXParser();
-//                     Source xmlInput = new SAXSource(saxParser.getXMLReader(),
-//                                     new InputSource(new FileReader(new File("/home/mbaudier/dev/git/gpl/argeo-qa/doc/platform/argeo-platform.dbk.xml"),StandardCharsets.UTF_8)));
-
-//                     Source xmlInput = new StreamSource(
-//                                     new File("/home/mbaudier/dev/workspaces/argeo-suite/xslt-test/input.xml"));
-//                     Result xmlOutput = new StreamResult(new File("output.html"));
-
-//                     TransformerFactory transformerFactory = new org.apache.xalan.processor.TransformerFactoryImpl();
-                               Transformer transformer = transformerFactory.newTransformer(xsl);
-                               transformer.transform(xmlInput, xmlOutput);
-                               resp.getOutputStream().write(out.toByteArray());
-                       } catch (Exception e) {
-                               throw new ServletException("Cannot transform " + path, e);
+                       Node node = session.getNode(path);
+                       if (DbkUtils.isDbk(node)) {
+                               // TODO customise DocBook so that it outputs UTF-8
+                               // see http://www.sagehill.net/docbookxsl/OutputEncoding.html
+                               resp.setContentType("text/html; charset=ISO-8859-1");
+
+                               // TODO optimise with pipes, SAX, etc. ?
+                               byte[] arr;
+                               try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
+                                       session.exportDocumentView(path, out, true, false);
+                                       arr = out.toByteArray();
+//                             System.out.println(new String(arr, StandardCharsets.UTF_8));
+                               } catch (RepositoryException e) {
+                                       throw new JcrException(e);
+                               }
+
+                               try (InputStream in = new ByteArrayInputStream(arr);
+//                                     ByteArrayOutputStream out = new ByteArrayOutputStream();
+                               ) {
+
+                                       Result xmlOutput = new StreamResult(resp.getOutputStream());
+
+                                       DocumentBuilder docBuilder = documentBuilderFactory.newDocumentBuilder();
+//                             Document doc = docBuilder.parse(new File(
+//                                             System.getProperty("user.home") + "/dev/git/gpl/argeo-qa/doc/platform/argeo-platform.dbk.xml"));
+                                       Document doc = docBuilder.parse(in);
+                                       Source xmlInput = new DOMSource(doc);
+
+                                       Transformer transformer = docBoookTemplates.newTransformer();
+                                       transformer.transform(xmlInput, xmlOutput);
+//                             resp.getOutputStream().write(out.toByteArray());
+                               } catch (Exception e) {
+                                       throw new ServletException("Cannot transform " + path, e);
+                               }
+                       } else if (node.isNodeType(NodeType.NT_FILE)) {// media download etc.
+                               String fileNameLowerCase = node.getName().toLowerCase();
+                               if (fileNameLowerCase.endsWith(".jpg") || fileNameLowerCase.endsWith(".jpeg")) {
+                                       resp.setContentType("image/jpeg");
+                               } else if (fileNameLowerCase.endsWith(".png")) {
+                                       resp.setContentType("image/png");
+                               } else if (fileNameLowerCase.endsWith(".gif")) {
+                                       resp.setContentType("image/gif");
+                               } else if (fileNameLowerCase.endsWith(".svg")) {
+                                       resp.setContentType("image/svg+xml");
+                               } else {
+                                       // TODO know more content types...
+                                       resp.setHeader("Content-Disposition", "attachment; filename=\"" + node.getName() + "\"");
+                               }
+                               IOUtils.copy(JcrUtils.getFileAsStream(node), resp.getOutputStream());
+                       } else {
+                               throw new IllegalArgumentException("Unsupported node " + node);
                        }
+               } catch (RepositoryException e1) {
+                       throw new JcrException(e1);
                } finally {
                        Jcr.logout(session);
                }
@@ -118,10 +124,36 @@ public class DbkServlet extends HttpServlet {
 
        @Override
        public void init() throws ServletException {
-               factory = DocumentBuilderFactory.newInstance();
-               factory.setXIncludeAware(true);
-               factory.setNamespaceAware(true);
-               transformerFactory = new SmartTransformerFactoryImpl();
+
+               // TODO improve configuration and provisioning of DocBook XSL
+               String xslBase = System.getProperty("argeo.docbook.xsl");
+               if (xslBase == null) {
+                       String defaultXslBase = "/opt/docbook-xsl";
+                       if (!Files.exists(Paths.get(defaultXslBase))) {
+                               throw new ServletException("System property argeo.docbook.xsl is not set and default location "
+                                               + defaultXslBase + " does not exist.");
+                       } else {
+                               xslBase = defaultXslBase;
+                       }
+               }
+               String xsl = xslBase + "/html/docbook.xsl";
+
+               documentBuilderFactory = DocumentBuilderFactory.newInstance();
+               documentBuilderFactory.setXIncludeAware(true);
+               documentBuilderFactory.setNamespaceAware(true);
+
+               // We must explicitly use the non-XSLTC transformer, as XSLTC is not working
+               // with DocBook stylesheets
+               transformerFactory = new TransformerFactoryImpl();
+
+               Source xslSource = new StreamSource(xsl);
+               try {
+                       docBoookTemplates = transformerFactory.newTemplates(xslSource);
+                       if (docBoookTemplates == null)
+                               throw new ServletException("Could not instantiate XSL " + xsl);
+               } catch (TransformerConfigurationException e) {
+                       throw new ServletException("Cannot instantiate XSL " + xsl, e);
+               }
        }
 
        public void setRepository(Repository repository) {