Frames | No Frames |
1: /* ======================================================================== 2: * JCommon : a free general purpose class library for the Java(tm) platform 3: * ======================================================================== 4: * 5: * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors. 6: * 7: * Project Info: http://www.jfree.org/jcommon/index.html 8: * 9: * This library is free software; you can redistribute it and/or modify it 10: * under the terms of the GNU Lesser General Public License as published by 11: * the Free Software Foundation; either version 2.1 of the License, or 12: * (at your option) any later version. 13: * 14: * This library is distributed in the hope that it will be useful, but 15: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 17: * License for more details. 18: * 19: * You should have received a copy of the GNU Lesser General Public 20: * License along with this library; if not, write to the Free Software 21: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 22: * USA. 23: * 24: * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 25: * in the United States and other countries.] 26: * 27: * -------------------- 28: * ReportGenerator.java 29: * -------------------- 30: * (C)opyright 2002-2005, by Thomas Morgner and Contributors. 31: * 32: * Original Author: Thomas Morgner (taquera@sherito.org); 33: * Contributor(s): David Gilbert (for Object Refinery Limited); 34: * 35: * $Id: ParserFrontend.java,v 1.8 2005/11/14 10:58:19 mungady Exp $ 36: * 37: * Changes 38: * ------- 39: * 10-May-2002 : Initial version 40: * 12-Dec-2002 : Fixed issues reported by Checkstyle (DG); 41: * 29-Apr-2003 : Distilled from the JFreeReport project and moved into JCommon 42: * 43: */ 44: 45: package org.jfree.xml; 46: 47: import java.io.BufferedInputStream; 48: import java.io.IOException; 49: import java.net.URL; 50: import javax.xml.parsers.ParserConfigurationException; 51: import javax.xml.parsers.SAXParser; 52: import javax.xml.parsers.SAXParserFactory; 53: 54: import org.jfree.util.Log; 55: import org.xml.sax.EntityResolver; 56: import org.xml.sax.InputSource; 57: import org.xml.sax.SAXException; 58: import org.xml.sax.XMLReader; 59: 60: /** 61: * The reportgenerator initializes the parser and provides an interface 62: * the the default parser. 63: * 64: * To create a report from an URL, use 65: * <code> 66: * ReportGenerator.getInstance().parseReport (URL myURl, URL contentBase); 67: * </code> 68: * 69: * @author Thomas Morgner 70: */ 71: public class ParserFrontend { 72: 73: /** The report handler. */ 74: private FrontendDefaultHandler defaulthandler; 75: 76: /** The parser factory. */ 77: private SAXParserFactory factory; 78: 79: /** The DTD. */ 80: private EntityResolver entityResolver; 81: 82: /** A flag indicating whether to use a DTD to validate the xml input. */ 83: private boolean validateDTD; 84: 85: /** 86: * Creates a new report generator. The generator uses the singleton pattern by default, 87: * so use generator.getInstance() to get the generator. 88: * 89: * @param parser the parser that is used to coordinate the parsing process. 90: */ 91: protected ParserFrontend(final FrontendDefaultHandler parser) { 92: if (parser == null) { 93: throw new NullPointerException(); 94: } 95: this.defaulthandler = parser; 96: } 97: 98: /** 99: * Returns <code>true</code> if the report definition should be validated against the 100: * DTD, and <code>false</code> otherwise. 101: * 102: * @return A boolean. 103: */ 104: public boolean isValidateDTD() { 105: return this.validateDTD; 106: } 107: 108: /** 109: * Sets a flag that controls whether or not the report definition is validated 110: * against the DTD. 111: * 112: * @param validateDTD the flag. 113: */ 114: public void setValidateDTD(final boolean validateDTD) { 115: this.validateDTD = validateDTD; 116: } 117: 118: /** 119: * Returns the entity resolver. 120: * 121: * @return The entity resolver. 122: */ 123: public EntityResolver getEntityResolver() { 124: return this.entityResolver; 125: } 126: 127: /** 128: * Sets the entity resolver. 129: * 130: * @param entityResolver the entity resolver. 131: */ 132: public void setEntityResolver(final EntityResolver entityResolver) { 133: this.entityResolver = entityResolver; 134: } 135: 136: /** 137: * Returns a SAX parser. 138: * 139: * @return a SAXParser. 140: * 141: * @throws ParserConfigurationException if there is a problem configuring the parser. 142: * @throws SAXException if there is a problem with the parser initialisation 143: */ 144: protected SAXParser getParser() throws ParserConfigurationException, SAXException { 145: if (this.factory == null) { 146: this.factory = SAXParserFactory.newInstance(); 147: if (isValidateDTD()) { 148: try { 149: // dont touch the validating feature, if not needed .. 150: this.factory.setValidating(true); 151: } 152: catch (Exception ex) { 153: // the parser does not like the idea of validating ... 154: Log.debug("The parser will not validate the xml document.", ex); 155: } 156: } 157: } 158: return this.factory.newSAXParser(); 159: } 160: 161: /** 162: * Sets the default handler used for parsing reports. This handler is used to 163: * initiate parsing. 164: * 165: * @param handler the handler. 166: */ 167: public void setDefaultHandler(final FrontendDefaultHandler handler) { 168: if (handler == null) { 169: throw new NullPointerException(); 170: } 171: this.defaulthandler = handler; 172: } 173: 174: /** 175: * Returns the ElementDefinitionHandler used for parsing reports. 176: * 177: * @return the report handler. 178: */ 179: public FrontendDefaultHandler getDefaultHandler() { 180: return this.defaulthandler; 181: } 182: 183: /** 184: * Creates a new instance of the currently set default handler and sets the contentbase 185: * for the handler to <code>contentBase</code>. 186: * 187: * @param contentBase the content base. 188: * 189: * @return the report handler. 190: */ 191: protected FrontendDefaultHandler createDefaultHandler(final URL contentBase) { 192: final FrontendDefaultHandler handler = getDefaultHandler().newInstance(); 193: if (contentBase != null) { 194: handler.setConfigProperty(Parser.CONTENTBASE_KEY, contentBase.toExternalForm()); 195: } 196: return handler; 197: } 198: 199: /** 200: * Parses an XML report template file. 201: * 202: * @param input the input source. 203: * @param contentBase the content base. 204: * 205: * @return the report. 206: * 207: * @throws ElementDefinitionException if an error occurred. 208: */ 209: protected Object parse(final InputSource input, final URL contentBase) 210: throws ElementDefinitionException { 211: try { 212: final SAXParser parser = getParser(); 213: final XMLReader reader = parser.getXMLReader(); 214: 215: try { 216: reader.setFeature("http://xml.org/sax/features/validation", isValidateDTD()); 217: } 218: catch (SAXException se) { 219: Log.debug("The XMLReader will not validate the xml document.", se); 220: } 221: final FrontendDefaultHandler handler = createDefaultHandler(contentBase); 222: configureReader(reader, handler); 223: try { 224: reader.setContentHandler(handler); 225: reader.setDTDHandler(handler); 226: if (getEntityResolver() != null) { 227: reader.setEntityResolver(getEntityResolver()); 228: } 229: reader.setErrorHandler(handler); 230: reader.parse(input); 231: return handler.getResult(); 232: } 233: catch (IOException e) { 234: throw new ElementDefinitionException(e); 235: } 236: } 237: catch (ParserConfigurationException e) { 238: throw new ElementDefinitionException(e); 239: } 240: catch (SAXException e) { 241: throw new ElementDefinitionException(e); 242: } 243: } 244: 245: /** 246: * Configures the xml reader. Use this to set features or properties 247: * before the documents get parsed. 248: * 249: * @param handler the parser implementation that will handle the SAX-Callbacks. 250: * @param reader the xml reader that should be configured. 251: */ 252: protected void configureReader(final XMLReader reader, final FrontendDefaultHandler handler) { 253: try { 254: reader.setProperty 255: ("http://xml.org/sax/properties/lexical-handler", handler.getCommentHandler()); 256: } 257: catch (SAXException se) { 258: Log.debug("Comments are not supported by this SAX implementation."); 259: } 260: } 261: 262: /** 263: * Parses an XML file which is loaded using the given URL. All 264: * needed relative file- and resourcespecification are loaded 265: * using the URL <code>contentBase</code> as base. 266: * <p> 267: * After the report is generated, the ReportDefinition-source and the contentbase are 268: * stored as string in the reportproperties. 269: * 270: * @param file the URL for the report template file. 271: * @param contentBase the URL for the report template content base. 272: * 273: * @return the parsed report. 274: * 275: * @throws IOException if an I/O error occurs. 276: * @throws ElementDefinitionException if there is a problem parsing the report template. 277: */ 278: public Object parse(final URL file, final URL contentBase) 279: throws ElementDefinitionException, IOException { 280: if (file == null) { 281: throw new NullPointerException("File may not be null"); 282: } 283: 284: final BufferedInputStream bin = new BufferedInputStream(file.openStream()); 285: final InputSource in = new InputSource(bin); 286: in.setSystemId(file.toString()); 287: final Object result = parse(in, contentBase); 288: bin.close(); 289: return result; 290: } 291: 292: }