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