]> git.argeo.org Git - gpl/argeo-suite.git/blob - org.argeo.app.servlet.publish/src/org/argeo/app/servlet/publish/FopServlet.java
Start improving People UI
[gpl/argeo-suite.git] / org.argeo.app.servlet.publish / src / org / argeo / app / servlet / publish / FopServlet.java
1 package org.argeo.app.servlet.publish;
2
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;
8 import java.net.URI;
9 import java.net.URL;
10 import java.net.URLDecoder;
11 import java.nio.charset.StandardCharsets;
12 import java.nio.file.Files;
13 import java.nio.file.Paths;
14 import java.util.Map;
15 import java.util.Objects;
16
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;
33
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.xalan.processor.TransformerFactoryImpl;
39 import org.apache.xmlgraphics.io.Resource;
40 import org.apache.xmlgraphics.io.ResourceResolver;
41 import org.argeo.api.acr.Content;
42 import org.argeo.api.acr.ContentRepository;
43 import org.argeo.api.acr.ContentSession;
44 import org.argeo.app.geo.GeoUtils;
45 import org.argeo.app.geo.GpxUtils;
46 import org.argeo.cms.auth.RemoteAuthUtils;
47 import org.argeo.cms.servlet.ServletHttpRequest;
48 import org.argeo.util.LangUtils;
49 import org.geotools.data.collection.ListFeatureCollection;
50 import org.geotools.data.simple.SimpleFeatureCollection;
51 import org.opengis.feature.simple.SimpleFeature;
52
53 /**
54 * A servlet transforming an XML view of the data to either FOP or PDF.
55 */
56 public class FopServlet extends HttpServlet {
57 private static final long serialVersionUID = 6906020513498289335L;
58
59 private final static String PROP_ARGEO_FO_XSL = "argeo.fo.xsl";
60
61 private ContentRepository contentRepository;
62
63 private DocumentBuilderFactory documentBuilderFactory;
64 private TransformerFactory transformerFactory;
65 private Templates foTemplates;
66
67 private URL xslUrl;
68
69 @Override
70 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
71 String servletPath = req.getServletPath();
72 String ext = servletPath.substring(servletPath.lastIndexOf('.'));
73 servletPath = servletPath.substring(1, servletPath.lastIndexOf('.'));
74 servletPath = servletPath.substring(servletPath.indexOf('/'), servletPath.length());
75 String path = URLDecoder.decode(servletPath, StandardCharsets.UTF_8);
76
77 boolean pdf = ".pdf".equals(ext);
78 ContentSession session = RemoteAuthUtils.doAs(() -> contentRepository.get(), new ServletHttpRequest(req));
79 Content content = session.get(path);
80 Source xmlInput = content.adapt(Source.class);
81 String systemId = req.getRequestURL().toString();
82 xmlInput.setSystemId(systemId);
83
84 // dev only
85 final boolean DEV = true;
86 if (DEV) {
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);
94 }
95 }
96
97 URIResolver uriResolver = (href, base) -> {
98 try {
99 URI url = URI.create(href);
100 if (url.getScheme() != null) {
101 if (url.getScheme().equals("file")) {
102 InputStream in = Files.newInputStream(Paths.get(URI.create(url.toString())));
103 return new StreamSource(in);
104 }
105 if (url.getScheme().equals("geo2svg")) {
106 String includePath = path + url.getPath();
107 String geoExt = includePath.substring(includePath.lastIndexOf('.'));
108 Content geoContent = session.get(includePath);
109 if (".gpx".equals(geoExt)) {
110 try (InputStream in = geoContent.open(InputStream.class)) {
111 SimpleFeature field = GpxUtils.parseGpxToPolygon(in);
112 SimpleFeatureCollection features = new ListFeatureCollection(field.getType(), field);
113 try (StringWriter writer = new StringWriter()) {
114 GeoUtils.exportToSvg(features, writer, 100, 100);
115 StreamSource res = new StreamSource(new StringReader(writer.toString()));
116 return res;
117 }
118 }
119 } else {
120 throw new UnsupportedOperationException(geoExt + " is not supported");
121 }
122 }
123 }
124 } catch (IOException e) {
125 throw new RuntimeException("Cannot process " + href);
126 }
127
128 String p = href.startsWith("/")?href:path+'/'+href;
129 Content subContent = session.get(p);
130 return subContent.adapt(Source.class);
131 };
132
133 ResourceResolver resourceResolver = new ResourceResolver() {
134
135 @Override
136 public Resource getResource(URI uri) throws IOException {
137 String subPath = uri.getPath();
138 Content subContent = session.get(subPath);
139 InputStream in = subContent.open(InputStream.class);
140 return new Resource(in);
141 }
142
143 @Override
144 public OutputStream getOutputStream(URI uri) throws IOException {
145 return null;
146 }
147 };
148
149 try {
150 if (pdf) {
151 FopFactoryBuilder builder = new FopFactoryBuilder(URI.create(req.getRequestURL().toString()),
152 resourceResolver);
153 FopFactory fopFactory = builder.build();
154 // FopFactory fopFactory = FopFactory.newInstance(URI.create(req.getRequestURL().toString()));
155 resp.setContentType("application/pdf");
156 Fop fop = fopFactory.newFop("application/pdf", resp.getOutputStream());
157 Transformer transformer = foTemplates.newTransformer();
158 transformer.setURIResolver(uriResolver);
159 Result fopResult = new SAXResult(fop.getDefaultHandler());
160 transformer.transform(xmlInput, fopResult);
161
162 } else {
163 Result xmlOutput = new StreamResult(resp.getOutputStream());
164 resp.setContentType("application/xml");
165 Transformer transformer = foTemplates.newTransformer();
166 // transformer = transformerFactory.newTransformer();// identity
167 transformer.setURIResolver(uriResolver);
168 transformer.transform(xmlInput, xmlOutput);
169 }
170 } catch (FOPException | IOException | TransformerException e) {
171 throw new RuntimeException("Cannot process " + path, e);
172 }
173
174 }
175
176 @Override
177 public void init() throws ServletException {
178 // for (Enumeration<String> it = getServletConfig().getInitParameterNames(); it.hasMoreElements();)
179 // System.out.println(it.nextElement());
180 // for (String str : getServletContext().getResourcePaths("/"))
181 // System.out.println(str);
182 }
183
184 public void start(Map<String, Object> properties) {
185 documentBuilderFactory = DocumentBuilderFactory.newInstance();
186 documentBuilderFactory.setXIncludeAware(true);
187 documentBuilderFactory.setNamespaceAware(true);
188
189 // We must explicitly use the non-XSLTC transformer, as XSLTC is not working
190 // with DocBook stylesheets
191 transformerFactory = new TransformerFactoryImpl();
192 // transformerFactory = TransformerFactory.newDefaultInstance();
193 try {
194 String xslStr = LangUtils.get(properties, PROP_ARGEO_FO_XSL);
195 Objects.requireNonNull(xslStr);
196 xslUrl = new URL(xslStr);
197 try (InputStream in = xslUrl.openStream()) {
198 Source xslSource = new StreamSource(in);
199 foTemplates = transformerFactory.newTemplates(xslSource);
200 if (foTemplates == null)
201 throw new IllegalStateException("Could not instantiate XSL " + xslUrl);
202 }
203
204 } catch (TransformerConfigurationException | IOException e) {
205 throw new IllegalStateException("Cannot instantiate XSL " + xslUrl, e);
206 }
207 }
208
209 public void stop(Map<String, Object> properties) {
210
211 }
212
213 public void setContentRepository(ContentRepository contentRepository) {
214 this.contentRepository = contentRepository;
215 }
216
217 }