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