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