1 /* 2 * Copyright (c) 2015, 2016, 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 catalog; 24 25 import java.io.IOException; 26 import javax.xml.catalog.Catalog; 27 import javax.xml.catalog.CatalogFeatures; 28 import javax.xml.catalog.CatalogFeatures.Feature; 29 import javax.xml.catalog.CatalogManager; 30 import javax.xml.catalog.CatalogResolver; 31 import javax.xml.catalog.CatalogUriResolver; 32 import javax.xml.parsers.ParserConfigurationException; 33 import javax.xml.parsers.SAXParser; 34 import javax.xml.parsers.SAXParserFactory; 35 import org.testng.Assert; 36 import org.testng.annotations.DataProvider; 37 import org.testng.annotations.Test; 38 import org.xml.sax.Attributes; 39 import org.xml.sax.ErrorHandler; 40 import org.xml.sax.SAXException; 41 import org.xml.sax.XMLReader; 42 import org.xml.sax.ext.DefaultHandler2; 43 44 /* 45 * @bug 8081248, 8144966, 8146606, 8146237, 8151154 46 * @summary Tests basic Catalog functions. 47 */ 48 public class CatalogTest { 49 /** 50 * @bug 8151154 51 * Verifies that the CatalogFeatures' builder throws IllegalArgumentException 52 * on invalid file inputs. 53 * @param file the file path 54 */ 55 @Test(dataProvider = "invalidPaths", expectedExceptions = IllegalArgumentException.class) 56 public void testFileInput(String file) { 57 CatalogFeatures features = CatalogFeatures.builder() 58 .with(CatalogFeatures.Feature.FILES, file) 59 .build(); 60 } 61 62 /** 63 * @bug 8146237 64 * PREFER from Features API taking precedence over catalog file 65 */ 66 @Test 67 public void testJDK8146237() { 68 String catalogFile = getClass().getResource("JDK8146237_catalog.xml").getFile(); 69 70 try { 71 CatalogFeatures features = CatalogFeatures.builder().with(CatalogFeatures.Feature.PREFER, "system").build(); 72 Catalog catalog = CatalogManager.catalog(features, catalogFile); 73 CatalogResolver catalogResolver = CatalogManager.catalogResolver(catalog); 74 String actualSystemId = catalogResolver.resolveEntity("-//FOO//DTD XML Dummy V0.0//EN", "http://www.oracle.com/alt1sys.dtd").getSystemId(); 75 Assert.assertTrue(actualSystemId.contains("dummy.dtd"), "Resulting id should contain dummy.dtd, indicating a match by publicId"); 76 77 } catch (Exception e) { 78 Assert.fail(e.getMessage()); 79 } 80 } 81 82 /* 83 @bug 8146606 84 Verifies that the resulting systemId does not contain duplicate slashes 85 */ 86 @Test 87 public void testRewriteSystem() { 88 String catalog = getClass().getResource("rewriteCatalog.xml").getFile(); 89 90 try { 91 CatalogResolver resolver = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalog); 92 String actualSystemId = resolver.resolveEntity(null, "http://remote.com/dtd/book.dtd").getSystemId(); 93 Assert.assertTrue(!actualSystemId.contains("//"), "result contains duplicate slashes"); 94 } catch (Exception e) { 95 Assert.fail(e.getMessage()); 96 } 97 98 } 99 100 /* 101 @bug 8146606 102 Verifies that the resulting systemId does not contain duplicate slashes 103 */ 104 @Test 105 public void testRewriteUri() { 106 String catalog = getClass().getResource("rewriteCatalog.xml").getFile(); 107 108 try { 109 110 CatalogUriResolver resolver = CatalogManager.catalogUriResolver(CatalogFeatures.defaults(), catalog); 111 String actualSystemId = resolver.resolve("http://remote.com/import/import.xsl", null).getSystemId(); 112 Assert.assertTrue(!actualSystemId.contains("//"), "result contains duplicate slashes"); 113 } catch (Exception e) { 114 Assert.fail(e.getMessage()); 115 } 116 } 117 118 /* 119 @bug 8144966 120 Verifies that passing null as CatalogFeatures will result in a NPE. 121 */ 122 @Test(expectedExceptions = NullPointerException.class) 123 public void testFeatureNull() { 124 CatalogResolver resolver = CatalogManager.catalogResolver(null, ""); 125 126 } 127 128 /* 129 @bug 8144966 130 Verifies that passing null as the path will result in a NPE. 131 */ 132 @Test(expectedExceptions = NullPointerException.class) 133 public void testPathNull() { 134 String path = null; 135 CatalogResolver resolver = CatalogManager.catalogResolver(CatalogFeatures.defaults(), path); 136 } 137 138 /* 139 Tests basic catalog feature by using a CatalogResolver instance to 140 resolve a DTD reference to a locally specified DTD file. If the resolution 141 is successful, the Handler shall return the value of the entity reference 142 that matches the expected value. 143 */ 144 @Test(dataProvider = "catalog") 145 public void testCatalogResolver(String test, String expected, String catalogFile, String xml, SAXParser saxParser) { 146 String catalog = null; 147 if (catalogFile != null) { 148 catalog = getClass().getResource(catalogFile).getFile(); 149 } 150 String url = getClass().getResource(xml).getFile(); 151 try { 152 CatalogResolver cr = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalog); 153 XMLReader reader = saxParser.getXMLReader(); 154 reader.setEntityResolver(cr); 155 MyHandler handler = new MyHandler(saxParser); 156 reader.setContentHandler(handler); 157 reader.parse(url); 158 System.out.println(test + ": expected [" + expected + "] <> actual [" + handler.getResult() + "]"); 159 Assert.assertEquals(handler.getResult(), expected); 160 } catch (SAXException | IOException e) { 161 Assert.fail(e.getMessage()); 162 } 163 } 164 165 /* 166 Verifies that when there's no match, in this case only an invalid 167 catalog is provided, the resolver will throw an exception by default. 168 */ 169 @Test 170 public void testInvalidCatalog() { 171 String catalog = getClass().getResource("catalog_invalid.xml").getFile(); 172 173 String test = "testInvalidCatalog"; 174 try { 175 CatalogResolver resolver = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalog); 176 String actualSystemId = resolver.resolveEntity(null, "http://remote/xml/dtd/sys/alice/docAlice.dtd").getSystemId(); 177 } catch (Exception e) { 178 String msg = e.getMessage(); 179 if (msg != null) { 180 if (msg.contains("No match found for publicId")) { 181 Assert.assertEquals(msg, "No match found for publicId 'null' and systemId 'http://remote/xml/dtd/sys/alice/docAlice.dtd'."); 182 System.out.println(test + ": expected [No match found for publicId 'null' and systemId 'http://remote/xml/dtd/sys/alice/docAlice.dtd'.]"); 183 System.out.println("actual [" + msg + "]"); 184 } 185 } 186 } 187 } 188 189 /* 190 Verifies that if resolve is "ignore", an empty InputSource will be returned 191 when there's no match. The systemId is then null. 192 */ 193 @Test 194 public void testIgnoreInvalidCatalog() { 195 String catalog = getClass().getResource("catalog_invalid.xml").getFile(); 196 CatalogFeatures f = CatalogFeatures.builder() 197 .with(Feature.FILES, catalog) 198 .with(Feature.PREFER, "public") 199 .with(Feature.DEFER, "true") 200 .with(Feature.RESOLVE, "ignore") 201 .build(); 202 203 String test = "testInvalidCatalog"; 204 try { 205 CatalogResolver resolver = CatalogManager.catalogResolver(f, ""); 206 String actualSystemId = resolver.resolveEntity(null, "http://remote/xml/dtd/sys/alice/docAlice.dtd").getSystemId(); 207 System.out.println("testIgnoreInvalidCatalog: expected [null]"); 208 System.out.println("testIgnoreInvalidCatalog: expected [null]"); 209 System.out.println("actual [" + actualSystemId + "]"); 210 Assert.assertEquals(actualSystemId, null); 211 } catch (Exception e) { 212 Assert.fail(e.getMessage()); 213 } 214 } 215 216 /* 217 DataProvider: for testing the verification of file paths by 218 the CatalogFeatures builder 219 */ 220 @DataProvider(name = "invalidPaths") 221 Object[][] getFiles() { 222 return new Object[][]{ 223 {null}, 224 {""}, 225 {"file:a/b\\c"}, 226 {"file:/../../.."}, 227 {"c:/te:t"}, 228 {"c:/te?t"}, 229 {"c/te*t"}, 230 {"in|valid.txt"}, 231 {"shema:invalid.txt"}, 232 }; 233 } 234 235 /* 236 DataProvider: provides test name, expected string, the catalog, and XML 237 document. 238 */ 239 @DataProvider(name = "catalog") 240 Object[][] getCatalog() { 241 return new Object[][]{ 242 {"testSystem", "Test system entry", "catalog.xml", "system.xml", getParser()}, 243 {"testRewriteSystem", "Test rewritesystem entry", "catalog.xml", "rewritesystem.xml", getParser()}, 244 {"testRewriteSystem1", "Test rewritesystem entry", "catalog.xml", "rewritesystem1.xml", getParser()}, 245 {"testSystemSuffix", "Test systemsuffix entry", "catalog.xml", "systemsuffix.xml", getParser()}, 246 {"testDelegateSystem", "Test delegatesystem entry", "catalog.xml", "delegatesystem.xml", getParser()}, 247 {"testPublic", "Test public entry", "catalog.xml", "public.xml", getParser()}, 248 {"testDelegatePublic", "Test delegatepublic entry", "catalog.xml", "delegatepublic.xml", getParser()}, 249 }; 250 } 251 252 SAXParser getParser() { 253 SAXParser saxParser = null; 254 try { 255 SAXParserFactory factory = SAXParserFactory.newInstance(); 256 factory.setNamespaceAware(true); 257 saxParser = factory.newSAXParser(); 258 } catch (ParserConfigurationException | SAXException e) { 259 } 260 261 return saxParser; 262 } 263 264 265 /** 266 * SAX handler 267 */ 268 public class MyHandler extends DefaultHandler2 implements ErrorHandler { 269 270 StringBuilder textContent = new StringBuilder(); 271 SAXParser saxParser; 272 273 MyHandler(SAXParser saxParser) { 274 textContent.setLength(0); 275 this.saxParser = saxParser; 276 } 277 278 String getResult() { 279 return textContent.toString(); 280 } 281 282 @Override 283 public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { 284 textContent.delete(0, textContent.length()); 285 try { 286 System.out.println("Element: " + uri + ":" + localName + " " + qName); 287 } catch (Exception e) { 288 throw new SAXException(e); 289 } 290 291 } 292 293 @Override 294 public void characters(char ch[], int start, int length) throws SAXException { 295 textContent.append(ch, start, length); 296 } 297 } 298 }