KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > fop > apps > Driver


1 /*
2  * $Id: Driver.java,v 1.36.2.10 2003/02/25 10:18:32 jeremias Exp $
3  * ============================================================================
4  * The Apache Software License, Version 1.1
5  * ============================================================================
6  *
7  * Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without modifica-
10  * tion, are permitted provided that the following conditions are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * 3. The end-user documentation included with the redistribution, if any, must
20  * include the following acknowledgment: "This product includes software
21  * developed by the Apache Software Foundation (http://www.apache.org/)."
22  * Alternately, this acknowledgment may appear in the software itself, if
23  * and wherever such third-party acknowledgments normally appear.
24  *
25  * 4. The names "FOP" and "Apache Software Foundation" must not be used to
26  * endorse or promote products derived from this software without prior
27  * written permission. For written permission, please contact
28  * apache@apache.org.
29  *
30  * 5. Products derived from this software may not be called "Apache", nor may
31  * "Apache" appear in their name, without prior written permission of the
32  * Apache Software Foundation.
33  *
34  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
35  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
36  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
37  * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
38  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
39  * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
40  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
41  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
42  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
43  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44  * ============================================================================
45  *
46  * This software consists of voluntary contributions made by many individuals
47  * on behalf of the Apache Software Foundation and was originally created by
48  * James Tauber <jtauber@jtauber.com>. For more information on the Apache
49  * Software Foundation, please see <http://www.apache.org/>.
50  */

51 package org.apache.fop.apps;
52
53 // FOP
54
import org.apache.fop.configuration.ConfigurationReader;
55 import org.apache.fop.fo.ElementMapping;
56 import org.apache.fop.fo.FOTreeBuilder;
57 import org.apache.fop.render.Renderer;
58 import org.apache.fop.tools.DocumentInputSource;
59 import org.apache.fop.tools.DocumentReader;
60
61 // Avalon
62
import org.apache.avalon.framework.logger.ConsoleLogger;
63 import org.apache.avalon.framework.logger.Logger;
64
65 // DOM
66
import org.w3c.dom.Document JavaDoc;
67
68 // SAX
69
import org.xml.sax.ContentHandler JavaDoc;
70 import org.xml.sax.InputSource JavaDoc;
71 import org.xml.sax.SAXException JavaDoc;
72 import org.xml.sax.XMLReader JavaDoc;
73
74 // Java
75
import java.io.BufferedReader JavaDoc;
76 import java.io.InputStreamReader JavaDoc;
77 import java.io.InputStream JavaDoc;
78 import java.io.IOException JavaDoc;
79 import java.io.OutputStream JavaDoc;
80 import java.util.Enumeration JavaDoc;
81 import java.util.HashMap JavaDoc;
82 import java.util.Vector JavaDoc;
83
84 /**
85  * Primary class that drives overall FOP process.
86  * <P>
87  * The simplest way to use this is to instantiate it with the
88  * InputSource and OutputStream, then set the renderer desired, and
89  * calling run();
90  * <P>
91  * Here is an example use of Driver which outputs PDF:
92  *
93  * <PRE>
94  * Driver driver = new Driver(new InputSource (args[0]),
95  * new FileOutputStream(args[1]));
96  * driver.setRenderer(RENDER_PDF);
97  * driver.run();
98  * </PRE>
99  * If neccessary, calling classes can call into the lower level
100  * methods to setup and render. Methods can be called to set the
101  * Renderer to use, the (possibly multiple) ElementMapping(s) to use
102  * and the OutputStream to use to output the results of the rendering
103  * (where applicable). In the case of the Renderer and
104  * ElementMapping(s), the Driver may be supplied either with the
105  * object itself, or the name of the class, in which case Driver will
106  * instantiate the class itself. The advantage of the latter is it
107  * enables runtime determination of Renderer and ElementMapping(s).
108  * <P>
109  * Once the Driver is set up, the render method is called. Depending
110  * on whether DOM or SAX is being used, the invocation of the method
111  * is either render(Document) or render(Parser, InputSource)
112  * respectively.
113  * <P>
114  * A third possibility is to call getContentHandler() and firing
115  * the SAX events yourself.
116  * <P>
117  * Here is an example use of Driver which outputs to AWT:
118  *
119  * <PRE>
120  * Driver driver = new Driver();
121  * driver.setRenderer(new org.apache.fop.render.awt.AWTRenderer(translator));
122  * driver.render(parser, fileInputSource(args[0]));
123  * </PRE> */

124 public class Driver {
125
126     /**
127      * Render to PDF. OutputStream must be set
128      */

129     public static final int RENDER_PDF = 1;
130
131     /**
132      * Render to a GUI window. No OutputStream neccessary
133      */

134     public static final int RENDER_AWT = 2;
135
136     /**
137      * Render to MIF. OutputStream must be set
138      */

139     public static final int RENDER_MIF = 3;
140
141     /**
142      * Render to XML. OutputStream must be set
143      */

144     public static final int RENDER_XML = 4;
145
146     /**
147      * Render to PRINT. No OutputStream neccessary
148      */

149     public static final int RENDER_PRINT = 5;
150
151     /**
152      * Render to PCL. OutputStream must be set
153      */

154     public static final int RENDER_PCL = 6;
155
156     /**
157      * Render to Postscript. OutputStream must be set
158      */

159     public static final int RENDER_PS = 7;
160
161     /**
162      * Render to Text. OutputStream must be set
163      */

164     public static final int RENDER_TXT = 8;
165
166     /**
167      * Render to SVG. OutputStream must be set
168      */

169     public static final int RENDER_SVG = 9;
170
171     /**
172      * the FO tree builder
173      */

174     private FOTreeBuilder _treeBuilder;
175
176     /**
177      * the renderer to use to output the area tree
178      */

179     private Renderer _renderer;
180
181     /**
182      * the source of the FO file
183      */

184     private InputSource _source;
185
186     /**
187      * the stream to use to output the results of the renderer
188      */

189     private OutputStream JavaDoc _stream;
190
191     /**
192      * The XML parser to use when building the FO tree
193      */

194     private XMLReader JavaDoc _reader;
195
196     /**
197      * If true, full error stacks are reported
198      */

199     private boolean _errorDump = false;
200
201     /**
202      * the system resources that FOP will use
203      */

204     private Logger log;
205
206     public static final String JavaDoc getParserClassName() {
207         try {
208             return javax.xml.parsers.SAXParserFactory.newInstance().newSAXParser().getXMLReader().getClass().getName();
209         } catch (javax.xml.parsers.ParserConfigurationException JavaDoc e) {
210             return null;
211         } catch (org.xml.sax.SAXException JavaDoc e) {
212             return null;
213         }
214     }
215
216     /**
217      * create a new Driver
218      */

219     public Driver() {
220         _stream = null;
221         _treeBuilder = new FOTreeBuilder();
222         setupDefaultMappings();
223     }
224
225     public Driver(InputSource source, OutputStream JavaDoc stream) {
226         this();
227         _source = source;
228         _stream = stream;
229     }
230
231     public void setLogger(Logger logger) {
232         log = logger;
233     }
234
235     private Logger getLogger() {
236         if(log == null) {
237             log = new ConsoleLogger(ConsoleLogger.LEVEL_INFO);
238             log.error("Logger not set");
239         }
240
241         return log;
242     }
243
244     /**
245      * Resets the Driver so it can be reused. Property and element
246      * mappings are reset to defaults.
247      * The output stream is cleared. The renderer is cleared.
248      */

249     public synchronized void reset() {
250         _source = null;
251         _stream = null;
252         _reader = null;
253         _treeBuilder.reset();
254     }
255
256     /**
257      * Returns the results of the last rendering process. Information includes
258      * the total number of pages generated and the number of pages per
259      * page-sequence.
260      */

261     public FormattingResults getResults() {
262         try {
263             return _treeBuilder.getStreamRenderer().getResults();
264         } catch (NullPointerException JavaDoc e) {
265             return null;
266         }
267     }
268
269     public boolean hasData() {
270         return (_treeBuilder.hasData());
271     }
272
273     /**
274      * Set the error dump option
275      * @param dump if true, full stacks will be reported to the error log
276      */

277     public void setErrorDump(boolean dump) {
278         _errorDump = dump;
279     }
280
281     /**
282      * Set the OutputStream to use to output the result of the Renderer
283      * (if applicable)
284      * @param stream the stream to output the result of rendering to
285      *
286      */

287     public void setOutputStream(OutputStream JavaDoc stream) {
288         _stream = stream;
289     }
290
291     /**
292      * Set the source for the FO document. This can be a normal SAX
293      * InputSource, or an DocumentInputSource containing a DOM document.
294      * @see DocumentInputSource
295      */

296     public void setInputSource(InputSource source) {
297         _source = source;
298     }
299
300     /**
301      * Sets the reader used when reading in the source. If not set,
302      * this defaults to a basic SAX parser.
303      */

304     public void setXMLReader(XMLReader JavaDoc reader) {
305         _reader = reader;
306     }
307
308     /**
309      * Sets all the element and property list mappings to their default values.
310      *
311      */

312     public void setupDefaultMappings() {
313         addElementMapping("org.apache.fop.fo.StandardElementMapping");
314         addElementMapping("org.apache.fop.svg.SVGElementMapping");
315         addElementMapping("org.apache.fop.extensions.ExtensionElementMapping");
316
317         // add mappings from available services
318
Enumeration JavaDoc providers =
319             Service.providers(org.apache.fop.fo.ElementMapping.class);
320         if (providers != null) {
321             while (providers.hasMoreElements()) {
322                 String JavaDoc str = (String JavaDoc)providers.nextElement();
323                 try {
324                     addElementMapping(str);
325                 } catch (IllegalArgumentException JavaDoc e) {}
326
327             }
328         }
329     }
330
331     /**
332      * Set the rendering type to use. Must be one of
333      * <ul>
334      * <li>RENDER_PDF
335      * <li>RENDER_AWT
336      * <li>RENDER_MIF
337      * <li>RENDER_XML
338      * <li>RENDER_PCL
339      * <li>RENDER_PS
340      * <li>RENDER_TXT
341      * <li>RENDER_SVG
342      * </ul>
343      * @param renderer the type of renderer to use
344      */

345     public void setRenderer(int renderer) throws IllegalArgumentException JavaDoc {
346         switch (renderer) {
347         case RENDER_PDF:
348             setRenderer(new org.apache.fop.render.pdf.PDFRenderer());
349             break;
350         case RENDER_AWT:
351             throw new IllegalArgumentException JavaDoc("Use renderer form of setRenderer() for AWT");
352         case RENDER_PRINT:
353             throw new IllegalArgumentException JavaDoc("Use renderer form of setRenderer() for PRINT");
354         case RENDER_PCL:
355             setRenderer(new org.apache.fop.render.pcl.PCLRenderer());
356             break;
357         case RENDER_PS:
358             setRenderer(new org.apache.fop.render.ps.PSRenderer());
359             break;
360         case RENDER_TXT:
361             setRenderer(new org.apache.fop.render.txt.TXTRenderer());
362             break;
363         case RENDER_MIF:
364             setRenderer(new org.apache.fop.render.mif.MIFRenderer());
365             break;
366         case RENDER_XML:
367             setRenderer(new org.apache.fop.render.xml.XMLRenderer());
368             break;
369         case RENDER_SVG:
370             setRenderer(new org.apache.fop.render.svg.SVGRenderer());
371             break;
372         default:
373             throw new IllegalArgumentException JavaDoc("Unknown renderer type");
374         }
375
376     }
377
378     /**
379      * Set the Renderer to use
380      * @param renderer the renderer instance to use
381      */

382     public void setRenderer(Renderer renderer) {
383         renderer.setLogger(getLogger());
384         _renderer = renderer;
385     }
386
387     public Renderer getRenderer() {
388         return _renderer;
389     }
390
391     /**
392      * @deprecated use renderer.setProducer(version) + setRenderer(renderer) or just setRenderer(renderer_type) which will use the default producer string.
393      * @see #setRenderer(int)
394      * @see #setRenderer(Renderer)
395      */

396     public void setRenderer(String JavaDoc rendererClassName, String JavaDoc version) {
397         setRenderer(rendererClassName);
398     }
399
400     /**
401      * Set the class name of the Renderer to use as well as the
402      * producer string for those renderers that can make use of it.
403      * @param rendererClassName classname of the renderer to use such as
404      * "org.apache.fop.render.pdf.PDFRenderer"
405      * @exception IllegalArgumentException if the classname was invalid.
406      * @see #setRenderer(int)
407      */

408     public void setRenderer(String JavaDoc rendererClassName)
409     throws IllegalArgumentException JavaDoc {
410         try {
411             _renderer =
412                 (Renderer)Class.forName(rendererClassName).newInstance();
413             _renderer.setProducer(Version.getVersion());
414         } catch (ClassNotFoundException JavaDoc e) {
415             throw new IllegalArgumentException JavaDoc("Could not find "
416                                                + rendererClassName);
417         }
418         catch (InstantiationException JavaDoc e) {
419             throw new IllegalArgumentException JavaDoc("Could not instantiate "
420                                                + rendererClassName);
421         }
422         catch (IllegalAccessException JavaDoc e) {
423             throw new IllegalArgumentException JavaDoc("Could not access "
424                                                + rendererClassName);
425         }
426         catch (ClassCastException JavaDoc e) {
427             throw new IllegalArgumentException JavaDoc(rendererClassName
428                                                + " is not a renderer");
429         }
430     }
431
432     /**
433      * Add the given element mapping.
434      * An element mapping maps element names to Java classes.
435      *
436      * @param mapping the element mappingto add
437      */

438     public void addElementMapping(ElementMapping mapping) {
439         mapping.addToBuilder(_treeBuilder);
440     }
441
442     /**
443      * add the element mapping with the given class name
444      */

445     public void addElementMapping(String JavaDoc mappingClassName)
446     throws IllegalArgumentException JavaDoc {
447         try {
448             ElementMapping mapping =
449                 (ElementMapping)Class.forName(mappingClassName).newInstance();
450             addElementMapping(mapping);
451         } catch (ClassNotFoundException JavaDoc e) {
452             throw new IllegalArgumentException JavaDoc("Could not find "
453                                                + mappingClassName);
454         }
455         catch (InstantiationException JavaDoc e) {
456             throw new IllegalArgumentException JavaDoc("Could not instantiate "
457                                                + mappingClassName);
458         }
459         catch (IllegalAccessException JavaDoc e) {
460             throw new IllegalArgumentException JavaDoc("Could not access "
461                                                + mappingClassName);
462         }
463         catch (ClassCastException JavaDoc e) {
464             throw new IllegalArgumentException JavaDoc(mappingClassName
465                                                + " is not an ElementMapping");
466         }
467     }
468
469     /**
470      * Returns the tree builder (a SAX ContentHandler).
471      *
472      * Used in situations where SAX is used but not via a FOP-invoked
473      * SAX parser. A good example is an XSLT engine that fires SAX
474      * events but isn't a SAX Parser itself.
475      */

476     public ContentHandler JavaDoc getContentHandler() {
477         if (!(_renderer instanceof org.apache.fop.render.awt.AWTRenderer
478               || _renderer instanceof org.apache.fop.render.PrintRenderer)) {
479             if (_stream == null) throw new NullPointerException JavaDoc("OutputStream has not been set. Set before getting the ContentHandler");
480         }
481         if (_renderer == null) throw new NullPointerException JavaDoc("The renderer has not been set. Set before getting the ContentHandler");
482         StreamRenderer streamRenderer = new StreamRenderer(_stream, _renderer);
483         streamRenderer.setLogger(getLogger());
484         _treeBuilder.setLogger(getLogger());
485         _treeBuilder.setStreamRenderer(streamRenderer);
486
487         return _treeBuilder;
488     }
489
490     /**
491      * Build the formatting object tree using the given SAX Parser and
492      * SAX InputSource
493      */

494     public synchronized void render(XMLReader JavaDoc parser, InputSource source)
495                 throws FOPException {
496         parser.setContentHandler(getContentHandler());
497         try {
498             parser.parse(source);
499         } catch (SAXException JavaDoc e) {
500             if (e.getException() instanceof FOPException) {
501                 throw (FOPException)e.getException();
502             } else {
503                 throw new FOPException(e);
504             }
505         }
506         catch (IOException JavaDoc e) {
507             throw new FOPException(e);
508         }
509     }
510
511     /**
512      * Build the formatting object tree using the given DOM Document
513      */

514     public synchronized void render(Document JavaDoc document)
515                 throws FOPException {
516          DocumentInputSource source = new DocumentInputSource(document);
517          DocumentReader reader = new DocumentReader();
518          render(reader, source);
519     }
520
521     /**
522      * Dumps an error
523      */

524     public void dumpError(Exception JavaDoc e) {
525         if (_errorDump) {
526             Logger log = getLogger();
527             if (e instanceof SAXException JavaDoc) {
528                 log.error("", e);
529                 if (((SAXException JavaDoc)e).getException() != null) {
530                     log.error("", ((SAXException JavaDoc)e).getException());
531                 }
532             } else if (e instanceof FOPException) {
533                 e.printStackTrace();
534                 if (((FOPException)e).getException() != null) {
535                     log.error("", ((FOPException)e).getException());
536                 }
537             } else {
538                 log.error("", e);
539             }
540         }
541     }
542
543     /**
544      * Runs the formatting and renderering process using the previously set
545      * inputsource and outputstream
546      */

547     public synchronized void run() throws IOException JavaDoc, FOPException {
548         if (_renderer == null) {
549             setRenderer(RENDER_PDF);
550         }
551
552         if (_source == null) {
553             throw new FOPException("InputSource is not set.");
554         }
555
556         if (_reader == null) {
557             if (!(_source instanceof DocumentInputSource)) {
558                 _reader = ConfigurationReader.createParser();
559             }
560         }
561
562         if (_source instanceof DocumentInputSource) {
563             render(((DocumentInputSource)_source).getDocument());
564         } else {
565             render(_reader, _source);
566         }
567     }
568
569 }
570
571 // code stolen from org.apache.batik.util and modified slightly
572
// does what sun.misc.Service probably does, but it cannot be relied on.
573
// hopefully will be part of standard jdk sometime.
574

575 /**
576  * This class loads services present in the class path.
577  */

578 class Service {
579
580     static HashMap JavaDoc providerMap = new HashMap JavaDoc();
581
582     public static synchronized Enumeration JavaDoc providers(Class JavaDoc cls) {
583         ClassLoader JavaDoc cl = cls.getClassLoader();
584         String JavaDoc serviceFile = "META-INF/services/" + cls.getName();
585
586         // System.out.println("File: " + serviceFile);
587

588         Vector JavaDoc v = (Vector JavaDoc)providerMap.get(serviceFile);
589         if (v != null)
590             return v.elements();
591
592         v = new Vector JavaDoc();
593         providerMap.put(serviceFile, v);
594
595         Enumeration JavaDoc e;
596         try {
597             e = cl.getResources(serviceFile);
598         } catch (IOException JavaDoc ioe) {
599             return v.elements();
600         }
601
602         while (e.hasMoreElements()) {
603             try {
604                 java.net.URL JavaDoc u = (java.net.URL JavaDoc)e.nextElement();
605                 // System.out.println("URL: " + u);
606

607                 InputStream JavaDoc is = u.openStream();
608                 InputStreamReader JavaDoc r = new InputStreamReader JavaDoc(is, "UTF-8");
609                 BufferedReader JavaDoc br = new BufferedReader JavaDoc(r);
610
611                 String JavaDoc line = br.readLine();
612                 while (line != null) {
613                     try {
614                         // First strip any comment...
615
int idx = line.indexOf('#');
616                         if (idx != -1)
617                             line = line.substring(0, idx);
618
619                         // Trim whitespace.
620
line = line.trim();
621
622                         // If nothing left then loop around...
623
if (line.length() == 0) {
624                             line = br.readLine();
625                             continue;
626                         }
627                         // System.out.println("Line: " + line);
628

629                         // Try and load the class
630
// Object obj = cl.loadClass(line).newInstance();
631
// stick it into our vector...
632
v.add(line);
633                     } catch (Exception JavaDoc ex) {
634                         // Just try the next line
635
}
636
637                     line = br.readLine();
638                 }
639             } catch (Exception JavaDoc ex) {
640                 // Just try the next file...
641
}
642
643         }
644         return v.elements();
645     }
646
647 }
648
649
Popular Tags