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