1/*
2 * Copyright (c) 2014, 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
24package stream.XMLStreamReaderTest;
25
26import java.io.File;
27import java.io.FileInputStream;
28import java.io.StringReader;
29import java.util.List;
30
31import javax.xml.stream.XMLEventReader;
32import javax.xml.stream.XMLInputFactory;
33import javax.xml.stream.XMLStreamConstants;
34import javax.xml.stream.events.Characters;
35import javax.xml.stream.events.DTD;
36import javax.xml.stream.events.EntityDeclaration;
37import javax.xml.stream.events.EntityReference;
38import javax.xml.stream.events.XMLEvent;
39
40import org.testng.Assert;
41import org.testng.annotations.Listeners;
42import org.testng.annotations.Test;
43
44/*
45 * @test
46 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
47 * @run testng/othervm -DrunSecMngr=true stream.XMLStreamReaderTest.SupportDTDTest
48 * @run testng/othervm stream.XMLStreamReaderTest.SupportDTDTest
49 * @summary Test SUPPORT_DTD and IS_REPLACING_ENTITY_REFERENCES.
50 */
51
52/**
53*
54* SUPPORT_DTD behavior:
55* Regardless of supportDTD, always report a DTD event () and throw an
56* exception if an entity reference is found when supportDTD is false
57*
58* The behavior is related to property IS_REPLACING_ENTITY_REFERENCES.
59*
60* SUPPORT_DTD      Replace Entity   DTD                    ENTITY_REFERENCE
61* true (default)   true (default)   yes, has entities      no, return Characters
62* true (default)   false            yes, has entities      yes, can print entity name
63* false            true (default)   yes, but no entity     Exception: Undeclared general entity
64* false            false            yes, but no entity     yes, can print entity name
65*
66* Two patches related:
67* sjsxp issue 9: XMLDocumentScannerImpl.java rev 1.6
68* If the supportDTD property is set to FALSE, external and internal subsets
69* are now ignored, rather than an error being reported. In particular, with
70* this property set to FALSE, no error is reported if an external subset cannot
71* be found. Note that the internal subset is still parsed (and errors could be
72* reported here) but no events are returned by the parser. This fixes SJSXP
73* issue 9 from Java.net.
74* Note: SAX and DOM report fatal errors:
75*       If either SAX or DOM is used, turning on http://apache.org/xml/features/disallow-doctype-decl [1] effectively disables DTD,
76*       according to the spec: A fatal error is thrown if the incoming document contains a DOCTYPE declaration.
77*       The current jaxp implementation actually throws a nullpointexception. A better error message could be used.
78*
79*/
80@Listeners({jaxp.library.FilePolicy.class})
81public class SupportDTDTest {
82    final boolean DEBUG = false;
83    final String _file = "ExternalDTD.xml";
84    final String XML = "<?xml version='1.0' ?>" + "<!DOCTYPE root [\n" + "<!ENTITY intEnt 'internal entity'>\n" + "<!ENTITY extParsedEnt SYSTEM 'url:dummy'>\n"
85            + "<!NOTATION notation PUBLIC 'notation-public-id'>\n" + "<!NOTATION notation2 SYSTEM 'url:dummy'>\n"
86            + "<!ENTITY extUnparsedEnt SYSTEM 'url:dummy2' NDATA notation>\n" + "]>" + "<root>&intEnt;</root>";
87
88    final String XML1 = "<?xml version='1.0' encoding ='utf-8'?>" + "<!DOCTYPE document SYSTEM \"" + this.getClass().getResource("ExternalDTD.dtd").getFile()
89            + "\">" + "<document>" + "<name>&mkm;</name>" + "</document>";
90
91   // final String XML1 = "<?xml version='1.0' encoding ='utf-8'?>" + "<!DOCTYPE document SYSTEM \"/home/oracle/repo/xmlwork/dev/jdk/test/javax/xml/jaxp/unittest/javax/xml/stream/XMLStreamReaderTest/ExternalDTD.dtd\">" + "<document>"
92   //         + "<name>&mkm;</name>" + "</document>";
93
94    final int ENTITY_INTERNAL_ONLY = 1;
95    final int ENTITY_EXTERNAL_ONLY = 2;
96    final int ENTITY_BOTH = 3;
97
98    boolean _DTDReturned = false;
99    boolean _EntityEventReturned = false;
100    boolean _hasEntityDelaration = false;
101    boolean _exceptionThrown = false;
102
103    /** Creates a new instance of StreamReader */
104    public SupportDTDTest(String name) {
105    }
106
107    void reset() {
108        _DTDReturned = false;
109        _EntityEventReturned = false;
110        _hasEntityDelaration = false;
111        _exceptionThrown = false;
112    }
113
114    // tests 1-4 test internal entities only
115    @Test
116    public void test1() {
117        supportDTD(true, true, ENTITY_INTERNAL_ONLY);
118        Assert.assertEquals(true, _DTDReturned);
119        Assert.assertEquals(true, _hasEntityDelaration);
120        Assert.assertEquals(false, _EntityEventReturned);
121    }
122
123    @Test
124    public void test2() {
125        supportDTD(true, false, ENTITY_INTERNAL_ONLY);
126        Assert.assertEquals(true, _DTDReturned);
127        Assert.assertEquals(true, _hasEntityDelaration);
128        Assert.assertEquals(true, _EntityEventReturned);
129    }
130
131    @Test
132    public void test3() {
133        supportDTD(false, true, ENTITY_INTERNAL_ONLY);
134        Assert.assertEquals(true, _DTDReturned);
135        Assert.assertEquals(false, _hasEntityDelaration);
136        Assert.assertEquals(true, _exceptionThrown);
137    }
138
139    @Test
140    public void test4() {
141        supportDTD(false, false, ENTITY_INTERNAL_ONLY);
142        Assert.assertEquals(true, _DTDReturned);
143        Assert.assertEquals(false, _hasEntityDelaration);
144        Assert.assertEquals(true, _EntityEventReturned);
145    }
146
147    // tests 5-8 test external entities only
148    @Test
149    public void test5() {
150        supportDTD(true, true, ENTITY_EXTERNAL_ONLY);
151        Assert.assertEquals(true, _DTDReturned);
152        Assert.assertEquals(true, _hasEntityDelaration);
153        Assert.assertEquals(false, _EntityEventReturned);
154    }
155
156    @Test
157    public void test6() {
158        supportDTD(true, false, ENTITY_EXTERNAL_ONLY);
159        Assert.assertEquals(true, _DTDReturned);
160        Assert.assertEquals(true, _hasEntityDelaration);
161        Assert.assertEquals(true, _EntityEventReturned);
162    }
163
164    @Test
165    public void test7() {
166        supportDTD(false, true, ENTITY_EXTERNAL_ONLY);
167        Assert.assertEquals(true, _DTDReturned);
168        Assert.assertEquals(false, _hasEntityDelaration);
169        Assert.assertEquals(true, _exceptionThrown);
170    }
171
172    @Test
173    public void test8() {
174        supportDTD(false, false, ENTITY_EXTERNAL_ONLY);
175        Assert.assertEquals(true, _DTDReturned);
176        Assert.assertEquals(false, _hasEntityDelaration);
177        Assert.assertEquals(true, _EntityEventReturned);
178    }
179
180    // tests 9-12 test both internal and external entities
181    @Test
182    public void test9() {
183        supportDTD(true, true, ENTITY_BOTH);
184        Assert.assertEquals(true, _DTDReturned);
185        Assert.assertEquals(true, _hasEntityDelaration);
186        Assert.assertEquals(false, _EntityEventReturned);
187    }
188
189    @Test
190    public void test10() {
191        supportDTD(true, false, ENTITY_BOTH);
192        Assert.assertEquals(true, _DTDReturned);
193        Assert.assertEquals(true, _hasEntityDelaration);
194        Assert.assertEquals(true, _EntityEventReturned);
195    }
196
197    @Test
198    public void test11() {
199        supportDTD(false, true, ENTITY_BOTH);
200        Assert.assertEquals(true, _DTDReturned);
201        Assert.assertEquals(false, _hasEntityDelaration);
202        Assert.assertEquals(true, _exceptionThrown);
203    }
204
205    @Test
206    public void test12() {
207        supportDTD(false, false, ENTITY_BOTH);
208        Assert.assertEquals(true, _DTDReturned);
209        Assert.assertEquals(false, _hasEntityDelaration);
210        Assert.assertEquals(true, _EntityEventReturned);
211    }
212
213    public void supportDTD(boolean supportDTD, boolean replaceEntity, int inputType) {
214        reset();
215        print("\n");
216        print((supportDTD ? "SupportDTD=true" : "SupportDTD=false") + ", " + (replaceEntity ? "replaceEntity=true" : "replaceEntity=false"));
217        try {
218            XMLInputFactory xif = getFactory(supportDTD, replaceEntity);
219            XMLEventReader r = getEventReader(xif, inputType);
220            int eventType = 0;
221            int count = 0;
222            while (r.hasNext()) {
223                XMLEvent event = r.nextEvent();
224                eventType = event.getEventType();
225                print("Event " + ++count + ": " + eventType);
226                switch (eventType) {
227                    case XMLStreamConstants.DTD:
228                        DisplayEntities((DTD) event);
229                        _DTDReturned = true;
230                        break;
231                    case XMLStreamConstants.ENTITY_REFERENCE:
232                        print("Entity Name: " + ((EntityReference) event).getName());
233                        _EntityEventReturned = true;
234                        break;
235                    case XMLStreamConstants.CHARACTERS:
236                        print("Text: " + ((Characters) event).getData());
237                }
238            }
239
240        } catch (Exception e) {
241            _exceptionThrown = true;
242            if (DEBUG)
243                e.printStackTrace();
244        }
245    }
246
247    XMLInputFactory getFactory(boolean supportDTD, boolean replaceEntity) {
248        XMLInputFactory xif = XMLInputFactory.newInstance();
249        xif.setProperty(XMLInputFactory.SUPPORT_DTD, (supportDTD) ? Boolean.TRUE : Boolean.FALSE);
250        xif.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, (replaceEntity) ? Boolean.TRUE : Boolean.FALSE);
251        // xif.setProperty(XMLInputFactory.IS_VALIDATING, Boolean.TRUE);
252        return xif;
253    }
254
255    private XMLEventReader getEventReader(XMLInputFactory inputFactory, int input) throws Exception {
256        XMLEventReader er = null;
257        if (input == ENTITY_INTERNAL_ONLY) {
258            er = inputFactory.createXMLEventReader(new StringReader(XML));
259        } else if (input == ENTITY_EXTERNAL_ONLY) {
260            er = inputFactory.createXMLEventReader(new StringReader(XML1));
261        } else {
262            File file = new File(this.getClass().getResource(_file).getFile());
263            FileInputStream inputStream = new FileInputStream(file);
264            // XMLStreamReader r = xif.createXMLStreamReader(inputStream);
265            er = inputFactory.createXMLEventReader(inputStream);
266        }
267        return er;
268    }
269
270    void DisplayEntities(DTD event) {
271        List entities = event.getEntities();
272        if (entities == null) {
273            _hasEntityDelaration = false;
274            print("No entity found.");
275        } else {
276            _hasEntityDelaration = true;
277            for (int i = 0; i < entities.size(); i++) {
278                EntityDeclaration entity = (EntityDeclaration) entities.get(i);
279                print(entity.getName());
280            }
281        }
282
283    }
284
285    void print(String s) {
286        if (DEBUG)
287            System.out.println(s);
288    }
289
290}
291