123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414 |
- /*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
- /* $Id$ */
-
- package org.apache.fop.fo;
-
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.io.OutputStream;
- import java.io.Reader;
- import java.util.ArrayList;
- import java.util.Enumeration;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Map;
- import java.util.Set;
-
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- import org.apache.fop.apps.FOPException;
- import org.apache.fop.apps.FOUserAgent;
- import org.apache.fop.area.AreaTreeHandler;
- import org.apache.fop.render.mif.MIFHandler;
- import org.apache.fop.render.rtf.RTFHandler;
- import org.apache.fop.fo.ElementMapping.Maker;
- import org.apache.fop.fo.pagination.Root;
- import org.xml.sax.Attributes;
- import org.xml.sax.Locator;
- import org.xml.sax.SAXException;
- import org.xml.sax.helpers.DefaultHandler;
-
- /**
- * SAX Handler that passes parsed data to the various
- * FO objects, where they can be used either to build
- * an FO Tree, or used by Structure Renderers to build
- * other data structures.
- */
- public class FOTreeBuilder extends DefaultHandler {
-
- /**
- * Table mapping element names to the makers of objects
- * representing formatting objects.
- */
- protected Map fobjTable = new java.util.HashMap();
-
- /**
- * logging instance
- */
- protected Log log = LogFactory.getLog(FOTreeBuilder.class);
-
- /**
- * Set of mapped namespaces.
- */
- protected Set namespaces = new java.util.HashSet();
-
- /**
- * The root of the formatting object tree
- */
- protected Root rootFObj = null;
-
- /**
- * Current formatting object being handled
- */
- protected FONode currentFObj = null;
-
- /**
- * The class that handles formatting and rendering to a stream
- * (mark-fop@inomial.com)
- */
- private FOInputHandler foInputHandler;
-
- /** The SAX locator object managing the line and column counters */
- private Locator locator;
-
- /**
- * FOTreeBuilder constructor
- * @param render type as defined in Constants class
- * @param foUserAgent in effect for this process
- * @param stream OutputStream to direct results
- */
- public FOTreeBuilder(int renderType, FOUserAgent foUserAgent,
- OutputStream stream) throws FOPException {
- if (renderType == Constants.RENDER_MIF) {
- foInputHandler = new MIFHandler(foUserAgent, stream);
- } else if (renderType == Constants.RENDER_RTF) {
- foInputHandler = new RTFHandler(foUserAgent, stream);
- } else {
- if (renderType == Constants.NOT_SET) {
- throw new IllegalStateException(
- "Render must be set using setRender(int renderType)");
- }
-
- foInputHandler = new AreaTreeHandler(foUserAgent, renderType,
- stream);
- }
-
- // Add standard element mappings
- setupDefaultMappings();
-
- // add additional ElementMappings defined within FOUserAgent
- ArrayList addlEMs = foUserAgent.getAdditionalElementMappings();
-
- if (addlEMs != null) {
- for (int i = 0; i < addlEMs.size(); i++) {
- addElementMapping((String) addlEMs.get(i));
- }
- }
- }
-
- /**
- * Sets all the element and property list mappings to their default values.
- *
- */
- private void setupDefaultMappings() {
- addElementMapping("org.apache.fop.fo.FOElementMapping");
- addElementMapping("org.apache.fop.fo.extensions.svg.SVGElementMapping");
- addElementMapping("org.apache.fop.fo.extensions.svg.BatikExtensionElementMapping");
- addElementMapping("org.apache.fop.fo.extensions.ExtensionElementMapping");
-
- // add mappings from available services
- Iterator providers =
- Service.providers(ElementMapping.class);
- if (providers != null) {
- while (providers.hasNext()) {
- String str = (String)providers.next();
- try {
- addElementMapping(str);
- } catch (IllegalArgumentException e) {
- log.warn("Error while adding element mapping", e);
- }
-
- }
- }
- }
-
- /**
- * Add the element mapping with the given class name.
- * @param mappingClassName the class name representing the element mapping.
- * @throws IllegalArgumentException if there was not such element mapping.
- */
- public void addElementMapping(String mappingClassName)
- throws IllegalArgumentException {
-
- try {
- ElementMapping mapping =
- (ElementMapping)Class.forName(mappingClassName).newInstance();
- addElementMapping(mapping);
- } catch (ClassNotFoundException e) {
- throw new IllegalArgumentException("Could not find "
- + mappingClassName);
- } catch (InstantiationException e) {
- throw new IllegalArgumentException("Could not instantiate "
- + mappingClassName);
- } catch (IllegalAccessException e) {
- throw new IllegalArgumentException("Could not access "
- + mappingClassName);
- } catch (ClassCastException e) {
- throw new IllegalArgumentException(mappingClassName
- + " is not an ElementMapping");
- }
- }
-
- private void addElementMapping(ElementMapping mapping) {
- this.fobjTable.put(mapping.getNamespaceURI(), mapping.getTable());
- this.namespaces.add(mapping.getNamespaceURI().intern());
- }
-
- /**
- * SAX Handler for locator
- * @see org.xml.sax.ContentHandler#setDocumentLocator(Locator)
- */
- public void setDocumentLocator(Locator locator) {
- this.locator = locator;
- }
-
- /**
- * SAX Handler for characters
- * @see org.xml.sax.ContentHandler#characters(char[], int, int)
- */
- public void characters(char[] data, int start, int length) {
- if (currentFObj != null) {
- currentFObj.addCharacters(data, start, start + length, locator);
- }
- }
-
- /**
- * SAX Handler for the start of the document
- * @see org.xml.sax.ContentHandler#startDocument()
- */
- public void startDocument() throws SAXException {
- rootFObj = null; // allows FOTreeBuilder to be reused
- if (log.isDebugEnabled()) {
- log.debug("Building formatting object tree");
- }
- foInputHandler.startDocument();
- }
-
- /**
- * SAX Handler for the end of the document
- * @see org.xml.sax.ContentHandler#endDocument()
- */
- public void endDocument() throws SAXException {
- rootFObj = null;
- currentFObj = null;
- if (log.isDebugEnabled()) {
- log.debug("Parsing of document complete");
- }
- foInputHandler.endDocument();
- }
-
- /**
- * SAX Handler for the start of an element
- * @see org.xml.sax.ContentHandler#startElement(String, String, String, Attributes)
- */
- public void startElement(String namespaceURI, String localName, String rawName,
- Attributes attlist) throws SAXException {
-
- /* the node found in the FO document */
- FONode foNode;
-
- // Check to ensure first node encountered is an fo:root
- if (rootFObj == null) {
- if (!namespaceURI.equals(FOElementMapping.URI)
- || !localName.equals("root")) {
- throw new SAXException(new IllegalArgumentException(
- "Error: First element must be fo:root formatting object"));
- }
- } else { // check that incoming node is valid for currentFObj
- try {
- currentFObj.validateChildNode(locator, namespaceURI, localName);
- } catch (IllegalArgumentException e) {
- throw new SAXException(e);
- }
- }
-
- ElementMapping.Maker fobjMaker = findFOMaker(namespaceURI, localName);
- // System.out.println("found a " + fobjMaker.toString());
-
- try {
- foNode = fobjMaker.make(currentFObj);
- foNode.processNode(localName, locator, attlist);
- } catch (IllegalArgumentException e) {
- throw new SAXException(e);
- } catch (FOPException e) {
- throw new SAXException(e);
- }
-
- if (rootFObj == null) {
- rootFObj = (Root) foNode;
- rootFObj.setFOInputHandler(foInputHandler);
- } else {
- currentFObj.addChild(foNode);
- }
-
- currentFObj = foNode;
- }
-
- /**
- * SAX Handler for the end of an element
- * @see org.xml.sax.ContentHandler#endElement(String, String, String)
- */
- public void endElement(String uri, String localName, String rawName)
- throws SAXException {
- try {
- currentFObj.end();
- } catch (IllegalArgumentException e) {
- throw new SAXException(e);
- }
-
- currentFObj = currentFObj.getParent();
- }
-
- /**
- * Finds the Maker used to create FO objects of a particular type
- * @param namespaceURI URI for the namespace of the element
- * @param localName name of the Element
- * @return the ElementMapping.Maker that can create an FO object for this element
- */
- private Maker findFOMaker(String namespaceURI, String localName) {
- Map table = (Map)fobjTable.get(namespaceURI);
- Maker fobjMaker = null;
- if (table != null) {
- fobjMaker = (ElementMapping.Maker)table.get(localName);
- // try default
- if (fobjMaker == null) {
- fobjMaker = (ElementMapping.Maker)table.get(ElementMapping.DEFAULT);
- }
- }
-
- if (fobjMaker == null) {
- if (log.isWarnEnabled()) {
- log.warn("Unknown formatting object " + namespaceURI + "^" + localName);
- }
- if (namespaces.contains(namespaceURI.intern())) {
- // fall back
- fobjMaker = new Unknown.Maker();
- } else {
- fobjMaker = new UnknownXMLObj.Maker(namespaceURI);
- }
- }
- return fobjMaker;
- }
-
- /**
- * Resets this object for another run.
- */
- public void reset() {
- currentFObj = null;
- rootFObj = null;
- foInputHandler = null;
- }
-
- }
-
- // code stolen from org.apache.batik.util and modified slightly
- // does what sun.misc.Service probably does, but it cannot be relied on.
- // hopefully will be part of standard jdk sometime.
-
- /**
- * This class loads services present in the class path.
- */
- class Service {
-
- private static Map providerMap = new java.util.Hashtable();
-
- public static synchronized Iterator providers(Class cls) {
- ClassLoader cl = cls.getClassLoader();
- // null if loaded by bootstrap class loader
- if (cl == null) {
- cl = ClassLoader.getSystemClassLoader();
- }
- String serviceFile = "META-INF/services/" + cls.getName();
-
- // log.debug("File: " + serviceFile);
-
- List lst = (List)providerMap.get(serviceFile);
- if (lst != null) {
- return lst.iterator();
- }
-
- lst = new java.util.Vector();
- providerMap.put(serviceFile, lst);
-
- Enumeration e;
- try {
- e = cl.getResources(serviceFile);
- } catch (IOException ioe) {
- return lst.iterator();
- }
-
- while (e.hasMoreElements()) {
- try {
- java.net.URL u = (java.net.URL)e.nextElement();
- //log.debug("URL: " + u);
-
- InputStream is = u.openStream();
- Reader r = new InputStreamReader(is, "UTF-8");
- BufferedReader br = new BufferedReader(r);
-
- String line = br.readLine();
- while (line != null) {
- try {
- // First strip any comment...
- int idx = line.indexOf('#');
- if (idx != -1) {
- line = line.substring(0, idx);
- }
-
- // Trim whitespace.
- line = line.trim();
-
- // If nothing left then loop around...
- if (line.length() == 0) {
- line = br.readLine();
- continue;
- }
- // log.debug("Line: " + line);
-
- // Try and load the class
- // Object obj = cl.loadClass(line).newInstance();
- // stick it into our vector...
- lst.add(line);
- } catch (Exception ex) {
- // Just try the next line
- }
-
- line = br.readLine();
- }
- } catch (Exception ex) {
- // Just try the next file...
- }
-
- }
- return lst.iterator();
- }
-
- }
|