| /* | ||
| * Copyright 2001-2004 (C) MetaStuff, Ltd. All Rights Reserved. | ||
| * | ||
| * This software is open source. | ||
| * See the bottom of this file for the licence. | ||
| * | ||
| * $Id: SAXModifier.java,v 1.2 2004/10/16 19:03:41 maartenc Exp $ | ||
| */ | ||
| package org.dom4j.io; | ||
| import java.io.File; | ||
| import java.io.InputStream; | ||
| import java.io.Reader; | ||
| import java.net.URL; | ||
| import java.util.HashMap; | ||
| import java.util.Iterator; | ||
| import java.util.Map; | ||
| import org.dom4j.Document; | ||
| import org.dom4j.DocumentException; | ||
| import org.dom4j.DocumentFactory; | ||
| import org.xml.sax.InputSource; | ||
| import org.xml.sax.SAXException; | ||
| import org.xml.sax.XMLReader; | ||
| /** | ||
| * The SAXModifier reads, modifies and writes XML documents using SAX. <br> | ||
| * Registered {@link ElementModifier} objects can provide modifications to (part of) the xml tree, | ||
| * while the document is still being processed. This makes it possible to change large xml documents | ||
| * without having them in memory.<br> | ||
| * The modified document is written when the {@link XMLWriter} is specified. | ||
| * | ||
| * @see org.dom4j.io.SAXReader | ||
| * @see org.dom4j.io.XMLWriter | ||
| * @author Wonne Keysers (Realsoftware.be) | ||
| */ | ||
| public class SAXModifier { | ||
| private XMLWriter xmlWriter; | ||
| private XMLReader xmlReader; | ||
| private boolean pruneElements; | ||
| private SAXModifyReader modifyReader; | ||
| 0x | private HashMap modifiers = new HashMap(); | |
| /** | ||
| * Creates a new modifier.<br> | ||
| * The XMLReader to parse the source will be created via the org.xml.sax.driver system property | ||
| * or JAXP if the system property is not set. | ||
| */ | ||
| 0x | public SAXModifier() { | |
| 0x | } | |
| /** | ||
| * Creates a new modifier.<br> | ||
| * The XMLReader to parse the source will be created via the org.xml.sax.driver system property | ||
| * or JAXP if the system property is not set. | ||
| * | ||
| * @param pruneElements Set to true when the modified document must NOT be kept in memory. | ||
| */ | ||
| 0x | public SAXModifier(boolean pruneElements) { | |
| 0x | this.pruneElements = pruneElements; | |
| 0x | } | |
| /** | ||
| * Creates a new modifier that will the specified {@link org.xml.sax.XMLReader} | ||
| * to parse the source. | ||
| * | ||
| * @param xmlReader The XMLReader to use | ||
| */ | ||
| 0x | public SAXModifier(XMLReader xmlReader) { | |
| 0x | this.xmlReader = xmlReader; | |
| 0x | } | |
| /** | ||
| * Creates a new modifier that will the specified {@link org.xml.sax.XMLReader} | ||
| * to parse the source. | ||
| * | ||
| * @param xmlReader The XMLReader to use | ||
| * @param pruneElements Set to true when the modified document must NOT be kept in memory. | ||
| */ | ||
| 0x | public SAXModifier(XMLReader xmlReader, boolean pruneElements) { | |
| 0x | this.xmlReader = xmlReader; | |
| 0x | } | |
| /** | ||
| * Reads a Document from the given {@link java.io.File} | ||
| * and writes it to the specified {@link XMLWriter} using SAX. | ||
| * Registered {@link ElementModifier} objects are invoked on the fly. | ||
| * | ||
| * @param source is the <code>File</code> to read from. | ||
| * @return the newly created Document instance | ||
| * @throws {@link org.dom4j.DocumentException} if an error occurs during parsing. | ||
| */ | ||
| public Document modify(File source) throws DocumentException { | ||
| try { | ||
| 0x | return installModifyReader().read(source); | |
| } | ||
| catch (SAXModifyException ex) { | ||
| 0x | Throwable cause = ex.getCause(); | |
| 0x | throw new DocumentException(cause.getMessage(), cause); | |
| } | ||
| } | ||
| /** | ||
| * Reads a Document from the given {@link org.xml.sax.InputSource} | ||
| * and writes it to the specified {@link XMLWriter} using SAX. | ||
| * Registered {@link ElementModifier} objects are invoked on the fly. | ||
| * | ||
| * @param source is the <code>org.xml.sax.InputSource</code> to read from. | ||
| * @return the newly created Document instance | ||
| * @throws {@link org.dom4j.DocumentException} if an error occurs during parsing. | ||
| */ | ||
| public Document modify(InputSource source) throws DocumentException { | ||
| try { | ||
| 0x | return installModifyReader().read(source); | |
| } | ||
| catch (SAXModifyException ex) { | ||
| 0x | Throwable cause = ex.getCause(); | |
| 0x | throw new DocumentException(cause.getMessage(), cause); | |
| } | ||
| } | ||
| /** | ||
| * Reads a Document from the given {@link java.io.InputStream} | ||
| * and writes it to the specified {@link XMLWriter} using SAX. | ||
| * Registered {@link ElementModifier} objects are invoked on the fly. | ||
| * | ||
| * @param source is the <code>java.io.InputStream</code> to read from. | ||
| * @return the newly created Document instance | ||
| * @throws {@link org.dom4j.DocumentException} if an error occurs during parsing. | ||
| */ | ||
| public Document modify(InputStream source) throws DocumentException { | ||
| try { | ||
| 0x | return installModifyReader().read(source); | |
| } | ||
| catch (SAXModifyException ex) { | ||
| 0x | Throwable cause = ex.getCause(); | |
| 0x | throw new DocumentException(cause.getMessage(), cause); | |
| } | ||
| } | ||
| /** | ||
| * Reads a Document from the given {@link java.io.InputStream} | ||
| * and writes it to the specified {@link XMLWriter} using SAX. | ||
| * Registered {@link ElementModifier} objects are invoked on the fly. | ||
| * | ||
| * @param source is the <code>java.io.InputStream</code> to read from. | ||
| * @return the newly created Document instance | ||
| * @throws {@link org.dom4j.DocumentException} if an error occurs during parsing. | ||
| */ | ||
| public Document modify(InputStream source, String systemId) throws DocumentException { | ||
| try { | ||
| 0x | return installModifyReader().read(source); | |
| } | ||
| catch (SAXModifyException ex) { | ||
| 0x | Throwable cause = ex.getCause(); | |
| 0x | throw new DocumentException(cause.getMessage(), cause); | |
| } | ||
| } | ||
| /** | ||
| * Reads a Document from the given {@link java.io.Reader} | ||
| * and writes it to the specified {@link XMLWriter} using SAX. | ||
| * Registered {@link ElementModifier} objects are invoked on the fly. | ||
| * | ||
| * @param source is the <code>java.io.Reader</code> to read from. | ||
| * @return the newly created Document instance | ||
| * @throws {@link org.dom4j.DocumentException} if an error occurs during parsing. | ||
| */ | ||
| public Document modify(Reader source) throws DocumentException { | ||
| try { | ||
| 0x | return installModifyReader().read(source); | |
| } | ||
| catch (SAXModifyException ex) { | ||
| 0x | Throwable cause = ex.getCause(); | |
| 0x | throw new DocumentException(cause.getMessage(), cause); | |
| } | ||
| } | ||
| /** | ||
| * Reads a Document from the given {@link java.io.Reader} | ||
| * and writes it to the specified {@link XMLWriter} using SAX. | ||
| * Registered {@link ElementModifier} objects are invoked on the fly. | ||
| * | ||
| * @param source is the <code>java.io.Reader</code> to read from. | ||
| * @return the newly created Document instance | ||
| * @throws {@link org.dom4j.DocumentException} if an error occurs during parsing. | ||
| */ | ||
| public Document modify(Reader source, String systemId) throws DocumentException { | ||
| try { | ||
| 0x | return installModifyReader().read(source); | |
| } | ||
| catch (SAXModifyException ex) { | ||
| 0x | Throwable cause = ex.getCause(); | |
| 0x | throw new DocumentException(cause.getMessage(), cause); | |
| } | ||
| } | ||
| /** | ||
| * Reads a Document from the given {@link java.net.URL} | ||
| * and writes it to the specified {@link XMLWriter} using SAX. | ||
| * Registered {@link ElementModifier} objects are invoked on the fly. | ||
| * | ||
| * @param source is the <code>java.net.URL</code> to read from. | ||
| * @return the newly created Document instance | ||
| * @throws {@link org.dom4j.DocumentException} if an error occurs during parsing. | ||
| */ | ||
| public Document modify(URL source) throws DocumentException { | ||
| try { | ||
| 0x | return installModifyReader().read(source); | |
| } | ||
| catch (SAXModifyException ex) { | ||
| 0x | Throwable cause = ex.getCause(); | |
| 0x | throw new DocumentException(cause.getMessage(), cause); | |
| } | ||
| } | ||
| /** | ||
| * Reads a Document from the given URL or filename | ||
| * and writes it to the specified {@link XMLWriter} using SAX. | ||
| * Registered {@link ElementModifier} objects are invoked on the fly. | ||
| * | ||
| * @param source is the URL or filename to read from. | ||
| * @return the newly created Document instance | ||
| * @throws {@link org.dom4j.DocumentException} if an error occurs during parsing. | ||
| */ | ||
| public Document modify(String source) throws DocumentException { | ||
| try { | ||
| 0x | return installModifyReader().read(source); | |
| } | ||
| catch (SAXModifyException ex) { | ||
| 0x | Throwable cause = ex.getCause(); | |
| 0x | throw new DocumentException(cause.getMessage(), cause); | |
| } | ||
| } | ||
| /** | ||
| * Adds the {@link ElementModifier} to be called | ||
| * when the specified element path is encounted while parsing the source. | ||
| * | ||
| * @param path The element path to be handled | ||
| * @param modifier The {@link ElementModifier} to be called by the event based processor. | ||
| */ | ||
| public void addModifier(String path, ElementModifier modifier) { | ||
| 0x | this.modifiers.put(path, modifier); | |
| 0x | } | |
| /** | ||
| * Removes all registered {@link ElementModifier} instances from the event based processor. | ||
| */ | ||
| public void resetModifiers() { | ||
| 0x | this.modifiers.clear(); | |
| 0x | getSAXModifyReader().resetHandlers(); | |
| 0x | } | |
| /** | ||
| * Removes the {@link ElementModifier} from the event based processor, | ||
| * for the specified element path. | ||
| * | ||
| * @param path The path to remove the {@link ElementModifier} for. | ||
| */ | ||
| public void removeModifier(String path) { | ||
| 0x | this.modifiers.remove(path); | |
| 0x | getSAXModifyReader().removeHandler(path); | |
| 0x | } | |
| /** | ||
| * Get the {@link org.dom4j.DocumentFactory} used to create the DOM4J document structure | ||
| * | ||
| * @return <code>DocumentFactory</code> that will be used | ||
| */ | ||
| public DocumentFactory getDocumentFactory() { | ||
| 0x | return getSAXModifyReader().getDocumentFactory(); | |
| } | ||
| /** | ||
| * Sets the {@link org.dom4j.DocumentFactory} used to create the DOM4J document tree. | ||
| * | ||
| * @param factory <code>DocumentFactory</code> to be used | ||
| */ | ||
| public void setDocumentFactory(DocumentFactory factory) { | ||
| 0x | getSAXModifyReader().setDocumentFactory(factory); | |
| 0x | } | |
| /** | ||
| * Returns the current {@link XMLWriter}. | ||
| * @return XMLWriter | ||
| */ | ||
| public XMLWriter getXMLWriter() { | ||
| 0x | return this.xmlWriter; | |
| } | ||
| /** | ||
| * Sets the {@link XMLWriter} used to write the modified document. | ||
| * @param xmlWriter The writer to use. | ||
| */ | ||
| public void setXMLWriter(XMLWriter xmlWriter) { | ||
| 0x | this.xmlWriter = xmlWriter; | |
| 0x | } | |
| /** | ||
| * Returns true when xml elements are not kept in memory while parsing. | ||
| * The {@link org.dom4j.Document} returned by the modify methods will be null. | ||
| * @return Returns the pruneElements. | ||
| */ | ||
| public boolean isPruneElements() { | ||
| 0x | return pruneElements; | |
| } | ||
| private SAXReader installModifyReader() throws DocumentException { | ||
| try { | ||
| 0x | SAXModifyReader reader = getSAXModifyReader(); | |
| 0/2 0x | if (isPruneElements()) { | |
| 0x | modifyReader.setDispatchHandler(new PruningDispatchHandler()); | |
| } | ||
| 0x | reader.resetHandlers(); | |
| 0x | Iterator modifierIt = this.modifiers.entrySet().iterator(); | |
| 0/2 0x | while(modifierIt.hasNext()){ | |
| 0x | Map.Entry entry = (Map.Entry)modifierIt.next(); | |
| 0x | SAXModifyElementHandler modifierHandler | |
| = new SAXModifyElementHandler((ElementModifier)entry.getValue()); | ||
| 0x | reader.addHandler((String)entry.getKey(), modifierHandler); | |
| } | ||
| 0x | reader.setXMLWriter(getXMLWriter()); | |
| 0x | reader.setXMLReader(getXMLReader()); | |
| 0x | return reader; | |
| } | ||
| catch (SAXException ex) { | ||
| 0x | throw new DocumentException(ex.getMessage(), ex); | |
| } | ||
| } | ||
| private XMLReader getXMLReader() throws SAXException { | ||
| 0/2 0x | if (this.xmlReader == null) { | |
| 0x | xmlReader = SAXHelper.createXMLReader(false); | |
| } | ||
| 0x | return this.xmlReader; | |
| } | ||
| private SAXModifyReader getSAXModifyReader() { | ||
| 0/2 0x | if (modifyReader == null) { | |
| 0x | modifyReader = new SAXModifyReader(); | |
| } | ||
| 0x | return modifyReader; | |
| } | ||
| } | ||
| /* | ||
| * Redistribution and use of this software and associated documentation | ||
| * ("Software"), with or without modification, are permitted provided | ||
| * that the following conditions are met: | ||
| * | ||
| * 1. Redistributions of source code must retain copyright | ||
| * statements and notices. Redistributions must also contain a | ||
| * copy of this document. | ||
| * | ||
| * 2. Redistributions in binary form must reproduce the | ||
| * above copyright notice, this list of conditions and the | ||
| * following disclaimer in the documentation and/or other | ||
| * materials provided with the distribution. | ||
| * | ||
| * 3. The name "DOM4J" must not be used to endorse or promote | ||
| * products derived from this Software without prior written | ||
| * permission of MetaStuff, Ltd. For written permission, | ||
| * please contact dom4j-info@metastuff.com. | ||
| * | ||
| * 4. Products derived from this Software may not be called "DOM4J" | ||
| * nor may "DOM4J" appear in their names without prior written | ||
| * permission of MetaStuff, Ltd. DOM4J is a registered | ||
| * trademark of MetaStuff, Ltd. | ||
| * | ||
| * 5. Due credit should be given to the DOM4J Project - | ||
| * http://www.dom4j.org | ||
| * | ||
| * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS | ||
| * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT | ||
| * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | ||
| * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | ||
| * METASTUFF, LTD. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | ||
| * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||
| * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
| * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | ||
| * OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| * | ||
| * Copyright 2001-2004 (C) MetaStuff, Ltd. All Rights Reserved. | ||
| * | ||
| * $Id: SAXModifier.java,v 1.2 2004/10/16 19:03:41 maartenc Exp $ | ||
| */ |