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.filenameToURL;
26 import static jaxp.library.JAXPTestUtilities.USER_DIR;
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 {
newInputSource(String filename)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), "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
startElement(Element e)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
acceptNode(Node n)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
getWhatToShow()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 {
MyDOMWriterFilter()154         public MyDOMWriterFilter() {
155         }
156 
157         /*
158          * Must implement method from NodeFilter interface
159          */
160         @Override
acceptNode(Node node)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
getWhatToShow()169         public int getWhatToShow() {
170             return SHOW_ELEMENT;
171         }
172     }
173 }
174