View Javadoc

    1   /*
    2    * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
    3    *
    4    * This software is open source.
    5    * See the bottom of this file for the licence.
    6    */
    7
    8   package org.dom4j.jaxb;
    9
    10  import java.io.File;
    11  import java.io.FileInputStream;
    12  import java.io.FileNotFoundException;
    13  import java.io.FileOutputStream;
    14  import java.io.IOException;
    15  import java.io.InputStream;
    16  import java.io.InputStreamReader;
    17  import java.io.OutputStream;
    18  import java.io.Reader;
    19  import java.io.Writer;
    20  import java.net.URL;
    21  import java.nio.charset.Charset;
    22  import java.util.HashMap;
    23  import java.util.Iterator;
    24  import java.util.Map;
    25
    26  import org.dom4j.Document;
    27  import org.dom4j.DocumentException;
    28  import org.dom4j.io.ElementModifier;
    29  import org.dom4j.io.OutputFormat;
    30  import org.dom4j.io.SAXModifier;
    31  import org.dom4j.io.XMLWriter;
    32
    33  import org.xml.sax.InputSource;
    34
    35  /***
    36   * Reads an XML document using SAX and writes its content to the provided
    37   * {@link org.dom4j.io.XMLWriter}. Modifications must be provided by {@link
    38   * org.dom4j.jaxb.JAXBObjectModifier} objects, which are called prior to writing
    39   * the XML fragment they are registered for.
    40   *
    41   * @author Wonne Keysers (Realsoftware.be)
    42   *
    43   * @see org.dom4j.io.SAXModifier
    44   */
    45  public class JAXBModifier extends JAXBSupport {
    46      private SAXModifier modifier;
    47
    48      private XMLWriter xmlWriter;
    49
    50      private boolean pruneElements;
    51
    52      private OutputFormat outputFormat;
    53
    54      private HashMap modifiers = new HashMap();
    55
    56      /***
    57       * Creates a new JAXBModifier for the given JAXB context path. This is the
    58       * Java package where JAXB can find the generated XML classes. This package
    59       * MUST contain jaxb.properties!
    60       *
    61       * @param contextPath
    62       *            JAXB context path to be used
    63       *
    64       * @see javax.xml.bind.JAXBContext
    65       */
    66      public JAXBModifier(String contextPath) {
    67          super(contextPath);
    68          this.outputFormat = new OutputFormat();
    69      }
    70
    71      /***
    72       * Creates a new JAXBModifier for the given JAXB context path, using the
    73       * given {@link java.lang.ClassLoader}. This is the Java package where JAXB
    74       * can find the generated XML classes. This package MUST contain
    75       * jaxb.properties!
    76       *
    77       * @param contextPath
    78       *            JAXB context path to be used
    79       * @param classloader
    80       *            the classloader to use
    81       *
    82       * @see javax.xml.bind.JAXBContext
    83       */
    84      public JAXBModifier(String contextPath, ClassLoader classloader) {
    85          super(contextPath, classloader);
    86          this.outputFormat = new OutputFormat();
    87      }
    88
    89      /***
    90       * Creates a new JAXBModifier for the given JAXB context path. The specified
    91       * {@link org.dom4j.io.OutputFormat}will be used while writing the XML
    92       * stream.
    93       *
    94       * @param contextPath
    95       *            JAXB context path to be used
    96       * @param outputFormat
    97       *            the DOM4J {@link org.dom4j.io.OutputFormat}to be used
    98       *
    99       * @see javax.xml.bind.JAXBContext
    100      */
    101     public JAXBModifier(String contextPath, OutputFormat outputFormat) {
    102         super(contextPath);
    103         this.outputFormat = outputFormat;
    104     }
    105
    106     /***
    107      * Creates a new JAXBModifier for the given JAXB context path, using the
    108      * specified {@link java.lang.Classloader}. The specified {@link
    109      * org.dom4j.io.OutputFormat} will be used while writing the XML stream.
    110      *
    111      * @param contextPath
    112      *            JAXB context path to be used
    113      * @param classloader
    114      *            the class loader to be used to load JAXB
    115      * @param outputFormat
    116      *            the DOM4J {@link org.dom4j.io.OutputFormat}to be used
    117      *
    118      * @see javax.xml.bind.JAXBContext
    119      */
    120     public JAXBModifier(String contextPath, ClassLoader classloader,
    121             OutputFormat outputFormat) {
    122         super(contextPath, classloader);
    123         this.outputFormat = outputFormat;
    124     }
    125
    126     /***
    127      * Parses the specified {@link java.io.File}with SAX
    128      *
    129      * @param source
    130      *            the file to parse
    131      *
    132      * @return the resulting DOM4J document
    133      *
    134      * @throws DocumentException
    135      *             when an error occurs while parsing
    136      * @throws IOException
    137      *             when an error occurs while writing to the {@link
    138      *             org.dom4j.io.XMLWriter}
    139      */
    140     public Document modify(File source) throws DocumentException, IOException {
    141         return installModifier().modify(source);
    142     }
    143
    144     /***
    145      * Parses the specified {@link java.io.File}with SAX, using the given
    146      * {@link java.nio.charset.Charset}.
    147      *
    148      * @param source
    149      *            the file to parse
    150      * @param charset
    151      *            the character set to use
    152      *
    153      * @return the resulting DOM4J document
    154      *
    155      * @throws DocumentException
    156      *             when an error occurs while parsing
    157      * @throws IOException
    158      *             when an error occurs while writing to the {@link
    159      *             org.dom4j.io.XMLWriter}
    160      */
    161     public Document modify(File source, Charset charset)
    162             throws DocumentException, IOException {
    163         try {
    164             Reader reader = new InputStreamReader(new FileInputStream(source),
    165                     charset);
    166
    167             return installModifier().modify(reader);
    168         } catch (JAXBRuntimeException ex) {
    169             Throwable cause = ex.getCause();
    170             throw new DocumentException(cause.getMessage(), cause);
    171         } catch (FileNotFoundException ex) {
    172             throw new DocumentException(ex.getMessage(), ex);
    173         }
    174     }
    175
    176     /***
    177      * Parses the specified {@link org.xml.sax.InputSource}with SAX.
    178      *
    179      * @param source
    180      *            the input source to parse
    181      *
    182      * @return the resulting DOM4J document
    183      *
    184      * @throws DocumentException
    185      *             when an error occurs while parsing
    186      * @throws IOException
    187      *             when an error occurs while writing to the {@link
    188      *             org.dom4j.io.XMLWriter}
    189      */
    190     public Document modify(InputSource source) throws DocumentException,
    191             IOException {
    192         try {
    193             return installModifier().modify(source);
    194         } catch (JAXBRuntimeException ex) {
    195             Throwable cause = ex.getCause();
    196             throw new DocumentException(cause.getMessage(), cause);
    197         }
    198     }
    199
    200     /***
    201      * Parses the specified {@link java.io.InputStream}with SAX.
    202      *
    203      * @param source
    204      *            the inputstream to parse
    205      *
    206      * @return the resulting DOM4J document
    207      *
    208      * @throws DocumentException
    209      *             when an error occurs while parsing
    210      * @throws IOException
    211      *             when an error occurs while writing to the {@link
    212      *             org.dom4j.io.XMLWriter}
    213      */
    214     public Document modify(InputStream source) throws DocumentException,
    215             IOException {
    216         try {
    217             return installModifier().modify(source);
    218         } catch (JAXBRuntimeException ex) {
    219             Throwable cause = ex.getCause();
    220             throw new DocumentException(cause.getMessage(), cause);
    221         }
    222     }
    223
    224     /***
    225      * Parses the specified {@link java.io.InputStream}with SAX.
    226      *
    227      * @param source
    228      *            the inputstream to parse
    229      * @param systemId
    230      *            the URI of the given inputstream
    231      *
    232      * @return the resulting DOM4J document
    233      *
    234      * @throws DocumentException
    235      *             when an error occurs while parsing
    236      * @throws IOException
    237      *             when an error occurs while writing to the {@link
    238      *             org.dom4j.io.XMLWriter}
    239      */
    240     public Document modify(InputStream source, String systemId)
    241             throws DocumentException, IOException {
    242         try {
    243             return installModifier().modify(source);
    244         } catch (JAXBRuntimeException ex) {
    245             Throwable cause = ex.getCause();
    246             throw new DocumentException(cause.getMessage(), cause);
    247         }
    248     }
    249
    250     /***
    251      * Parses the specified {@link java.io.Reader}with SAX.
    252      *
    253      * @param r
    254      *            the reader to use for parsing
    255      *
    256      * @return the resulting DOM4J document
    257      *
    258      * @throws DocumentException
    259      *             when an error occurs while parsing
    260      * @throws IOException
    261      *             when an error occurs while writing to the {@link
    262      *             org.dom4j.io.XMLWriter}
    263      */
    264     public Document modify(Reader r) throws DocumentException, IOException {
    265         try {
    266             return installModifier().modify(r);
    267         } catch (JAXBRuntimeException ex) {
    268             Throwable cause = ex.getCause();
    269             throw new DocumentException(cause.getMessage(), cause);
    270         }
    271     }
    272
    273     /***
    274      * Parses the specified {@link java.io.Reader}with SAX.
    275      *
    276      * @param source
    277      *            the reader to parse
    278      * @param systemId
    279      *            the URI of the given reader
    280      *
    281      * @return the resulting DOM4J document
    282      *
    283      * @throws DocumentException
    284      *             when an error occurs while parsing
    285      * @throws IOException
    286      *             when an error occurs while writing to the {@link
    287      *             org.dom4j.io.XMLWriter}
    288      */
    289     public Document modify(Reader source, String systemId)
    290             throws DocumentException, IOException {
    291         try {
    292             return installModifier().modify(source);
    293         } catch (JAXBRuntimeException ex) {
    294             Throwable cause = ex.getCause();
    295             throw new DocumentException(cause.getMessage(), cause);
    296         }
    297     }
    298
    299     /***
    300      * Parses the the given URL or filename.
    301      *
    302      * @param url
    303      *            the URL or filename to parse
    304      *
    305      * @return the resulting DOM4J document
    306      *
    307      * @throws DocumentException
    308      *             when an error occurs while parsing
    309      * @throws IOException
    310      *             when an error occurs while writing to the {@link
    311      *             org.dom4j.io.XMLWriter}
    312      */
    313     public Document modify(String url) throws DocumentException, IOException {
    314         try {
    315             return installModifier().modify(url);
    316         } catch (JAXBRuntimeException ex) {
    317             Throwable cause = ex.getCause();
    318             throw new DocumentException(cause.getMessage(), cause);
    319         }
    320     }
    321
    322     /***
    323      * Parses the the given URL.
    324      *
    325      * @param source
    326      *            the URL to parse
    327      *
    328      * @return the resulting DOM4J document
    329      *
    330      * @throws DocumentException
    331      *             when an error occurs while parsing
    332      * @throws IOException
    333      *             when an error occurs while writing to the {@link
    334      *             org.dom4j.io.XMLWriter}
    335      */
    336     public Document modify(URL source) throws DocumentException, IOException {
    337         try {
    338             return installModifier().modify(source);
    339         } catch (JAXBRuntimeException ex) {
    340             Throwable cause = ex.getCause();
    341             throw new DocumentException(cause.getMessage(), cause);
    342         }
    343     }
    344
    345     /***
    346      * Sets the Output to write the (modified) xml document to.
    347      *
    348      * @param file
    349      *            the {@link java.io.File}to write to
    350      *
    351      * @throws IOException
    352      *             when the file cannot be found or when the outputformat
    353      */
    354     public void setOutput(File file) throws IOException {
    355         createXMLWriter().setOutputStream(new FileOutputStream(file));
    356     }
    357
    358     /***
    359      * Sets the Output to write the (modified) xml document to.
    360      *
    361      * @param outputStream
    362      *            the {@link java.io.OutputStream}to write to
    363      *
    364      * @throws IOException
    365      *             when an error occurs
    366      */
    367     public void setOutput(OutputStream outputStream) throws IOException {
    368         createXMLWriter().setOutputStream(outputStream);
    369     }
    370
    371     /***
    372      * Sets the Output to write the (modified) xml document to.
    373      *
    374      * @param writer
    375      *            the {@link java.io.Writer}to write to
    376      *
    377      * @throws IOException
    378      *             when an error occurs
    379      */
    380     public void setOutput(Writer writer) throws IOException {
    381         createXMLWriter().setWriter(writer);
    382     }
    383
    384     /***
    385      * Adds the {@link JAXBObjectModifier}to be called when the specified xml
    386      * path is encounted while parsing the source.
    387      *
    388      * @param path
    389      *            the element path to listen for
    390      * @param mod
    391      *            the modifier to register
    392      */
    393     public void addObjectModifier(String path, JAXBObjectModifier mod) {
    394         modifiers.put(path, mod);
    395     }
    396
    397     /***
    398      * Removes the {@link JAXBObjectModifier}from the event based processor,
    399      * for the specified element path.
    400      *
    401      * @param path
    402      *            the xml path to remove the modifier for
    403      */
    404     public void removeObjectModifier(String path) {
    405         modifiers.remove(path);
    406         getModifier().removeModifier(path);
    407     }
    408
    409     /***
    410      * Removes all registered {@link JAXBObjectModifier}instances from the
    411      * event based processor.
    412      */
    413     public void resetObjectModifiers() {
    414         modifiers.clear();
    415         getModifier().resetModifiers();
    416     }
    417
    418     /***
    419      * Returns true when the modified {@link org.dom4j.Document}is not kept in
    420      * memory.
    421      *
    422      * @return Returns true if elements are pruned.
    423      */
    424     public boolean isPruneElements() {
    425         return pruneElements;
    426     }
    427
    428     /***
    429      * Define whether the modified {@link org.dom4j.Document}must only be
    430      * written to the output and pruned from the DOM4J tree.
    431      *
    432      * @param pruneElements
    433      *            When true, elements will not be kept in memory
    434      */
    435     public void setPruneElements(boolean pruneElements) {
    436         this.pruneElements = pruneElements;
    437     }
    438
    439     private SAXModifier installModifier() throws IOException {
    440         modifier = new SAXModifier(isPruneElements());
    441
    442         modifier.resetModifiers();
    443
    444         Iterator modifierIt = modifiers.entrySet().iterator();
    445
    446         while (modifierIt.hasNext()) {
    447             Map.Entry entry = (Map.Entry) modifierIt.next();
    448             ElementModifier mod = new JAXBElementModifier(this,
    449                     (JAXBObjectModifier) entry.getValue());
    450             getModifier().addModifier((String) entry.getKey(), mod);
    451         }
    452
    453         modifier.setXMLWriter(getXMLWriter());
    454
    455         return modifier;
    456     }
    457
    458     private SAXModifier getModifier() {
    459         if (this.modifier == null) {
    460             modifier = new SAXModifier(isPruneElements());
    461         }
    462
    463         return modifier;
    464     }
    465
    466     private XMLWriter getXMLWriter() {
    467         return xmlWriter;
    468     }
    469
    470     private XMLWriter createXMLWriter() throws IOException {
    471         if (this.xmlWriter == null) {
    472             xmlWriter = new XMLWriter(outputFormat);
    473         }
    474
    475         return xmlWriter;
    476     }
    477
    478     private class JAXBElementModifier implements ElementModifier {
    479         private JAXBModifier jaxbModifier;
    480
    481         private JAXBObjectModifier objectModifier;
    482
    483         public JAXBElementModifier(JAXBModifier jaxbModifier,
    484                 JAXBObjectModifier objectModifier) {
    485             this.jaxbModifier = jaxbModifier;
    486             this.objectModifier = objectModifier;
    487         }
    488
    489         public org.dom4j.Element modifyElement(org.dom4j.Element element)
    490                 throws Exception {
    491             javax.xml.bind.Element originalObject = jaxbModifier
    492                     .unmarshal(element);
    493             javax.xml.bind.Element modifiedObject = objectModifier
    494                     .modifyObject(originalObject);
    495
    496             return jaxbModifier.marshal(modifiedObject);
    497         }
    498     }
    499 }
    500
    501 /*
    502  * Redistribution and use of this software and associated documentation
    503  * ("Software"), with or without modification, are permitted provided that the
    504  * following conditions are met:
    505  *
    506  * 1. Redistributions of source code must retain copyright statements and
    507  * notices. Redistributions must also contain a copy of this document.
    508  *
    509  * 2. Redistributions in binary form must reproduce the above copyright notice,
    510  * this list of conditions and the following disclaimer in the documentation
    511  * and/or other materials provided with the distribution.
    512  *
    513  * 3. The name "DOM4J" must not be used to endorse or promote products derived
    514  * from this Software without prior written permission of MetaStuff, Ltd. For
    515  * written permission, please contact dom4j-info@metastuff.com.
    516  *
    517  * 4. Products derived from this Software may not be called "DOM4J" nor may
    518  * "DOM4J" appear in their names without prior written permission of MetaStuff,
    519  * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
    520  *
    521  * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
    522  *
    523  * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
    524  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    525  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    526  * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
    527  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    528  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    529  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    530  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    531  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    532  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    533  * POSSIBILITY OF SUCH DAMAGE.
    534  *
    535  * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
    536  */