]> git.argeo.org Git - gpl/argeo-suite.git/blob - org.argeo.app.servlet.publish/src/org/argeo/app/servlet/publish/FopServlet.java
Move UX components between packages
[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.net.URI;
7 import java.net.URL;
8 import java.net.URLDecoder;
9 import java.nio.charset.StandardCharsets;
10 import java.nio.file.Files;
11 import java.nio.file.Paths;
12 import java.util.Map;
13
14 import javax.servlet.ServletException;
15 import javax.servlet.http.HttpServlet;
16 import javax.servlet.http.HttpServletRequest;
17 import javax.servlet.http.HttpServletResponse;
18 import javax.xml.parsers.DocumentBuilderFactory;
19 import javax.xml.transform.Result;
20 import javax.xml.transform.Source;
21 import javax.xml.transform.Templates;
22 import javax.xml.transform.Transformer;
23 import javax.xml.transform.TransformerConfigurationException;
24 import javax.xml.transform.TransformerException;
25 import javax.xml.transform.TransformerFactory;
26 import javax.xml.transform.URIResolver;
27 import javax.xml.transform.sax.SAXResult;
28 import javax.xml.transform.stream.StreamResult;
29 import javax.xml.transform.stream.StreamSource;
30
31 import org.apache.fop.apps.FOPException;
32 import org.apache.fop.apps.Fop;
33 import org.apache.fop.apps.FopFactory;
34 import org.apache.fop.apps.FopFactoryBuilder;
35 import org.apache.xalan.processor.TransformerFactoryImpl;
36 import org.apache.xmlgraphics.io.Resource;
37 import org.apache.xmlgraphics.io.ResourceResolver;
38 import org.argeo.api.acr.Content;
39 import org.argeo.api.acr.ContentRepository;
40 import org.argeo.api.acr.ContentSession;
41 import org.argeo.cms.auth.RemoteAuthUtils;
42 import org.argeo.cms.servlet.ServletHttpRequest;
43 import org.argeo.util.LangUtils;
44
45 /**
46 * A servlet transforming an XML view of the data to either FOP or PDF.
47 */
48 public class FopServlet extends HttpServlet {
49 private static final long serialVersionUID = 6906020513498289335L;
50
51 private ContentRepository contentRepository;
52
53 private DocumentBuilderFactory documentBuilderFactory;
54 private TransformerFactory transformerFactory;
55 private Templates foTemplates;
56
57 private String xslUrl;
58
59 @Override
60 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
61 String servletPath = req.getServletPath();
62 String ext = servletPath.substring(servletPath.lastIndexOf('.'));
63 servletPath = servletPath.substring(1, servletPath.lastIndexOf('.'));
64 servletPath = servletPath.substring(servletPath.indexOf('/'), servletPath.length());
65 String path = URLDecoder.decode(servletPath, StandardCharsets.UTF_8);
66
67 boolean pdf = ".pdf".equals(ext);
68 ContentSession session = RemoteAuthUtils.doAs(() -> contentRepository.get(), new ServletHttpRequest(req));
69 Content content = session.get(path);
70 Source xmlInput = content.adapt(Source.class);
71 xmlInput.setSystemId(req.getRequestURI());
72
73 // dev only
74 try (InputStream in = new URL(xslUrl).openStream()) {
75 Source xslSource = new StreamSource(in);
76 foTemplates = transformerFactory.newTemplates(xslSource);
77 if (foTemplates == null)
78 throw new IllegalStateException("Could not instantiate XSL " + xslUrl);
79 } catch (TransformerConfigurationException | IOException e) {
80 throw new IllegalStateException("Cannot instantiate XSL " + xslUrl, e);
81 }
82
83 URIResolver uriResolver = (href, base) -> {
84 try {
85 URL url = new URL(href);
86 if (url.getProtocol().equals("file")) {
87 InputStream in = Files.newInputStream(Paths.get(URI.create(url.toString())));
88 return new StreamSource(in);
89 }
90 } catch (IOException e) {
91 // silent
92 }
93 Content subContent = session.get(href);
94 return subContent.adapt(Source.class);
95 };
96
97 ResourceResolver resourceResolver = new ResourceResolver() {
98
99 @Override
100 public Resource getResource(URI uri) throws IOException {
101 String subPath = uri.getPath();
102 Content subContent = session.get(subPath);
103 InputStream in = subContent.open(InputStream.class);
104 return new Resource(in);
105 }
106
107 @Override
108 public OutputStream getOutputStream(URI uri) throws IOException {
109 return null;
110 }
111 };
112
113 try {
114 if (pdf) {
115 FopFactoryBuilder builder = new FopFactoryBuilder(URI.create(req.getRequestURL().toString()),
116 resourceResolver);
117 FopFactory fopFactory = builder.build();
118 // FopFactory fopFactory = FopFactory.newInstance(URI.create(req.getRequestURL().toString()));
119 resp.setContentType("application/pdf");
120 Fop fop = fopFactory.newFop("application/pdf", resp.getOutputStream());
121 Transformer transformer = foTemplates.newTransformer();
122 transformer.setURIResolver(uriResolver);
123 Result fopResult = new SAXResult(fop.getDefaultHandler());
124 transformer.transform(xmlInput, fopResult);
125
126 } else {
127 Result xmlOutput = new StreamResult(resp.getOutputStream());
128 resp.setContentType("application/xml");
129 Transformer transformer = foTemplates.newTransformer();
130 // transformer = transformerFactory.newTransformer();// identity
131 transformer.setURIResolver(uriResolver);
132 transformer.transform(xmlInput, xmlOutput);
133 }
134 } catch (FOPException | IOException | TransformerException e) {
135 throw new RuntimeException("Cannot process " + path, e);
136 }
137
138 }
139
140 public void start(Map<String, Object> properties) {
141 documentBuilderFactory = DocumentBuilderFactory.newInstance();
142 documentBuilderFactory.setXIncludeAware(true);
143 documentBuilderFactory.setNamespaceAware(true);
144
145 // We must explicitly use the non-XSLTC transformer, as XSLTC is not working
146 // with DocBook stylesheets
147 transformerFactory = new TransformerFactoryImpl();
148 // transformerFactory = TransformerFactory.newDefaultInstance();
149
150 xslUrl = LangUtils.get(properties, "argeo.fo.xsl");
151 try (InputStream in = new URL(xslUrl).openStream()) {
152 Source xslSource = new StreamSource(in);
153 foTemplates = transformerFactory.newTemplates(xslSource);
154 if (foTemplates == null)
155 throw new IllegalStateException("Could not instantiate XSL " + xslUrl);
156 } catch (TransformerConfigurationException | IOException e) {
157 throw new IllegalStateException("Cannot instantiate XSL " + xslUrl, e);
158 }
159 }
160
161 public void stop(Map<String, Object> properties) {
162
163 }
164
165 public void setContentRepository(ContentRepository contentRepository) {
166 this.contentRepository = contentRepository;
167 }
168
169 }