1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.mycore.component.fo.common.fo;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.OutputStream;
24 import java.net.URI;
25 import java.net.URL;
26 import java.net.URLConnection;
27 import java.text.MessageFormat;
28 import java.util.Arrays;
29 import java.util.HashMap;
30 import java.util.Locale;
31 import java.util.Map;
32 import java.util.Optional;
33
34 import javax.xml.transform.Result;
35 import javax.xml.transform.Source;
36 import javax.xml.transform.Transformer;
37 import javax.xml.transform.TransformerException;
38 import javax.xml.transform.TransformerFactory;
39 import javax.xml.transform.TransformerFactoryConfigurationError;
40 import javax.xml.transform.sax.SAXResult;
41
42 import org.apache.fop.apps.EnvironmentalProfileFactory;
43 import org.apache.fop.apps.FOPException;
44 import org.apache.fop.apps.FOUserAgent;
45 import org.apache.fop.apps.Fop;
46 import org.apache.fop.apps.FopFactory;
47 import org.apache.fop.apps.FopFactoryBuilder;
48 import org.apache.fop.apps.MimeConstants;
49 import org.apache.fop.configuration.Configuration;
50 import org.apache.fop.configuration.ConfigurationException;
51 import org.apache.fop.configuration.DefaultConfigurationBuilder;
52 import org.apache.logging.log4j.LogManager;
53 import org.apache.logging.log4j.Logger;
54 import org.apache.xmlgraphics.io.Resource;
55 import org.apache.xmlgraphics.io.ResourceResolver;
56 import org.mycore.common.MCRCoreVersion;
57 import org.mycore.common.config.MCRConfiguration2;
58 import org.mycore.common.config.MCRConfigurationDir;
59 import org.mycore.common.content.MCRContent;
60 import org.mycore.common.content.MCRSourceContent;
61 import org.mycore.common.xml.MCRURIResolver;
62 import org.mycore.common.xsl.MCRErrorListener;
63
64
65
66
67
68
69
70
71
72 public class MCRFoFormatterFOP implements MCRFoFormatterInterface {
73
74 private static final Logger LOGGER = LogManager.getLogger();
75
76 private FopFactory fopFactory;
77
78 final ResourceResolver resolver = new ResourceResolver() {
79 public OutputStream getOutputStream(URI uri) throws IOException {
80 URL url = MCRURIResolver.getServletContext().getResource(uri.toString());
81 return url.openConnection().getOutputStream();
82 }
83
84 public Resource getResource(URI uri) throws IOException {
85 MCRContent content;
86 try {
87 content = MCRSourceContent.getInstance(uri.toString());
88 return new Resource(uri.getScheme(), content.getInputStream());
89 } catch (TransformerException e) {
90 LOGGER.error("Error while resolving uri: {}", uri);
91 }
92
93 return null;
94 }
95 };
96
97 public MCRFoFormatterFOP() {
98 FopFactoryBuilder fopFactoryBuilder;
99
100 fopFactoryBuilder = new FopFactoryBuilder(
101 EnvironmentalProfileFactory.createRestrictedIO(URI.create("resource:/"), resolver));
102 final String foCfg = MCRConfiguration2.getString("MCR.LayoutService.FoFormatter.FOP.config").orElse("");
103 if (!foCfg.isEmpty()) {
104 try {
105 URL configResource = MCRConfigurationDir.getConfigResource(foCfg);
106 URLConnection con = configResource.openConnection();
107 final DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
108 final Configuration cfg;
109 try (InputStream is = con.getInputStream();) {
110 cfg = cfgBuilder.build(is);
111 }
112 fopFactoryBuilder.setConfiguration(cfg);
113
114
115
116 Optional<Configuration[]> hyphPat = Optional.ofNullable(cfg.getChildren("hyphenation-pattern"));
117 hyphPat.ifPresent(configurations -> {
118 Map<String, String> hyphPatMap = new HashMap<>();
119 Arrays.stream(configurations).forEach(c -> {
120 try {
121 String lang = c.getAttribute("lang");
122 String file = c.getValue();
123
124 if ((lang != null && !lang.isEmpty()) && (file != null && !file.isEmpty())) {
125 hyphPatMap.put(lang, file);
126 }
127 } catch (Exception e) {
128 }
129 });
130 fopFactoryBuilder.setHyphPatNames(hyphPatMap);
131 });
132
133 } catch (ConfigurationException | IOException e) {
134 LOGGER.error("Exception while loading FOP configuration from {}.", foCfg, e);
135 }
136 }
137 fopFactory = fopFactoryBuilder.build();
138 getTransformerFactory();
139 }
140
141 private static TransformerFactory getTransformerFactory() throws TransformerFactoryConfigurationError {
142 TransformerFactory transformerFactory = TransformerFactory.newInstance();
143 transformerFactory.setURIResolver(MCRURIResolver.instance());
144 transformerFactory.setErrorListener(MCRErrorListener.getInstance());
145 return transformerFactory;
146 }
147
148 @Override
149 public void transform(MCRContent input, OutputStream out) throws TransformerException, IOException {
150 try {
151 final FOUserAgent userAgent = fopFactory.newFOUserAgent();
152 userAgent.setProducer(new MessageFormat("MyCoRe {0} ({1})", Locale.ROOT)
153 .format(new Object[] { MCRCoreVersion.getCompleteVersion(), userAgent.getProducer() }));
154
155 final Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, userAgent, out);
156 final Source src = input.getSource();
157 final Result res = new SAXResult(fop.getDefaultHandler());
158 Transformer transformer = getTransformerFactory().newTransformer();
159 transformer.transform(src, res);
160 } catch (FOPException e) {
161 throw new TransformerException(e);
162 } finally {
163 out.close();
164 }
165 }
166 }