Disable development mode in FOP servlet
[gpl/argeo-suite.git] / org.argeo.app.servlet.publish / src / org / argeo / app / servlet / publish / FopServlet.java
index bba0d3052238401879ed65df62c61370c8ae3064..a4e07ba90a7f27a52c0391f3ffa8241588a129d7 100644 (file)
@@ -3,6 +3,8 @@ package org.argeo.app.servlet.publish;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.io.StringReader;
+import java.io.StringWriter;
 import java.net.URI;
 import java.net.URL;
 import java.net.URLDecoder;
@@ -10,6 +12,7 @@ import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Paths;
 import java.util.Map;
+import java.util.Objects;
 
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
@@ -32,15 +35,23 @@ import org.apache.fop.apps.FOPException;
 import org.apache.fop.apps.Fop;
 import org.apache.fop.apps.FopFactory;
 import org.apache.fop.apps.FopFactoryBuilder;
-import org.apache.xalan.processor.TransformerFactoryImpl;
 import org.apache.xmlgraphics.io.Resource;
 import org.apache.xmlgraphics.io.ResourceResolver;
 import org.argeo.api.acr.Content;
 import org.argeo.api.acr.ContentRepository;
 import org.argeo.api.acr.ContentSession;
+import org.argeo.api.acr.NamespaceUtils;
+import org.argeo.app.geo.GeoUtils;
+import org.argeo.app.geo.GpxUtils;
+import org.argeo.app.geo.acr.GeoEntityUtils;
+import org.argeo.cms.acr.xml.XmlNormalizer;
 import org.argeo.cms.auth.RemoteAuthUtils;
 import org.argeo.cms.servlet.ServletHttpRequest;
-import org.argeo.util.LangUtils;
+import org.argeo.cms.util.LangUtils;
+import org.locationtech.jts.geom.Geometry;
+import org.locationtech.jts.geom.Polygon;
+
+import net.sf.saxon.BasicTransformerFactory;
 
 /**
  * A servlet transforming an XML view of the data to either FOP or PDF.
@@ -48,13 +59,15 @@ import org.argeo.util.LangUtils;
 public class FopServlet extends HttpServlet {
        private static final long serialVersionUID = 6906020513498289335L;
 
+       private final static String PROP_ARGEO_FO_XSL = "argeo.fo.xsl";
+
        private ContentRepository contentRepository;
 
        private DocumentBuilderFactory documentBuilderFactory;
        private TransformerFactory transformerFactory;
        private Templates foTemplates;
 
-       private String xslUrl;
+       private URL xslUrl;
 
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
@@ -67,30 +80,75 @@ public class FopServlet extends HttpServlet {
                boolean pdf = ".pdf".equals(ext);
                ContentSession session = RemoteAuthUtils.doAs(() -> contentRepository.get(), new ServletHttpRequest(req));
                Content content = session.get(path);
-               Source xmlInput = content.adapt(Source.class);
-               xmlInput.setSystemId(req.getRequestURI());
 
                // dev only
-               try (InputStream in = new URL(xslUrl).openStream()) {
-                       Source xslSource = new StreamSource(in);
-                       foTemplates = transformerFactory.newTemplates(xslSource);
-                       if (foTemplates == null)
-                               throw new IllegalStateException("Could not instantiate XSL " + xslUrl);
-               } catch (TransformerConfigurationException | IOException e) {
-                       throw new IllegalStateException("Cannot instantiate XSL " + xslUrl, e);
+               final boolean DEV = false;
+               if (DEV) {
+                       try (InputStream in = xslUrl.openStream()) {
+                               Source xslSource = new StreamSource(in);
+                               foTemplates = transformerFactory.newTemplates(xslSource);
+                               if (foTemplates == null)
+                                       throw new IllegalStateException("Could not instantiate XSL " + xslUrl);
+                       } catch (TransformerConfigurationException | IOException e) {
+                               throw new IllegalStateException("Cannot instantiate XSL " + xslUrl, e);
+                       }
+
+                       Source xmlInput = content.adapt(Source.class);
+                       XmlNormalizer.print(xmlInput, 0);
                }
 
+               Source xmlInput = content.adapt(Source.class);
+               String systemId = req.getRequestURL().toString();
+               xmlInput.setSystemId(systemId);
+
                URIResolver uriResolver = (href, base) -> {
                        try {
-                               URL url = new URL(href);
-                               if (url.getProtocol().equals("file")) {
-                                       InputStream in = Files.newInputStream(Paths.get(URI.create(url.toString())));
-                                       return new StreamSource(in);
+                               URI url = URI.create(href);
+                               if (url.getScheme() != null) {
+                                       if (url.getScheme().equals("file")) {
+                                               InputStream in = Files.newInputStream(Paths.get(URI.create(url.toString())));
+                                               return new StreamSource(in);
+                                       }
+                                       if (url.getScheme().equals("geo2svg")) {
+                                               int lastDot = url.getPath().lastIndexOf('.');
+                                               Polygon polygon;
+                                               if (lastDot > 0) {
+                                                       String includePath = path + url.getPath();
+                                                       Content geoContent = session.get(includePath);
+                                                       String geoExt = includePath.substring(lastDot);
+                                                       if (".gpx".equals(geoExt)) {
+                                                               try (InputStream in = geoContent.open(InputStream.class)) {
+                                                                       polygon = GpxUtils.parseGpxTrackTo(in, Polygon.class);
+                                                               }
+                                                       } else {
+                                                               throw new UnsupportedOperationException(geoExt + " is not supported");
+                                                       }
+                                               } else {
+                                                       Content geoContent;
+                                                       String attrName;
+                                                       if (url.getPath().startsWith("/@")) {
+                                                               geoContent = content;
+                                                               attrName = url.getPath().substring(2);// remove /@
+                                                       } else {
+                                                               throw new IllegalArgumentException("Only direct attributes are currently supported");
+                                                       }
+                                                       polygon = GeoEntityUtils.getGeometry(geoContent, NamespaceUtils.parsePrefixedName(attrName),
+                                                                       Polygon.class);
+                                               }
+                                               try (StringWriter writer = new StringWriter()) {
+                                                       GeoUtils.exportToSvg(new Geometry[] { polygon }, writer, 100, 100);
+                                                       StreamSource res = new StreamSource(new StringReader(writer.toString()));
+                                                       return res;
+                                               }
+                                       }
                                }
                        } catch (IOException e) {
-                               // silent
+                               throw new RuntimeException("Cannot process " + href);
                        }
-                       Content subContent = session.get(href);
+
+                       String p = href.startsWith("/") ? href : path + '/' + href;
+                       p = URLDecoder.decode(p, StandardCharsets.UTF_8);
+                       Content subContent = session.get(p);
                        return subContent.adapt(Source.class);
                };
 
@@ -137,22 +195,32 @@ public class FopServlet extends HttpServlet {
 
        }
 
+       @Override
+       public void init() throws ServletException {
+//             for (Enumeration<String> it = getServletConfig().getInitParameterNames(); it.hasMoreElements();)
+//                     System.out.println(it.nextElement());
+//             for (String str : getServletContext().getResourcePaths("/"))
+//                     System.out.println(str);
+       }
+
        public void start(Map<String, Object> properties) {
                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();
+               transformerFactory = new BasicTransformerFactory();
 //             transformerFactory = TransformerFactory.newDefaultInstance();
+               try {
+                       String xslStr = LangUtils.get(properties, PROP_ARGEO_FO_XSL);
+                       Objects.requireNonNull(xslStr);
+                       xslUrl = new URL(xslStr);
+                       try (InputStream in = xslUrl.openStream()) {
+                               Source xslSource = new StreamSource(in);
+                               foTemplates = transformerFactory.newTemplates(xslSource);
+                               if (foTemplates == null)
+                                       throw new IllegalStateException("Could not instantiate XSL " + xslUrl);
+                       }
 
-               xslUrl = LangUtils.get(properties, "argeo.fo.xsl");
-               try (InputStream in = new URL(xslUrl).openStream()) {
-                       Source xslSource = new StreamSource(in);
-                       foTemplates = transformerFactory.newTemplates(xslSource);
-                       if (foTemplates == null)
-                               throw new IllegalStateException("Could not instantiate XSL " + xslUrl);
                } catch (TransformerConfigurationException | IOException e) {
                        throw new IllegalStateException("Cannot instantiate XSL " + xslUrl, e);
                }