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 package test.auctionportal;
  24 
  25 import static com.sun.org.apache.xerces.internal.jaxp.JAXPConstants.JAXP_SCHEMA_LANGUAGE;
  26 import static com.sun.org.apache.xerces.internal.jaxp.JAXPConstants.JAXP_SCHEMA_SOURCE;
  27 import static org.testng.Assert.assertEquals;
  28 import static org.testng.Assert.assertFalse;
  29 import static org.testng.Assert.assertTrue;
  30 
  31 import java.io.File;
  32 import java.io.FileInputStream;
  33 import java.io.FilePermission;
  34 import java.io.IOException;
  35 import java.io.InputStream;
  36 import java.math.BigInteger;
  37 import java.nio.file.Paths;
  38 import java.util.GregorianCalendar;
  39 import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI;
  40 
  41 import javax.xml.datatype.DatatypeConfigurationException;
  42 import javax.xml.datatype.DatatypeConstants;
  43 import javax.xml.datatype.DatatypeFactory;
  44 import javax.xml.datatype.Duration;
  45 import javax.xml.parsers.DocumentBuilder;
  46 import javax.xml.parsers.DocumentBuilderFactory;
  47 import javax.xml.parsers.ParserConfigurationException;
  48 import javax.xml.parsers.SAXParser;
  49 import javax.xml.parsers.SAXParserFactory;
  50 import javax.xml.transform.dom.DOMResult;
  51 import javax.xml.transform.dom.DOMSource;
  52 import javax.xml.validation.Schema;
  53 import javax.xml.validation.SchemaFactory;
  54 import javax.xml.validation.Validator;
  55 import jaxp.library.JAXPBaseTest;
  56 import static jaxp.library.JAXPTestUtilities.bomStream;
  57 import org.testng.annotations.AfterGroups;
  58 import org.testng.annotations.BeforeGroups;
  59 import org.testng.annotations.Test;
  60 import org.w3c.dom.Attr;
  61 import org.w3c.dom.DOMConfiguration;
  62 import org.w3c.dom.Document;
  63 import org.w3c.dom.Element;
  64 import org.w3c.dom.NodeList;
  65 import org.w3c.dom.TypeInfo;
  66 import org.w3c.dom.bootstrap.DOMImplementationRegistry;
  67 import org.w3c.dom.ls.DOMImplementationLS;
  68 import org.w3c.dom.ls.LSSerializer;
  69 import org.xml.sax.SAXException;
  70 import static test.auctionportal.HiBidConstants.PORTAL_ACCOUNT_NS;
  71 import static test.auctionportal.HiBidConstants.XML_DIR;
  72 
  73 /**
  74  * This is the user controller  class for the Auction portal HiBid.com.
  75  */
  76 public class AuctionController extends JAXPBaseTest {
  77     /**
  78      * Save system property for restoring.
  79      */
  80     @BeforeGroups (groups = {"readLocalFiles"})
  81     public void setFilePermissions() {
  82         setPermissions(new FilePermission(XML_DIR + "/-", "read"));
  83     }
  84     
  85     /**
  86      * Restore the system property.
  87      */
  88     @AfterGroups (groups = {"readLocalFiles"})
  89     public void restoreFilePermissions() {
  90         setPermissions();
  91     }
  92 
  93     /**
  94      * Check for DOMErrorHandler handling DOMError. Before fix of bug 4890927
  95      * DOMConfiguration.setParameter("well-formed",true) throws an exception.
  96      * 
  97      * @throws ClassNotFoundException If any specified class does not implement.
  98      * @throws ParserConfigurationException if a DocumentBuilder cannot be 
  99      *         created which satisfies the configuration requested.
 100      * @throws InstantiationException If any specified class is an interface or 
 101      *         abstract class.
 102      * @throws IllegalAccessException If the default constructor of a specified 
 103      *         class is not accessible.
 104      * @throws SAXException If any parse errors occur.
 105      * @throws IOException if the file exists but is a directory rather than
 106      *         a regular file, does not exist but cannot be created, or cannot 
 107      *         be opened for any other reason.
 108      */
 109     @Test(groups = {"readLocalFiles"})
 110     public void testCreateNewItem2Sell() throws ClassNotFoundException, 
 111             ParserConfigurationException, InstantiationException, 
 112             IllegalAccessException, SAXException, IOException {
 113         String xmlFile = XML_DIR + "novelsInvalid.xml";
 114 
 115         Document document = DocumentBuilderFactory.newInstance()
 116                 .newDocumentBuilder().parse(xmlFile);
 117 
 118         document.getDomConfig().setParameter("well-formed", true);
 119 
 120         DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
 121         DOMImplementationLS impl = (DOMImplementationLS) registry.getDOMImplementation("LS");
 122         MyDOMOutput domOutput = new MyDOMOutput();
 123         domOutput.setByteStream(System.out);
 124         LSSerializer writer = impl.createLSSerializer();
 125         writer.write(document, domOutput);
 126     }
 127 
 128     /**
 129      * Check for DOMErrorHandler handling DOMError. Before fix of bug 4896132
 130      * test throws DOM Level 1 node error.
 131      * 
 132      * @throws ClassNotFoundException If any specified class does not implement.
 133      * @throws ParserConfigurationException if a DocumentBuilder cannot be 
 134      *         created which satisfies the configuration requested.
 135      * @throws InstantiationException If any specified class is an interface or 
 136      *         abstract class.
 137      * @throws IllegalAccessException If the default constructor of a specified 
 138      *         class is not accessible.
 139      * @throws SAXException If any parse errors occur.
 140      * @throws IOException if the file exists but is a directory rather than
 141      *         a regular file, does not exist but cannot be created, or cannot 
 142      *         be opened for any other reason.
 143      */
 144     @Test(groups = {"readLocalFiles"})
 145     public void testCreateNewItem2SellRetry() throws ClassNotFoundException, 
 146             ParserConfigurationException, InstantiationException, 
 147             IllegalAccessException, SAXException, IOException  {
 148         String xmlFile = XML_DIR + "accountInfo.xml";
 149 
 150         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 151         dbf.setNamespaceAware(true);
 152         Document document = dbf.newDocumentBuilder().parse(xmlFile);
 153 
 154         DOMConfiguration domConfig = document.getDomConfig();
 155         MyDOMErrorHandler errHandler = new MyDOMErrorHandler();
 156         domConfig.setParameter("error-handler", errHandler);
 157 
 158         DOMImplementationLS impl =
 159              (DOMImplementationLS) DOMImplementationRegistry.newInstance()
 160                      .getDOMImplementation("LS");
 161         LSSerializer writer = impl.createLSSerializer();
 162         MyDOMOutput domoutput = new MyDOMOutput();
 163 
 164         domoutput.setByteStream(System.out);
 165         writer.write(document, domoutput);
 166 
 167         document.normalizeDocument();
 168         writer.write(document, domoutput);
 169         assertFalse(errHandler.isError());
 170     }
 171 
 172     /**
 173      * Check if setting the attribute to be of type ID works. This will affect
 174      * the Attr.isID method according to the spec.
 175      * 
 176      * @throws ParserConfigurationException if a DocumentBuilder cannot be 
 177      *         created which satisfies the configuration requested.
 178      * @throws SAXException If any parse errors occur.
 179      * @throws IOException if the file exists but is a directory rather than
 180      *         a regular file, does not exist but cannot be created, or cannot 
 181      *         be opened for any other reason.
 182      */
 183     @Test(groups = {"readLocalFiles"})
 184     public void testCreateID() throws ParserConfigurationException,
 185             SAXException, IOException {
 186         String xmlFile = XML_DIR + "accountInfo.xml";
 187 
 188         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 189         dbf.setNamespaceAware(true);
 190 
 191         Document document = dbf.newDocumentBuilder().parse(xmlFile);
 192         Element account = (Element)document
 193             .getElementsByTagNameNS(PORTAL_ACCOUNT_NS, "Account").item(0);
 194 
 195         account.setIdAttributeNS(PORTAL_ACCOUNT_NS, "accountID", true);
 196         Attr aID = account.getAttributeNodeNS(PORTAL_ACCOUNT_NS, "accountID");
 197         assertTrue(aID.isId());
 198     }
 199 
 200     /**
 201      * Check the user data on the node.
 202      * 
 203      * @throws ParserConfigurationException if a DocumentBuilder cannot be 
 204      *         created which satisfies the configuration requested.
 205      * @throws SAXException If any parse errors occur.
 206      * @throws IOException if the file exists but is a directory rather than
 207      *         a regular file, does not exist but cannot be created, or cannot 
 208      *         be opened for any other reason.
 209      */
 210     @Test(groups = {"readLocalFiles"})
 211     public void testCheckingUserData() throws ParserConfigurationException, 
 212             SAXException, IOException {
 213         String xmlFile = XML_DIR + "accountInfo.xml";
 214 
 215         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 216         dbf.setNamespaceAware(true);
 217 
 218         DocumentBuilder docBuilder = dbf.newDocumentBuilder();
 219         Document document = docBuilder.parse(xmlFile);
 220 
 221         Element account = (Element)document.getElementsByTagNameNS(PORTAL_ACCOUNT_NS, "Account").item(0);
 222         assertEquals(account.getNodeName(), "acc:Account");
 223         Element firstName = (Element) document.getElementsByTagNameNS(PORTAL_ACCOUNT_NS, "FirstName").item(0);
 224         assertEquals(firstName.getNodeName(), "FirstName");
 225 
 226         Document doc1 = docBuilder.newDocument();
 227         Element someName = doc1.createElement("newelem");
 228 
 229         someName.setUserData("mykey", "dd",
 230             (operation, key,  data, src,  dst) ->  {
 231                 System.err.println("In UserDataHandler" + key);
 232                 System.out.println("In UserDataHandler");
 233             });
 234         Element impAccount = (Element)document.importNode(someName, true);
 235         assertEquals(impAccount.getNodeName(), "newelem");
 236         document.normalizeDocument();
 237         String data = (someName.getUserData("mykey")).toString();
 238         assertEquals(data, "dd");
 239     }
 240 
 241 
 242     /**
 243      * Check the UTF-16 XMLEncoding xml file.
 244      * 
 245      * @throws ParserConfigurationException if a DocumentBuilder cannot be 
 246      *         created which satisfies the configuration requested. 
 247      * @throws SAXException If any parse errors occur.
 248      * @throws IOException if the file exists but is a directory rather than
 249      *         a regular file, does not exist but cannot be created, or cannot 
 250      *         be opened for any other reason.
 251      * @see <a href="content/movies.xml">movies.xml</a>
 252      */
 253     @Test(groups = {"readLocalFiles"})
 254     public void testCheckingEncoding() throws ParserConfigurationException,
 255             IOException, SAXException {
 256         // Note since movies.xml is UTF-16 encoding. We're not using stanard XML
 257         // file suffix.
 258         String xmlFile = XML_DIR + "movies.xml.data";
 259 
 260         try (InputStream source = bomStream("UTF-16", xmlFile)) {
 261             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 262             dbf.setNamespaceAware(true);
 263             Document document = dbf.newDocumentBuilder().parse(source);
 264             assertEquals(document.getXmlEncoding(), "UTF-16");
 265             assertEquals(document.getXmlStandalone(), true);
 266         }
 267     }
 268 
 269     /**
 270      * Check validation API features. A schema which is including in Bug 4909119
 271      * used to be testing for the functionalities.
 272      * 
 273      * @throws ParserConfigurationException if a DocumentBuilder cannot be 
 274      *         created which satisfies the configuration requested. 
 275      * @throws SAXException If any parse errors occur.
 276      * @throws IOException if the file exists but is a directory rather than
 277      *         a regular file, does not exist but cannot be created, or cannot 
 278      *         be opened for any other reason.
 279      * @see <a href="content/userDetails.xsd">userDetails.xsd</a>
 280      */
 281     @Test(groups = {"readLocalFiles"})
 282     public void testGetOwnerInfo() throws ParserConfigurationException, 
 283             SAXException, IOException {
 284         String schemaFile = XML_DIR + "userDetails.xsd";
 285         String xmlFile = XML_DIR + "userDetails.xml";
 286         
 287         try(FileInputStream fis = new FileInputStream(xmlFile)) {
 288             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 289             dbf.setNamespaceAware(true);
 290             dbf.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA_NS_URI);
 291 
 292             SchemaFactory schemaFactory = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI);
 293             Schema schema = schemaFactory.newSchema(Paths.get(schemaFile).toFile());
 294 
 295             Validator validator = schema.newValidator();
 296             MyErrorHandler eh = new MyErrorHandler();
 297             validator.setErrorHandler(eh);
 298 
 299             DocumentBuilder docBuilder = dbf.newDocumentBuilder();
 300             docBuilder.setErrorHandler(eh);
 301 
 302             Document document = docBuilder.parse(fis);
 303             DOMResult dResult = new DOMResult();
 304             DOMSource domSource = new DOMSource(document);
 305             validator.validate(domSource, dResult);
 306             assertFalse(eh.isAnyError());
 307         }
 308     }
 309 
 310     /**
 311      * Check grammar caching with imported schemas.
 312      * 
 313      * @throws ParserConfigurationException if a DocumentBuilder cannot be 
 314      *         created which satisfies the configuration requested. 
 315      * @throws SAXException If any parse errors occur.
 316      * @throws IOException if the file exists but is a directory rather than
 317      *         a regular file, does not exist but cannot be created, or cannot 
 318      *         be opened for any other reason.
 319      * @see <a href="content/coins.xsd">coins.xsd</a>
 320      * @see <a href="content/coinsImportMe.xsd">coinsImportMe.xsd</a>
 321      */
 322     @Test(groups = {"readLocalFiles"})
 323     public void testGetOwnerItemList() throws ParserConfigurationException, 
 324             IOException, SAXException {
 325         String xsdFile = XML_DIR + "coins.xsd";
 326         String xmlFile = XML_DIR + "coins.xml";
 327 
 328         try(FileInputStream fis = new FileInputStream(xmlFile)) {
 329             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 330             dbf.setNamespaceAware(true);
 331             dbf.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA_NS_URI);
 332             dbf.setValidating(false);
 333 
 334             SchemaFactory schemaFactory = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI);
 335             Schema schema = schemaFactory.newSchema(new File(((xsdFile))));
 336 
 337             MyErrorHandler eh = new MyErrorHandler();
 338             Validator validator = schema.newValidator();
 339             validator.setErrorHandler(eh);
 340 
 341             DocumentBuilder docBuilder = dbf.newDocumentBuilder();
 342             Document document = docBuilder.parse(fis);
 343             validator.validate(new DOMSource(document), new DOMResult());
 344             assertFalse(eh.isAnyError());
 345         }
 346     }
 347 
 348 
 349     /**
 350      * Check for the same imported schemas but will use SAXParserFactory and try
 351      * parsing using the SAXParser. SCHEMA_SOURCE attribute is using for this
 352      * test.
 353      * 
 354      * @throws SAXException If any parse errors occur.
 355      * @throws IOException if the file exists but is a directory rather than
 356      *         a regular file, does not exist but cannot be created, or cannot 
 357      *         be opened for any other reason.
 358      * @throws ParserConfigurationException if a DocumentBuilder cannot be 
 359      *         created which satisfies the configuration requested.
 360      * @see <a href="content/coins.xsd">coins.xsd</a>
 361      * @see <a href="content/coinsImportMe.xsd">coinsImportMe.xsd</a>
 362      */
 363 
 364     @Test(groups = {"readLocalFiles"})
 365     public void testGetOwnerItemList1() throws SAXException, IOException, 
 366             ParserConfigurationException {
 367         String xsdFile = XML_DIR + "coins.xsd";
 368         String xmlFile = XML_DIR + "coins.xml";
 369         SAXParserFactory spf = SAXParserFactory.newInstance();
 370         spf.setNamespaceAware(true);
 371         spf.setValidating(true);
 372 
 373         SAXParser sp = spf.newSAXParser();
 374         sp.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA_NS_URI);
 375         sp.setProperty(JAXP_SCHEMA_SOURCE, xsdFile);
 376 
 377         MyErrorHandler eh = new MyErrorHandler();
 378         sp.parse(new File(xmlFile), eh);
 379         assertFalse(eh.isAnyError());
 380     }
 381 
 382     /**
 383      * Check usage of javax.xml.datatype.Duration class.
 384      * 
 385      * @throws SAXException If any parse errors occur.
 386      * @throws IOException if the file exists but is a directory rather than
 387      *         a regular file, does not exist but cannot be created, or cannot 
 388      *         be opened for any other reason.
 389      * @throws ParserConfigurationException if a DocumentBuilder cannot be 
 390      *         created which satisfies the configuration requested.
 391      * @throws DatatypeConfigurationException If the implementation is not
 392      *         available or cannot be instantiated.
 393      */
 394     @Test(groups = {"readLocalFiles"})
 395     public void testGetItemDuration() throws ParserConfigurationException, 
 396             SAXException, DatatypeConfigurationException, IOException {
 397         String xmlFile = XML_DIR + "itemsDuration.xml";
 398 
 399         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 400         dbf.setNamespaceAware(true);
 401         Document document = dbf.newDocumentBuilder().parse(xmlFile);
 402 
 403         Element durationElement = (Element) document.getElementsByTagName("sellDuration").item(0);
 404 
 405         NodeList childList = durationElement.getChildNodes();
 406 
 407         for (int i = 0; i < childList.getLength(); i++) {
 408             System.out.println("child " + i + childList.item(i));
 409         }
 410 
 411         Duration duration = DatatypeFactory.newInstance().newDuration("P365D");
 412         Duration sellDuration = DatatypeFactory.newInstance().newDuration(childList.item(0).getNodeValue());
 413         assertFalse(sellDuration.isShorterThan(duration));
 414         assertFalse(sellDuration.isLongerThan(duration));
 415         assertEquals(sellDuration.getField(DatatypeConstants.DAYS), BigInteger.valueOf(365));
 416         assertEquals(sellDuration.normalizeWith(new GregorianCalendar(1999, 2, 22)), duration);
 417 
 418         Duration myDuration = sellDuration.add(duration);
 419         assertEquals(myDuration.normalizeWith(new GregorianCalendar(2003, 2, 22)),
 420                 DatatypeFactory.newInstance().newDuration("P730D"));
 421     }
 422 
 423     /**
 424      * Check usage of TypeInfo interface introduced in DOM L3.
 425      * 
 426      * @throws ParserConfigurationException if a DocumentBuilder cannot be 
 427      *         created which satisfies the configuration requested.
 428      * @throws SAXException If any parse errors occur.
 429      * @throws IOException if the file exists but is a directory rather than
 430      *         a regular file, does not exist but cannot be created, or cannot 
 431      *         be opened for any other reason.
 432      */
 433     @Test(groups = {"readLocalFiles"})
 434     public void testGetTypeInfo() throws ParserConfigurationException, 
 435             SAXException, IOException {
 436         String xmlFile = XML_DIR + "accountInfo.xml";
 437 
 438         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 439         dbf.setNamespaceAware(true);
 440         dbf.setValidating(true);
 441         dbf.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA_NS_URI);
 442 
 443         DocumentBuilder docBuilder = dbf.newDocumentBuilder();
 444         docBuilder.setErrorHandler(new MyErrorHandler());
 445 
 446         Document document = docBuilder.parse(xmlFile);
 447         Element userId = (Element)document.getElementsByTagNameNS(PORTAL_ACCOUNT_NS, "UserID").item(0);
 448         TypeInfo typeInfo = userId.getSchemaTypeInfo();
 449         assertTrue(typeInfo.getTypeName().equals("nonNegativeInteger"));
 450         assertTrue(typeInfo.getTypeNamespace().equals(W3C_XML_SCHEMA_NS_URI));
 451 
 452         Element role = (Element)document.getElementsByTagNameNS(PORTAL_ACCOUNT_NS, "Role").item(0);
 453         TypeInfo roletypeInfo = role.getSchemaTypeInfo();
 454         assertTrue(roletypeInfo.getTypeName().equals("BuyOrSell"));
 455         assertTrue(roletypeInfo.getTypeNamespace().equals(PORTAL_ACCOUNT_NS));
 456     }
 457 }