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 org.testng.Assert.assertFalse;
  27 import java.io.FileOutputStream;
  28 import java.io.IOException;
  29 import java.nio.file.Files;
  30 import java.nio.file.Paths;
  31 import java.nio.file.StandardCopyOption;
  32 import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI;
  33 import javax.xml.parsers.DocumentBuilder;
  34 import javax.xml.parsers.DocumentBuilderFactory;
  35 import javax.xml.parsers.ParserConfigurationException;
  36 import jaxp.library.JAXPFileBaseTest;
  37 import static jaxp.library.JAXPTestUtilities.compareDocumentWithGold;
  38 import static org.testng.Assert.assertEquals;
  39 import static org.testng.Assert.assertTrue;
  40 import org.testng.annotations.Test;
  41 import org.w3c.dom.Attr;
  42 import org.w3c.dom.Document;
  43 import org.w3c.dom.Element;
  44 import org.w3c.dom.NodeList;
  45 import org.w3c.dom.Text;
  46 import org.w3c.dom.bootstrap.DOMImplementationRegistry;
  47 import org.w3c.dom.ls.DOMImplementationLS;
  48 import org.w3c.dom.ls.LSParser;
  49 import org.w3c.dom.ls.LSSerializer;
  50 import org.xml.sax.SAXException;
  51 import static test.auctionportal.HiBidConstants.CLASS_DIR;
  52 import static test.auctionportal.HiBidConstants.GOLDEN_DIR;
  53 import static test.auctionportal.HiBidConstants.PORTAL_ACCOUNT_NS;
  54 import static test.auctionportal.HiBidConstants.XML_DIR;
  55 
  56 /**
  57  * This is the user controller class for the Auction portal HiBid.com.
  58  */
  59 public class UserController extends JAXPFileBaseTest {
  60     /**
  61      * Checking when creating an XML document using DOM Level 2 validating
  62      * it without having a schema source or a schema location It must throw a
  63      * sax parse exception.
  64      * 
  65      * @throws ClassNotFoundException If any specified class does not implement.
  66      * @throws ParserConfigurationException if a DocumentBuilder cannot be 
  67      *         created which satisfies the configuration requested.
  68      * @throws InstantiationException If any specified class is an interface or 
  69      *         abstract class.
  70      * @throws IllegalAccessException If the default constructor of a specified 
  71      *         class is not accessible.
  72      * @throws SAXException If any parse errors occur.
  73      * @throws IOException if the file exists but is a directory rather than
  74      *         a regular file, does not exist but cannot be created, or cannot 
  75      *         be opened for any other reason.
  76      */
  77     @Test
  78     public void testCreateNewUser() throws ParserConfigurationException,  
  79             SAXException, IOException, ClassNotFoundException, 
  80              InstantiationException, IllegalAccessException {
  81         String resultFile = CLASS_DIR + "accountInfoOut.xml";
  82         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
  83         dbf.setNamespaceAware(true);
  84         dbf.setValidating(true);
  85 
  86         DocumentBuilder docBuilder = dbf.newDocumentBuilder();
  87         MyErrorHandler eh = new MyErrorHandler();
  88         docBuilder.setErrorHandler(eh);
  89 
  90         Document document = docBuilder.newDocument();
  91 
  92         Element account = document.createElementNS(PORTAL_ACCOUNT_NS, "acc:Account");
  93         Attr accountID = document.createAttributeNS(PORTAL_ACCOUNT_NS, "acc:accountID");
  94         account.setAttributeNode(accountID);
  95 
  96         account.appendChild(document.createElement("FirstName"));
  97         account.appendChild(document.createElementNS(PORTAL_ACCOUNT_NS, "acc:LastName"));
  98         account.appendChild(document.createElement("UserID"));
  99 
 100         DOMImplementationLS impl
 101                 = (DOMImplementationLS) DOMImplementationRegistry
 102                         .newInstance().getDOMImplementation("LS");
 103         LSSerializer writer = impl.createLSSerializer();
 104         LSParser builder = impl.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, null);
 105         try(FileOutputStream output = new FileOutputStream(resultFile)) {
 106             MyDOMOutput domOutput = new MyDOMOutput();
 107             domOutput.setByteStream(output);
 108             writer.write(account, domOutput);
 109             docBuilder.parse(resultFile);
 110         }
 111         assertTrue(eh.isAnyError());
 112     }
 113 
 114     /**
 115      * Checking conflicting namespaces and use renameNode and normalizeDocument.
 116      * @see <a href="content/accountInfo.xml">accountInfo.xml</a>
 117      * 
 118      * @throws ClassNotFoundException If any specified class does not implement.
 119      * @throws ParserConfigurationException if a DocumentBuilder cannot be 
 120      *         created which satisfies the configuration requested.
 121      * @throws InstantiationException If any specified class is an interface or 
 122      *         abstract class.
 123      * @throws IllegalAccessException If the default constructor of a specified 
 124      *         class is not accessible.
 125      * @throws SAXException If any parse errors occur.
 126      * @throws IOException if the file exists but is a directory rather than
 127      *         a regular file, does not exist but cannot be created, or cannot 
 128      *         be opened for any other reason.
 129      */
 130     @Test
 131     public void testAddUser() throws ParserConfigurationException, SAXException, 
 132             IOException, ClassNotFoundException, InstantiationException, 
 133             IllegalAccessException {
 134         String resultFile = CLASS_DIR + "accountRole.out";
 135         String xmlFile = XML_DIR + "accountInfo.xml";
 136         
 137         // Copy schema for outputfile
 138         Files.copy(Paths.get(XML_DIR, "accountInfo.xsd"),
 139                 Paths.get(CLASS_DIR, "accountInfo.xsd"),
 140                 StandardCopyOption.REPLACE_EXISTING);
 141         MyErrorHandler eh = new MyErrorHandler();
 142         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 143 
 144         dbf.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA_NS_URI);
 145         dbf.setNamespaceAware(true);
 146         dbf.setValidating(true);
 147 
 148         DocumentBuilder docBuilder = dbf.newDocumentBuilder();
 149         docBuilder.setErrorHandler(eh);
 150 
 151         Document document = docBuilder.parse(xmlFile);
 152         Element sell = (Element) document.getElementsByTagNameNS(PORTAL_ACCOUNT_NS, "Sell").item(0);
 153         Element role = (Element) sell.getParentNode();
 154 
 155         Element buy = (Element) document.renameNode(sell, PORTAL_ACCOUNT_NS, "acc:Buy");
 156         role.appendChild(buy);
 157 
 158         DOMImplementationLS impl
 159                 = (DOMImplementationLS) DOMImplementationRegistry
 160                         .newInstance().getDOMImplementation("LS");
 161         LSSerializer writer = impl.createLSSerializer();
 162 
 163 
 164         try(FileOutputStream output = new FileOutputStream(resultFile)) {
 165             MyDOMOutput mydomoutput = new MyDOMOutput();
 166             mydomoutput.setByteStream(output);
 167             writer.write(document, mydomoutput);
 168         }
 169 
 170         docBuilder.parse(resultFile);
 171         assertFalse(eh.isAnyError());
 172     }
 173 
 174     /**
 175      * Checking Text content in XML file.
 176      * @see <a href="content/accountInfo.xml">accountInfo.xml</a>
 177      * 
 178      * @throws ParserConfigurationException if a DocumentBuilder cannot be 
 179      *         created which satisfies the configuration requested.
 180      * @throws SAXException If any parse errors occur.
 181      * @throws IOException if the file exists but is a directory rather than
 182      *         a regular file, does not exist but cannot be created, or cannot 
 183      *         be opened for any other reason.
 184      */
 185     @Test(groups = {"readLocalFiles"})
 186     public void testMoreUserInfo() throws ParserConfigurationException, 
 187             SAXException, IOException {
 188         String xmlFile = XML_DIR + "accountInfo.xml";
 189         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 190 
 191         dbf.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA_NS_URI);
 192         dbf.setNamespaceAware(true);
 193         dbf.setValidating(true);
 194 
 195         DocumentBuilder docBuilder = dbf.newDocumentBuilder();
 196         MyErrorHandler eh = new MyErrorHandler();
 197         docBuilder.setErrorHandler(eh);
 198 
 199         Document document = docBuilder.parse(xmlFile);
 200         Element account = (Element)document
 201                 .getElementsByTagNameNS(PORTAL_ACCOUNT_NS, "Account").item(0);
 202         String textContent = account.getTextContent();
 203         assertTrue(textContent.trim().regionMatches(0, "Rachel", 0, 6));
 204         assertEquals(textContent, "RachelGreen744");
 205 
 206         Attr accountID = account.getAttributeNodeNS(PORTAL_ACCOUNT_NS, "accountID");
 207         assertTrue(accountID.getTextContent().trim().equals("1"));
 208 
 209         assertFalse(eh.isAnyError());
 210     }
 211 
 212     /**
 213      * This will check if adoptNode works will adoptNode from
 214      * @see <a href="content/userInfo.xml">userInfo.xml</a>
 215      * @see <a href="content/accountInfo.xml">accountInfo.xml</a>. This is
 216      * adopting a node from the XML file which is validated by a DTD and
 217      * into an XML file which is validated by the schema This covers Row 5
 218      * for the table
 219      * http://javaweb.sfbay/~jsuttor/JSR206/jsr-206-html/ch03s05.html. Filed
 220      * bug 4893745 because there was a difference in behavior.
 221      * 
 222      * @throws ClassNotFoundException If any specified class does not implement.
 223      * @throws ParserConfigurationException if a DocumentBuilder cannot be 
 224      *         created which satisfies the configuration requested.
 225      * @throws InstantiationException If any specified class is an interface or 
 226      *         abstract class.
 227      * @throws IllegalAccessException If the default constructor of a specified 
 228      *         class is not accessible.
 229      * @throws SAXException If any parse errors occur.
 230      * @throws IOException if the file exists but is a directory rather than
 231      *         a regular file, does not exist but cannot be created, or cannot 
 232      *         be opened for any other reason.
 233      */
 234     @Test
 235     public void testCreateUserAccount() throws ParserConfigurationException, 
 236             SAXException, IOException, ClassNotFoundException, 
 237             InstantiationException, IllegalAccessException {
 238         String userXmlFile = XML_DIR + "userInfo.xml";
 239         String accountXmlFile = XML_DIR + "accountInfo.xml";
 240         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 241         dbf.setNamespaceAware(true);
 242         dbf.setValidating(true);
 243 
 244         DocumentBuilder docBuilder = dbf.newDocumentBuilder();
 245         MyErrorHandler eh = new MyErrorHandler();
 246         docBuilder.setErrorHandler(eh);
 247 
 248         Document document = docBuilder.parse(userXmlFile);
 249         Element user = (Element) document.getElementsByTagName("FirstName").item(0);
 250         // Set schema after parsing userInfo.xml. Otherwise it will conflict
 251         // with DTD validation.
 252         dbf.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA_NS_URI);
 253         DocumentBuilder docBuilder1 = dbf.newDocumentBuilder();
 254         docBuilder1.setErrorHandler(eh);
 255         Document accDocument = docBuilder1.parse(accountXmlFile);
 256 
 257         Element firstName = (Element) accDocument
 258                 .getElementsByTagNameNS(PORTAL_ACCOUNT_NS, "FirstName").item(0);
 259         Element adoptedAccount = (Element) accDocument.adoptNode(user);
 260 
 261         Element parent = (Element) firstName.getParentNode();
 262         parent.replaceChild(adoptedAccount, firstName);
 263 
 264         DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
 265         DOMImplementationLS impl = (DOMImplementationLS) registry.getDOMImplementation("LS");
 266         LSSerializer writer = impl.createLSSerializer();
 267 
 268         MyDOMOutput mydomoutput = new MyDOMOutput();
 269         mydomoutput.setByteStream(System.out);
 270 
 271         writer.write(document, mydomoutput);
 272         writer.write(accDocument, mydomoutput);
 273 
 274         assertFalse(eh.isAnyError());
 275     }
 276 
 277     /**
 278      * Checking for Row 8 from the schema table when setting the schemaSource
 279      * without the schemaLanguage must report an error.
 280      * 
 281      * @throws ParserConfigurationException if a DocumentBuilder cannot be 
 282      *         created which satisfies the configuration requested.
 283      * @throws SAXException If any parse errors occur.
 284      * @throws IOException if the file exists but is a directory rather than
 285      *         a regular file, does not exist but cannot be created, or cannot 
 286      *         be opened for any other reason.
 287      */
 288     @Test(expectedExceptions = IllegalArgumentException.class)
 289     public void testUserError() throws ParserConfigurationException, 
 290             SAXException, IOException {
 291         String xmlFile = XML_DIR + "userInfo.xml";
 292         String schema = "http://java.sun.com/xml/jaxp/properties/schemaSource";
 293         String schemaValue = "http://dummy.com/dummy.xsd";
 294         
 295         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 296         dbf.setNamespaceAware(true);
 297         dbf.setValidating(true);
 298         dbf.setAttribute(schema, schemaValue);
 299 
 300         DocumentBuilder docBuilder = dbf.newDocumentBuilder();
 301         MyErrorHandler eh = new MyErrorHandler();
 302         docBuilder.setErrorHandler(eh);
 303         docBuilder.parse(xmlFile);
 304         assertFalse(eh.isAnyError());
 305     }
 306 
 307     /**
 308      * Checking for namespace normalization.
 309      * @see <a href="content/screenName.xml">screenName.xml</a> has prefix of
 310      * userName is bound to "http://hibid.com/user" namespace normalization
 311      * will create a namespace of prefix us and attach userEmail.
 312      * 
 313      * @throws ClassNotFoundException If any specified class does not implement.
 314      * @throws ParserConfigurationException if a DocumentBuilder cannot be 
 315      *         created which satisfies the configuration requested.
 316      * @throws InstantiationException If any specified class is an interface or 
 317      *         abstract class.
 318      * @throws IllegalAccessException If the default constructor of a specified 
 319      *         class is not accessible.
 320      * @throws SAXException If any parse errors occur.
 321      * @throws IOException if the file exists but is a directory rather than
 322      *         a regular file, does not exist but cannot be created, or cannot 
 323      *         be opened for any other reason.
 324      */
 325     @Test
 326     public void testCheckScreenNameExists() throws ParserConfigurationException, 
 327             ClassNotFoundException, InstantiationException, IllegalAccessException,
 328             SAXException, IOException {
 329         String resultFile = CLASS_DIR + "screenName.out";
 330         String xmlFile = XML_DIR + "screenName.xml";
 331         String goldFile = GOLDEN_DIR + "screenNameGold.xml";
 332 
 333         String nsTagName = "http://hibid.com/screenName";
 334         String userNs = "http://hibid.com/user";
 335 
 336         try (FileOutputStream output = new FileOutputStream(resultFile)) {
 337             DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
 338             DOMImplementationLS impl = (DOMImplementationLS) registry.getDOMImplementation("LS");
 339             LSSerializer writer = impl.createLSSerializer();
 340             LSParser builder = impl.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, null);
 341             Document document = builder.parseURI(xmlFile);
 342             NodeList nl = document.getElementsByTagNameNS(nsTagName, "screen-name");
 343             assertEquals(nl.getLength(), 1);
 344             Element screenName = (Element)nl.item(0);
 345             Element userEmail = document.createElementNS(userNs, "userEmail");
 346             assertTrue(userEmail.isDefaultNamespace(userNs));
 347 
 348             Text email = document.createTextNode("myid@hibid.com");
 349             userEmail.appendChild(email);
 350             screenName.appendChild(userEmail);
 351             document.normalizeDocument();
 352 
 353             MyDOMOutput domoutput = new MyDOMOutput();
 354             domoutput.setByteStream(output);
 355             writer.write(document, domoutput);
 356         }
 357         assertTrue(compareDocumentWithGold(goldFile, resultFile));
 358     }
 359 }