1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 /* $Id: ExampleEvents.java 1356646 2012-07-03 09:46:41Z mehdi $ */
19 
20 package embedding.events;
21 
22 import java.io.BufferedOutputStream;
23 import java.io.File;
24 import java.io.FileNotFoundException;
25 import java.io.FileOutputStream;
26 import java.io.IOException;
27 import java.io.OutputStream;
28 import java.net.URL;
29 
30 import javax.xml.transform.Result;
31 import javax.xml.transform.Source;
32 import javax.xml.transform.Transformer;
33 import javax.xml.transform.TransformerException;
34 import javax.xml.transform.TransformerFactory;
35 import javax.xml.transform.sax.SAXResult;
36 import javax.xml.transform.stream.StreamSource;
37 
38 import org.xml.sax.SAXException;
39 
40 import org.apache.commons.io.IOUtils;
41 
42 import org.apache.fop.apps.FOPException;
43 import org.apache.fop.apps.FOUserAgent;
44 import org.apache.fop.apps.Fop;
45 import org.apache.fop.apps.FopFactory;
46 import org.apache.fop.apps.MimeConstants;
47 import org.apache.fop.events.Event;
48 import org.apache.fop.events.EventFormatter;
49 import org.apache.fop.events.EventListener;
50 import org.apache.fop.events.model.EventSeverity;
51 
52 /**
53  * This class demonstrates how to register an event listener with FOP so you can customize
54  * FOP's error behaviour.
55  */
56 public class ExampleEvents {
57 
58     // configure fopFactory as desired
59     private final FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());
60 
61     /**
62      * Converts an FO file to a PDF file using FOP
63      * @param fo the FO file
64      * @param pdf the target PDF file
65      * @throws IOException In case of an I/O problem
66      * @throws FOPException In case of a FOP problem
67      * @throws TransformerException In case of a problem with XSLT
68      */
convertFO2PDF(URL fo, File pdf)69     public void convertFO2PDF(URL fo, File pdf)
70             throws IOException, FOPException, TransformerException {
71 
72         OutputStream out = null;
73 
74         try {
75             //Create the user agent for this processing run
76             FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
77 
78             //Adding a simple logging listener that writes to stdout and stderr
79             foUserAgent.getEventBroadcaster().addEventListener(new SysOutEventListener());
80 
81             // Add your own event listener
82             foUserAgent.getEventBroadcaster().addEventListener(new MyEventListener());
83 
84             // configure foUserAgent further as desired
85 
86             // Setup output stream.  Note: Using BufferedOutputStream
87             // for performance reasons (helpful with FileOutputStreams).
88             out = new FileOutputStream(pdf);
89             out = new BufferedOutputStream(out);
90 
91             // Construct fop with desired output format
92             Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);
93 
94             // Setup JAXP using identity transformer
95             TransformerFactory factory = TransformerFactory.newInstance();
96             Transformer transformer = factory.newTransformer(); // identity transformer
97 
98             // Setup input stream
99             Source src = new StreamSource(fo.toExternalForm());
100 
101             // Resulting SAX events (the generated FO) must be piped through to FOP
102             Result res = new SAXResult(fop.getDefaultHandler());
103 
104             // Start XSLT transformation and FOP processing
105             transformer.transform(src, res);
106 
107         } finally {
108             IOUtils.closeQuietly(out);
109         }
110     }
111 
112     private static class MyEventListener implements EventListener {
113 
processEvent(Event event)114         public void processEvent(Event event) {
115             if ("org.apache.fop.ResourceEventProducer.imageNotFound"
116                     .equals(event.getEventID())) {
117 
118                 //Get the FileNotFoundException that's part of the event's parameters
119                 FileNotFoundException fnfe = (FileNotFoundException)event.getParam("fnfe");
120 
121                 System.out.println("---=== imageNotFound Event for " + event.getParam("uri")
122                         + "!!! ===---");
123                 //Stop processing when an image could not be found. Otherwise, FOP would just
124                 //continue without the image!
125 
126                 System.out.println("Throwing a RuntimeException...");
127                 throw new RuntimeException(EventFormatter.format(event), fnfe);
128             } else {
129                 //ignore all other events
130             }
131         }
132 
133     }
134 
135     /** A simple event listener that writes the events to stdout and sterr. */
136     private static class SysOutEventListener implements EventListener {
137 
138         /** {@inheritDoc} */
processEvent(Event event)139         public void processEvent(Event event) {
140             String msg = EventFormatter.format(event);
141             EventSeverity severity = event.getSeverity();
142             if (severity == EventSeverity.INFO) {
143                 System.out.println("[INFO ] " + msg);
144             } else if (severity == EventSeverity.WARN) {
145                 System.out.println("[WARN ] " + msg);
146             } else if (severity == EventSeverity.ERROR) {
147                 System.err.println("[ERROR] " + msg);
148             } else if (severity == EventSeverity.FATAL) {
149                 System.err.println("[FATAL] " + msg);
150             } else {
151                 assert false;
152             }
153         }
154     }
155 
156 
157     /**
158      * This method extracts the original exception from some exception. The exception
159      * might be nested multiple levels deep.
160      * @param t the Throwable to inspect
161      * @return the original Throwable or the method parameter t if there are no nested Throwables.
162      */
getOriginalThrowable(Throwable t)163     private static Throwable getOriginalThrowable(Throwable t) {
164         if (t instanceof SAXException) {
165             SAXException saxe = (SAXException)t;
166             if (saxe.getException() != null) {
167                 return getOriginalThrowable(saxe.getException());
168             } else {
169                 return saxe;
170             }
171         } else {
172             if (t.getCause() != null) {
173                 return getOriginalThrowable(t.getCause());
174             } else {
175                 return t;
176             }
177         }
178     }
179 
180     /**
181      * Main method.
182      * @param args command-line arguments
183      */
main(String[] args)184     public static void main(String[] args) {
185         try {
186             System.out.println("FOP ExampleEvents\n");
187             System.out.println("Preparing...");
188 
189             //Setup directories
190             File baseDir = new File(".");
191             File outDir = new File(baseDir, "out");
192             outDir.mkdirs();
193 
194             //Setup input and output files
195             URL fo = ExampleEvents.class.getResource("missing-image.fo");
196             File pdffile = new File(outDir, "out.pdf");
197 
198             System.out.println("Input: XSL-FO (" + fo.toExternalForm() + ")");
199             System.out.println("Output: PDF (" + pdffile + ")");
200             System.out.println();
201             System.out.println("Transforming...");
202 
203             ExampleEvents app = new ExampleEvents();
204 
205             try {
206                 app.convertFO2PDF(fo, pdffile);
207             } catch (TransformerException te) {
208                 //Note: We don't get the original exception here!
209                 //FOP needs to embed the exception in a SAXException and the TraX transformer
210                 //again wraps the SAXException in a TransformerException. Even our own
211                 //RuntimeException just wraps the original FileNotFoundException.
212                 //So we need to unpack to get the original exception (about three layers deep).
213                 Throwable originalThrowable = getOriginalThrowable(te);
214                 originalThrowable.printStackTrace(System.err);
215                 System.out.println("Aborted!");
216                 System.exit(-1);
217             }
218 
219             System.out.println("Success!");
220         } catch (Exception e) {
221             //Some other error (shouldn't happen in this example)
222             e.printStackTrace(System.err);
223             System.exit(-1);
224         }
225     }
226 
227 }
228