X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=org.argeo.app.servlet.publish%2Fsrc%2Forg%2Fargeo%2Fapp%2Fservlet%2Fpublish%2FFopServlet.java;h=a4e07ba90a7f27a52c0391f3ffa8241588a129d7;hb=b06a0f5f77d4f126c8e38625882cd68a827dcd70;hp=bba0d3052238401879ed65df62c61370c8ae3064;hpb=8e76163658cc6275b0ca4206f6ea4b3eee09d787;p=gpl%2Fargeo-suite.git diff --git a/org.argeo.app.servlet.publish/src/org/argeo/app/servlet/publish/FopServlet.java b/org.argeo.app.servlet.publish/src/org/argeo/app/servlet/publish/FopServlet.java index bba0d30..a4e07ba 100644 --- a/org.argeo.app.servlet.publish/src/org/argeo/app/servlet/publish/FopServlet.java +++ b/org.argeo.app.servlet.publish/src/org/argeo/app/servlet/publish/FopServlet.java @@ -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 it = getServletConfig().getInitParameterNames(); it.hasMoreElements();) +// System.out.println(it.nextElement()); +// for (String str : getServletContext().getResourcePaths("/")) +// System.out.println(str); + } + public void start(Map 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); }