1 /*
   2  * Copyright (c) 2017, 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.BufferedOutputStream;
  26 import java.io.BufferedReader;
  27 import java.io.BufferedWriter;
  28 import java.io.File;
  29 import java.io.IOException;
  30 import java.io.InputStream;
  31 import java.io.InputStreamReader;
  32 import java.io.OutputStream;
  33 import java.io.OutputStreamWriter;
  34 import java.net.URI;
  35 import java.nio.file.Files;
  36 import java.nio.file.Path;
  37 import java.nio.file.Paths;
  38 import static java.nio.file.StandardOpenOption.APPEND;
  39 import static java.nio.file.StandardOpenOption.CREATE;
  40 import javax.xml.catalog.Catalog;
  41 import javax.xml.catalog.CatalogException;
  42 import javax.xml.catalog.CatalogFeatures;
  43 import javax.xml.catalog.CatalogManager;
  44 import javax.xml.catalog.CatalogResolver;
  45 import static jaxp.library.JAXPTestUtilities.getSystemProperty;
  46 import jaxp.library.JarUtils;
  47 import jaxp.library.SimpleHttpServer;
  48 import org.testng.Assert;
  49 import org.testng.annotations.AfterClass;
  50 import org.testng.annotations.BeforeClass;
  51 import org.testng.annotations.DataProvider;
  52 import org.testng.annotations.Listeners;
  53 import org.testng.annotations.Test;
  54 import org.xml.sax.InputSource;
  55 
  56 /*
  57  * @test
  58  * @bug 8151154 8171243
  59  * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
  60  * @run testng/othervm catalog.CatalogFileInputTest
  61  * @summary Verifies that the Catalog API accepts valid URIs only;
  62             Verifies that the CatalogFeatures' builder throws
  63  *          IllegalArgumentException on invalid file inputs.
  64  *          This test was splitted from CatalogTest.java due to
  65  *          JDK-8168968, it has to only run without SecurityManager
  66  *          because an ACE will be thrown for invalid path.
  67  */
  68 @Listeners({jaxp.library.FilePolicy.class, jaxp.library.NetAccessPolicy.class})
  69 public class CatalogFileInputTest extends CatalogSupportBase {
  70 
  71     static final CatalogFeatures FEATURES = CatalogFeatures.builder().
  72             with(CatalogFeatures.Feature.PREFER, "system").build();
  73     static String USER_DIR = getSystemProperty("user.dir");
  74     static String CLS_DIR = getSystemProperty("test.classes");
  75     static String SRC_DIR = System.getProperty("test.src");
  76     static String JAR_CONTENT = "META-INF";
  77     final static String SCHEME_JARFILE = "jar:";
  78     static final String REMOTE_FILE_LOCATION = "/jar/META-INF";
  79     static final String DOCROOT = SRC_DIR;
  80     static final String TESTCONTEXT = REMOTE_FILE_LOCATION;  //mapped to local file path
  81     SimpleHttpServer _httpserver;
  82     String _remoteFilePath;
  83 
  84     /*
  85      * Initializing fields
  86      */
  87     @BeforeClass
  88     public void setUpClass() throws Exception {
  89         super.setUp();
  90 
  91         // set up HttpServer
  92         _httpserver = new SimpleHttpServer(TESTCONTEXT, DOCROOT);
  93         _httpserver.start();
  94         _remoteFilePath = _httpserver.getAddress() + REMOTE_FILE_LOCATION;
  95 
  96     }
  97 
  98     @AfterClass
  99     protected void tearDown() throws Exception {
 100         if (_httpserver != null) {
 101             _httpserver.stop();
 102         }
 103     }
 104 
 105     /*
 106      * Verifies that the Catalog can be created with file system paths including JAR
 107      * and http URL, and used to resolve a systemId as expected.
 108      */
 109     @Test(dataProvider = "acceptedURI")
 110     public void testMatch(String uri, String sysId, String pubId,
 111             String expectedId, String msg) throws Exception {
 112         CatalogResolver cr = CatalogManager.catalogResolver(FEATURES, URI.create(uri));
 113         InputSource is = cr.resolveEntity(pubId, sysId);
 114         Assert.assertNotNull(is, msg);
 115         Assert.assertEquals(expectedId, is.getSystemId(), msg);
 116     }
 117 
 118     @Test(dataProvider = "invalidCatalog")
 119     public void testEmptyCatalog(String uri, String publicId, String msg) {
 120         Catalog c = CatalogManager.catalog(FEATURES, uri != null? URI.create(uri) : null);
 121         Assert.assertNull(c.matchSystem(publicId), msg);
 122     }
 123 
 124     @Test(dataProvider = "invalidCatalog", expectedExceptions = CatalogException.class)
 125     public void testCatalogResolverWEmptyCatalog(String uri, String publicId, String msg) {
 126         CatalogResolver cr = CatalogManager.catalogResolver(
 127                 CatalogFeatures.builder().with(CatalogFeatures.Feature.RESOLVE, "strict").build(),
 128                 uri != null? URI.create(uri) : null);
 129         InputSource is = cr.resolveEntity(publicId, "");
 130     }
 131 
 132     @Test(dataProvider = "invalidCatalog")
 133     public void testCatalogResolverWEmptyCatalog1(String uri, String publicId, String msg) {
 134         CatalogResolver cr = CatalogManager.catalogResolver(
 135                 CatalogFeatures.builder().with(CatalogFeatures.Feature.RESOLVE, "continue").build(),
 136                 uri != null? URI.create(uri) : null);
 137         Assert.assertNull(cr.resolveEntity(publicId, ""), msg);
 138     }
 139 
 140     @Test(dataProvider = "invalidInput", expectedExceptions = IllegalArgumentException.class)
 141     public void testFileInput(String file) {
 142         CatalogFeatures features = CatalogFeatures.builder()
 143             .with(CatalogFeatures.Feature.FILES, file)
 144             .build();
 145     }
 146 
 147     @Test(dataProvider = "invalidInput", expectedExceptions = IllegalArgumentException.class)
 148     public void testInvalidUri(String file) {
 149         CatalogResolver cr = CatalogManager.catalogResolver(FEATURES, file != null? URI.create(file) : null);
 150     }
 151 
 152     @Test(dataProvider = "invalidInput", expectedExceptions = IllegalArgumentException.class)
 153     public void testInvalidUri1(String file) {
 154         Catalog c = CatalogManager.catalog(FEATURES, file != null? URI.create(file) : null);
 155         System.err.println("Catalog =" + c);
 156     }
 157 
 158 
 159     @Test(expectedExceptions = NullPointerException.class)
 160     public void testNullFileInput() {
 161         CatalogFeatures features = CatalogFeatures.builder()
 162             .with(CatalogFeatures.Feature.FILES, null)
 163             .build();
 164     }
 165 
 166     @Test(expectedExceptions = NullPointerException.class)
 167     public void testNullUri() {
 168         URI uri = null;
 169         CatalogResolver cr = CatalogManager.catalogResolver(FEATURES, uri);
 170     }
 171 
 172     @Test(expectedExceptions = NullPointerException.class)
 173     public void testNullUri1() {
 174         URI uri = null;
 175         Catalog c = CatalogManager.catalog(FEATURES, uri);
 176     }
 177 
 178     String systemId = "http://www.sys00test.com/rewrite.dtd";
 179     String publicId = "PUB-404";
 180     String expected = "http://www.groupxmlbase.com/dtds/rewrite.dtd";
 181     String errMsg = "Relative rewriteSystem with xml:base at group level failed";
 182 
 183     /*
 184         DataProvider: used to verify CatalogResolver's resolveEntity function.
 185         Data columns:
 186         catalog, systemId, publicId, expectedUri, msg
 187      */
 188     @DataProvider(name = "acceptedURI")
 189     Object[][] getData() throws Exception {
 190         String filename = "rewriteSystem_id.xml";
 191         String urlFile = getClass().getResource(filename).toExternalForm();
 192         String urlHttp = _remoteFilePath + "/jax-ws-catalog.xml";
 193         String remoteXSD = _remoteFilePath + "/catalog/ws-addr.xsd";
 194         File file = new File(CLS_DIR + "/JDK8171243.jar!/META-INF/jax-ws-catalog.xml");
 195         String jarPath = SCHEME_JARFILE + file.toURI().toString();
 196         String xsd = jarPath.substring(0, jarPath.lastIndexOf("/")) + "/catalog/ws-addr.xsd";
 197 
 198         // create JAR file
 199         try {
 200             JarUtils.createJarFile(Paths.get(CLS_DIR + "/JDK8171243.jar"),
 201                     Paths.get(SRC_DIR + "/jar"), JAR_CONTENT);
 202         } catch (IOException ex) {
 203             Assert.fail("Failed to create JAR: " + ex.getMessage());
 204         }
 205 
 206         return new Object[][]{
 207             // URL
 208             {urlFile, systemId, publicId, expected, errMsg},
 209             {urlHttp, "http://www.w3.org/2006/03/addressing/ws-addr.xsd", "", remoteXSD, "http test failed."},
 210             // JAR file
 211             {jarPath, "http://www.w3.org/2006/03/addressing/ws-addr.xsd", "", xsd, "jar file test failed."},
 212         };
 213     }
 214 
 215     /*
 216      *  DataProvider: invalid catalog result in empty catalog
 217      *  Note: the difference from invalidInput is that invalidInput is syntactically
 218      *  rejected with an IAE.
 219      */
 220     @DataProvider(name = "invalidCatalog")
 221     public Object[][] getInvalidCatalog() throws Exception {
 222         String catalogUri = getClass().getResource("catalog_invalid.xml").toExternalForm();
 223         return new Object[][]{
 224             {catalogUri, "-//W3C//DTD XHTML 1.0 Strict//EN",
 225                 "The catalog is invalid, attempting to match the public entry shall return null."},
 226             {"file:/../../..", "-//W3C//DTD XHTML 1.0 Strict//EN",
 227                 "The catalog is invalid, attempting to match the public entry shall return null."}
 228         };
 229     }
 230 
 231     /*
 232      *  DataProvider: a list of invalid inputs, expects IAE
 233      *  Note: exclude null since NPE would have been expected
 234      */
 235     @DataProvider(name = "invalidInput")
 236     public Object[][] getFiles() throws Exception {
 237         String filename = "rewriteSystem_id.xml";
 238         copyFile(Paths.get(SRC_DIR + "/" + filename), Paths.get(filename));
 239         String absolutePath = getClass().getResource(filename).getFile();
 240 
 241         return new Object[][]{
 242             {""},
 243             {"file:a/b\\c"},
 244             {"c:/te:t"},
 245             {"c:/te?t"},
 246             {"c/te*t"},
 247             {"in|valid.txt"},
 248             {"shema:invalid.txt"},
 249             // relative file path
 250             {filename},
 251             // absolute file path
 252             {absolutePath}
 253         };
 254     }
 255 
 256     /*
 257        DataProvider: a list of invalid inputs
 258      */
 259     @DataProvider(name = "nullTest")
 260     public Object[][] getNull() throws Exception {
 261 
 262         return new Object[][]{
 263             {null},
 264         };
 265     }
 266 
 267     void copyFile(Path src, Path target) throws Exception {
 268 
 269         try (InputStream in = Files.newInputStream(src);
 270                 BufferedReader reader
 271                 = new BufferedReader(new InputStreamReader(in));
 272                 OutputStream out = new BufferedOutputStream(
 273                         Files.newOutputStream(target, CREATE, APPEND));
 274                 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out))) {
 275             String line = null;
 276             while ((line = reader.readLine()) != null) {
 277                 bw.write(line);
 278             }
 279         } catch (IOException x) {
 280             throw new Exception(x.getMessage());
 281         }
 282     }
 283 }