1 /*
   2  * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package test.astro;
  24 
  25 import static jaxp.library.JAXPTestUtilities.USER_DIR;
  26 import static jaxp.library.JAXPTestUtilities.filenameToURL;
  27 import static org.w3c.dom.ls.DOMImplementationLS.MODE_SYNCHRONOUS;
  28 import static org.w3c.dom.traversal.NodeFilter.SHOW_ELEMENT;
  29 
  30 import java.io.ByteArrayInputStream;
  31 import java.io.FileReader;
  32 import java.io.FileWriter;
  33 import java.io.InputStreamReader;
  34 import java.io.Reader;
  35 import java.nio.file.Files;
  36 import java.nio.file.Paths;
  37 
  38 import javax.xml.parsers.DocumentBuilder;
  39 import javax.xml.parsers.DocumentBuilderFactory;
  40 
  41 import org.w3c.dom.DOMConfiguration;
  42 import org.w3c.dom.Document;
  43 import org.w3c.dom.Element;
  44 import org.w3c.dom.Node;
  45 import org.w3c.dom.ls.DOMImplementationLS;
  46 import org.w3c.dom.ls.LSInput;
  47 import org.w3c.dom.ls.LSParser;
  48 import org.w3c.dom.ls.LSParserFilter;
  49 import org.w3c.dom.ls.LSSerializer;
  50 import org.w3c.dom.ls.LSSerializerFilter;
  51 import org.xml.sax.InputSource;
  52 
  53 /*
  54  * A specialized implementation of an Input Source factory that utilizes
  55  * DOM Level 3 implementations to build a Document (DOM) from the
  56  * astro input file (XML) and then will serialize the DOM. The serialized DOM
  57  * of the astro input file is then used to create the sax InputSource
  58  * and set it's system id. It is then returned to the caller.
  59  *
  60  */
  61 public class DOML3InputSourceFactoryImpl implements InputSourceFactory {
  62     public InputSource newInputSource(String filename) throws Exception {
  63         // Create DOMImplementationLS, and DOM L3 LSParser
  64         DocumentBuilderFactory fact = DocumentBuilderFactory.newInstance();
  65         DocumentBuilder bldr = fact.newDocumentBuilder();
  66         DOMImplementationLS impl = (DOMImplementationLS) bldr.getDOMImplementation();
  67         LSParser domparser = impl.createLSParser(MODE_SYNCHRONOUS, null);
  68         domparser.setFilter(new MyDOMBuilderFilter());
  69 
  70         // Parse the xml document to create the DOM Document using
  71         // the DOM L3 LSParser and a LSInput (formerly LSInputSource)
  72         Document doc = null;
  73         LSInput src = impl.createLSInput();
  74         // register the input file with the input source...
  75         String systemId = filenameToURL(filename);
  76         src.setSystemId(systemId);
  77         try (Reader reader = new FileReader(filename)) {
  78             src.setCharacterStream(reader);
  79             src.setEncoding("UTF-8");
  80             doc = domparser.parse(src);
  81         }
  82 
  83         // Use DOM L3 LSSerializer (previously called a DOMWriter)
  84         // to serialize the xml doc DOM to a file stream.
  85         String tmpCatalog = Files.createTempFile(Paths.get(USER_DIR + "/astro"), "catalog.xml", null).toString();
  86 
  87         LSSerializer domserializer = impl.createLSSerializer();
  88         domserializer.setFilter(new MyDOMWriterFilter());
  89         domserializer.getNewLine();
  90         DOMConfiguration config = domserializer.getDomConfig();
  91         config.setParameter("xml-declaration", Boolean.TRUE);
  92         String result = domserializer.writeToString(doc);
  93         try (FileWriter os = new FileWriter(tmpCatalog, false)) {
  94             os.write(result);
  95             os.flush();
  96         }
  97 
  98         // Return the Input Source created from the Serialized DOM L3 Document.
  99         InputSource catsrc = new InputSource(new InputStreamReader(new ByteArrayInputStream(Files.readAllBytes(Paths.get(tmpCatalog)))));
 100         catsrc.setSystemId(systemId);
 101         return catsrc;
 102     }
 103 
 104     /*
 105      * Implementation of a DOM L3 DOM Builder Filter. The filter is capable of
 106      * examining nodes as they are available during the parse. This
 107      * implementation both rejects (filters) and modifies particular nodes
 108      * during the parse of the document. As such, the document in memory will
 109      * become a subset of the document on the stream in accordance with the DOM
 110      * Level 3 Load and Save Specification, v1.0, sect. 1.3 Load Interfaces.
 111      */
 112     private static class MyDOMBuilderFilter implements LSParserFilter {
 113 
 114         /*
 115          * Filter the DOM. Define element(s) and their children that should be
 116          * efficiently skipped thereby filtering them out of the stream.
 117          */
 118         @Override
 119         public short startElement(Element e) {
 120             return "_test01".equals(e.getTagName()) ? FILTER_REJECT : FILTER_ACCEPT;
 121         }
 122 
 123         /*
 124          * Modify the DOM 'in situ'. Find a particular Node and change the Node
 125          * value of its child, allow other nodes to pass through unchanged.
 126          */
 127         @Override
 128         public short acceptNode(Node n) {
 129             String localname = n.getLocalName();
 130             if (localname.equals("_test-04")) {
 131                 Node child = n.getFirstChild();
 132                 String text = child.getNodeValue();
 133                 if (text.equals("T%e!s#t$")) {
 134                     child.setNodeValue("T%E!S#T$");
 135                 }
 136             }
 137             return FILTER_ACCEPT;
 138         }
 139 
 140         /*
 141          * Tells the DOMBuilder what types of nodes to show to the filter.
 142          */
 143         @Override
 144         public int getWhatToShow() {
 145             return SHOW_ELEMENT;
 146         }
 147     }
 148 
 149     /*
 150      * Implementation of a DOM Serializer Filter (previously called a DOM Writer
 151      * Filter) which is a specialization of the NodeFilter interface.
 152      */
 153     private static class MyDOMWriterFilter implements LSSerializerFilter {
 154         public MyDOMWriterFilter() {
 155         }
 156 
 157         /*
 158          * Must implement method from NodeFilter interface
 159          */
 160         @Override
 161         public short acceptNode(Node node) {
 162             return FILTER_ACCEPT;
 163         }
 164 
 165         /*
 166          * Tells the DOMBuilder what types of nodes to show to the filter.
 167          */
 168         @Override
 169         public int getWhatToShow() {
 170             return SHOW_ELEMENT;
 171         }
 172     }
 173 }