1 package org
.argeo
.app
.servlet
.publish
;
3 import java
.io
.IOException
;
4 import java
.io
.InputStream
;
5 import java
.io
.OutputStream
;
6 import java
.io
.StringReader
;
7 import java
.io
.StringWriter
;
10 import java
.net
.URLDecoder
;
11 import java
.nio
.charset
.StandardCharsets
;
12 import java
.nio
.file
.Files
;
13 import java
.nio
.file
.Paths
;
15 import java
.util
.Objects
;
17 import javax
.servlet
.ServletException
;
18 import javax
.servlet
.http
.HttpServlet
;
19 import javax
.servlet
.http
.HttpServletRequest
;
20 import javax
.servlet
.http
.HttpServletResponse
;
21 import javax
.xml
.parsers
.DocumentBuilderFactory
;
22 import javax
.xml
.transform
.Result
;
23 import javax
.xml
.transform
.Source
;
24 import javax
.xml
.transform
.Templates
;
25 import javax
.xml
.transform
.Transformer
;
26 import javax
.xml
.transform
.TransformerConfigurationException
;
27 import javax
.xml
.transform
.TransformerException
;
28 import javax
.xml
.transform
.TransformerFactory
;
29 import javax
.xml
.transform
.URIResolver
;
30 import javax
.xml
.transform
.sax
.SAXResult
;
31 import javax
.xml
.transform
.stream
.StreamResult
;
32 import javax
.xml
.transform
.stream
.StreamSource
;
34 import org
.apache
.fop
.apps
.FOPException
;
35 import org
.apache
.fop
.apps
.Fop
;
36 import org
.apache
.fop
.apps
.FopFactory
;
37 import org
.apache
.fop
.apps
.FopFactoryBuilder
;
38 import org
.apache
.xmlgraphics
.io
.Resource
;
39 import org
.apache
.xmlgraphics
.io
.ResourceResolver
;
40 import org
.argeo
.api
.acr
.Content
;
41 import org
.argeo
.api
.acr
.ContentRepository
;
42 import org
.argeo
.api
.acr
.ContentSession
;
43 import org
.argeo
.api
.acr
.NamespaceUtils
;
44 import org
.argeo
.app
.geo
.GeoUtils
;
45 import org
.argeo
.app
.geo
.GpxUtils
;
46 import org
.argeo
.app
.geo
.acr
.GeoEntityUtils
;
47 import org
.argeo
.cms
.acr
.xml
.XmlNormalizer
;
48 import org
.argeo
.cms
.auth
.RemoteAuthUtils
;
49 import org
.argeo
.cms
.servlet
.ServletHttpRequest
;
50 import org
.argeo
.cms
.util
.LangUtils
;
51 import org
.locationtech
.jts
.geom
.Geometry
;
52 import org
.locationtech
.jts
.geom
.Polygon
;
54 import net
.sf
.saxon
.BasicTransformerFactory
;
57 * A servlet transforming an XML view of the data to either FOP or PDF.
59 public class FopServlet
extends HttpServlet
{
60 private static final long serialVersionUID
= 6906020513498289335L;
62 private final static String PROP_ARGEO_FO_XSL
= "argeo.fo.xsl";
64 private ContentRepository contentRepository
;
66 private DocumentBuilderFactory documentBuilderFactory
;
67 private TransformerFactory transformerFactory
;
68 private Templates foTemplates
;
73 protected void doGet(HttpServletRequest req
, HttpServletResponse resp
) throws ServletException
, IOException
{
74 String servletPath
= req
.getServletPath();
75 String ext
= servletPath
.substring(servletPath
.lastIndexOf('.'));
76 servletPath
= servletPath
.substring(1, servletPath
.lastIndexOf('.'));
77 servletPath
= servletPath
.substring(servletPath
.indexOf('/'), servletPath
.length());
78 String path
= URLDecoder
.decode(servletPath
, StandardCharsets
.UTF_8
);
80 boolean pdf
= ".pdf".equals(ext
);
81 ContentSession session
= RemoteAuthUtils
.doAs(() -> contentRepository
.get(), new ServletHttpRequest(req
));
82 Content content
= session
.get(path
);
85 final boolean DEV
= false;
87 try (InputStream in
= xslUrl
.openStream()) {
88 Source xslSource
= new StreamSource(in
);
89 foTemplates
= transformerFactory
.newTemplates(xslSource
);
90 if (foTemplates
== null)
91 throw new IllegalStateException("Could not instantiate XSL " + xslUrl
);
92 } catch (TransformerConfigurationException
| IOException e
) {
93 throw new IllegalStateException("Cannot instantiate XSL " + xslUrl
, e
);
96 Source xmlInput
= content
.adapt(Source
.class);
97 XmlNormalizer
.print(xmlInput
, 0);
100 Source xmlInput
= content
.adapt(Source
.class);
101 String systemId
= req
.getRequestURL().toString();
102 xmlInput
.setSystemId(systemId
);
104 URIResolver uriResolver
= (href
, base
) -> {
106 URI url
= URI
.create(href
);
107 if (url
.getScheme() != null) {
108 if (url
.getScheme().equals("file")) {
109 InputStream in
= Files
.newInputStream(Paths
.get(URI
.create(url
.toString())));
110 return new StreamSource(in
);
112 if (url
.getScheme().equals("geo2svg")) {
113 int lastDot
= url
.getPath().lastIndexOf('.');
116 String includePath
= path
+ url
.getPath();
117 Content geoContent
= session
.get(includePath
);
118 String geoExt
= includePath
.substring(lastDot
);
119 if (".gpx".equals(geoExt
)) {
120 try (InputStream in
= geoContent
.open(InputStream
.class)) {
121 polygon
= GpxUtils
.parseGpxTrackTo(in
, Polygon
.class);
124 throw new UnsupportedOperationException(geoExt
+ " is not supported");
129 if (url
.getPath().startsWith("/@")) {
130 geoContent
= content
;
131 attrName
= url
.getPath().substring(2);// remove /@
133 throw new IllegalArgumentException("Only direct attributes are currently supported");
135 polygon
= GeoEntityUtils
.getGeometry(geoContent
, NamespaceUtils
.parsePrefixedName(attrName
),
138 try (StringWriter writer
= new StringWriter()) {
139 GeoUtils
.exportToSvg(new Geometry
[] { polygon
}, writer
, 100, 100);
140 StreamSource res
= new StreamSource(new StringReader(writer
.toString()));
145 } catch (IOException e
) {
146 throw new RuntimeException("Cannot process " + href
);
149 String p
= href
.startsWith("/") ? href
: path
+ '/' + href
;
150 p
= URLDecoder
.decode(p
, StandardCharsets
.UTF_8
);
151 Content subContent
= session
.get(p
);
152 return subContent
.adapt(Source
.class);
155 ResourceResolver resourceResolver
= new ResourceResolver() {
158 public Resource
getResource(URI uri
) throws IOException
{
159 String subPath
= uri
.getPath();
160 Content subContent
= session
.get(subPath
);
161 InputStream in
= subContent
.open(InputStream
.class);
162 return new Resource(in
);
166 public OutputStream
getOutputStream(URI uri
) throws IOException
{
173 FopFactoryBuilder builder
= new FopFactoryBuilder(URI
.create(req
.getRequestURL().toString()),
175 FopFactory fopFactory
= builder
.build();
176 // FopFactory fopFactory = FopFactory.newInstance(URI.create(req.getRequestURL().toString()));
177 resp
.setContentType("application/pdf");
178 Fop fop
= fopFactory
.newFop("application/pdf", resp
.getOutputStream());
179 Transformer transformer
= foTemplates
.newTransformer();
180 transformer
.setURIResolver(uriResolver
);
181 Result fopResult
= new SAXResult(fop
.getDefaultHandler());
182 transformer
.transform(xmlInput
, fopResult
);
185 Result xmlOutput
= new StreamResult(resp
.getOutputStream());
186 resp
.setContentType("application/xml");
187 Transformer transformer
= foTemplates
.newTransformer();
188 // transformer = transformerFactory.newTransformer();// identity
189 transformer
.setURIResolver(uriResolver
);
190 transformer
.transform(xmlInput
, xmlOutput
);
192 } catch (FOPException
| IOException
| TransformerException e
) {
193 throw new RuntimeException("Cannot process " + path
, e
);
199 public void init() throws ServletException
{
200 // for (Enumeration<String> it = getServletConfig().getInitParameterNames(); it.hasMoreElements();)
201 // System.out.println(it.nextElement());
202 // for (String str : getServletContext().getResourcePaths("/"))
203 // System.out.println(str);
206 public void start(Map
<String
, Object
> properties
) {
207 documentBuilderFactory
= DocumentBuilderFactory
.newInstance();
208 documentBuilderFactory
.setXIncludeAware(true);
209 documentBuilderFactory
.setNamespaceAware(true);
211 transformerFactory
= new BasicTransformerFactory();
212 // transformerFactory = TransformerFactory.newDefaultInstance();
214 String xslStr
= LangUtils
.get(properties
, PROP_ARGEO_FO_XSL
);
215 Objects
.requireNonNull(xslStr
);
216 xslUrl
= new URL(xslStr
);
217 try (InputStream in
= xslUrl
.openStream()) {
218 Source xslSource
= new StreamSource(in
);
219 foTemplates
= transformerFactory
.newTemplates(xslSource
);
220 if (foTemplates
== null)
221 throw new IllegalStateException("Could not instantiate XSL " + xslUrl
);
224 } catch (TransformerConfigurationException
| IOException e
) {
225 throw new IllegalStateException("Cannot instantiate XSL " + xslUrl
, e
);
229 public void stop(Map
<String
, Object
> properties
) {
233 public void setContentRepository(ContentRepository contentRepository
) {
234 this.contentRepository
= contentRepository
;