| /* |
| * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0, which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * This Source Code may also be made available under the following Secondary |
| * Licenses when the conditions for such availability set forth in the |
| * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, |
| * version 2 with the GNU Classpath Exception, which is available at |
| * https://www.gnu.org/software/classpath/license.html. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 |
| */ |
| |
| package com.sun.ejte.ccl.reporter; |
| |
| import org.xml.sax.*; |
| import org.xml.sax.ext.*; |
| import org.xml.sax.helpers.*; |
| import java.io.*; |
| import java.util.*; |
| |
| public class ParseML{ |
| private String vendorParserClass = |
| "org.apache.xerces.parsers.SAXParser"; |
| public static boolean debug = false; |
| boolean inTestcase = false; |
| boolean inTestcaseID = false; |
| boolean gotStatus = false; |
| static Hashtable hash = null; |
| static Vector[] fileDiffs = null; |
| String key = ""; |
| String value = ""; |
| |
| public static void main(String args[]){ |
| ParseML pml = new ParseML(); |
| if(args.length<2){ |
| pml.usage(); |
| } |
| hash = new Hashtable(); |
| int no_of_files = args.length; |
| if(debug){ |
| System.out.println("number of files:"+no_of_files); |
| } |
| Hashtable[] filehash = new Hashtable[no_of_files]; |
| fileDiffs = new Vector[no_of_files]; |
| for(int i = 0; i<args.length; i++){ |
| filehash[i] = new Hashtable(); |
| fileDiffs[i] = new Vector(); |
| fileDiffs[i].add("</u><b>File:"+args[i]+"</b></u><br>\n"); // add the filename to the vector |
| System.out.println("parsing file #"+i); |
| filehash[i] = pml.buildTree(args[i]); |
| hash = null; |
| hash = new Hashtable(); |
| if(debug){ |
| System.out.print("========================"); |
| System.out.println("Displaying hashtable # "+i); |
| pml.displayHash(filehash[i]); |
| } |
| } |
| pml.diffHash(filehash); |
| pml.displayVectorArr(fileDiffs); |
| System.out.print("writing diffs to file..."); |
| pml.writeDiffs(fileDiffs); |
| System.out.println("done"); |
| } |
| public Hashtable buildTree(String xmlURI){ |
| //hash = null; |
| try{ |
| //Initialize a reader |
| XMLReader reader = |
| XMLReaderFactory.createXMLReader(vendorParserClass); |
| //Register Content Handler |
| ContentHandler myContentHandler = new MyContentHandler(); |
| reader.setContentHandler(myContentHandler); |
| |
| //Parse |
| InputSource inputSource = |
| new InputSource(new java.io.FileInputStream(new java.io.File(xmlURI))); |
| reader.parse(inputSource); |
| |
| } catch(Throwable th){ |
| th.printStackTrace(); |
| } |
| return hash; |
| } |
| |
| class MyContentHandler implements ContentHandler{ |
| private Locator locator; |
| public void setDocumentLocator(Locator locator){ |
| this.locator = locator; |
| } |
| public void startDocument() throws SAXException{ |
| //initialize a 2D vector here |
| } |
| public void endDocument() throws SAXException{ |
| } |
| public void processingInstruction(String target, String data) |
| throws SAXException{ |
| // add target and data to the 2D vector |
| } |
| public void startPrefixMapping(String prefix, String uri){ |
| } |
| public void endPrefixMapping(String prefix){ |
| } |
| public void startElement(String namespaceURI, String localName, |
| String qName, Attributes atts) |
| throws SAXException{ |
| // add the local name into vector |
| if(localName.equals("testcase")){ |
| inTestcase = true; |
| } |
| if(localName.equals("id") && (inTestcase)){ |
| inTestcaseID = true; |
| if(debug){ |
| System.out.println("inside testcase id."); |
| } |
| } |
| // assuming that when its time to get the status, the value for the keys would have been obtained. |
| if(localName.equals("status") && (inTestcase)){ |
| //get attributes: pass/fail |
| if(debug){ |
| System.out.println("getting testcase status..."); |
| } |
| value = atts.getValue(0).trim(); |
| if((key!=null) && (!(key.equals(""))) && (value!=null) && (!value.equals(""))){ |
| if(debug){ |
| System.out.println("Key["+key+"] has value["+value+"]"); |
| } |
| hash.put(key,value); |
| gotStatus = true; |
| key = ""; |
| value = ""; |
| } |
| else{ |
| if(key == null || key.equals("")){ |
| System.out.println("invalid key!"); |
| } |
| if(value== null || value.equals("")){ |
| System.out.println("invalid value!"); |
| } |
| } |
| } |
| } |
| public void endElement(String namespaceURI, String localName, String qName) |
| throws SAXException{ |
| if(localName.equals("testcase")){ |
| inTestcase = false; |
| if(debug){ |
| System.out.println("Outside testcase tag"); |
| } |
| } |
| if(localName.equals("id") && (inTestcase)){ |
| inTestcaseID = false; |
| if(debug){ |
| System.out.println("Outside testcase-ID tag"); |
| } /* |
| key = key.trim(); |
| value = value.trim(); |
| if((key!=null) && (value!=null) && |
| (!(value.equals(""))) && (!(key.equals("")))){ |
| |
| } */ |
| } |
| } |
| public void characters(char[] ch, int start, int length) |
| throws SAXException{ |
| String s = new String(ch, start, length); |
| if(debug){ |
| System.out.print("\nvalue of start index= "+start+", "); |
| System.out.print("length of charectars = "+length+", "); |
| System.out.println("string = ["+s+"]"); |
| } |
| if(inTestcaseID){ |
| key += s.trim(); |
| if((key!=null) && (!key.equals(""))){ |
| if(debug){ |
| System.out.println("TestCase ID:"+key); |
| } |
| } |
| } |
| } |
| public void ignorableWhitespace(char[] ch, int start, int length) |
| throws SAXException{ |
| } |
| public void skippedEntity(String name) throws SAXException{ |
| System.out.println("Skipped entity is:"+name); |
| } |
| } |
| /*======= End of Inner Class Definition ================*/ |
| |
| public void displayHash(Hashtable hashtable){ |
| for (Enumeration e = hashtable.keys() ; e.hasMoreElements() ;) { |
| String keyval = (String)e.nextElement(); |
| System.out.println(keyval +":"+hashtable.get(keyval)); |
| } |
| } |
| |
| public void displayVector(Vector v){ |
| for(int i=0; i<v.size(); i++){ |
| System.out.println((String)v.get(i)); |
| } |
| } |
| |
| public void displayVectorArr(Vector[] v){ |
| for (int i = 0; i<v.length; i++){ |
| displayVector(v[i]); |
| } |
| } |
| |
| public void writeDiffs(Vector[] v){ |
| try{ |
| File inputfile = new File("fileDiffs.html"); |
| FileWriter fw = new FileWriter(inputfile); |
| String filecontent = "<h3>File Diff Output</h3><hr>\n"; |
| for(int i = 0; i<v.length ; i++){ |
| for(int j = 0; j<v[i].size(); j++){ |
| filecontent += v[i].get(j)+"<br>\n"; |
| } |
| filecontent += "<hr>\n"; |
| } |
| fw.write(filecontent); |
| fw.close(); |
| } catch(FileNotFoundException fnfe){ |
| System.out.println("File is not present. \n"+ |
| "Please check the file name and try again"); |
| } catch(Exception ex){ |
| ex.printStackTrace(); |
| } |
| } |
| |
| public Vector getKeyList(Hashtable[] hashes){ |
| int hashtables = hashes.length; |
| Vector allkeys= new Vector(); |
| Vector[] hashVecs = new Vector[hashtables]; |
| for(int i=0; i<hashtables; i++){ |
| hashVecs[i] = new Vector((Collection)hashes[i].keySet()); |
| } |
| allkeys = getUnion(hashVecs); |
| return allkeys; |
| } |
| |
| public Vector getUnion(Vector[] v){ |
| Vector union = new Vector(); |
| for(int i=0; i<v.length; i++){ |
| for(int j=0; j<v[i].size(); j++){ |
| if(!union.contains(v[i].get(j))){ |
| union.add(v[i].get(j)); |
| }//end if |
| }//end inner-for |
| }// end outer-for |
| return union; |
| }// end method getUnion |
| |
| public void diffHash(Hashtable[] hashes){ |
| int hashtables = hashes.length; |
| if(debug){ |
| System.out.println("total hashtables to diff:"+hashtables); |
| } |
| int bigHash = 0; // take the first hashtable as the golden file. |
| /*Get a list of most keys*/ |
| Vector keylist = new Vector(); |
| keylist = getKeyList(hashes); |
| /*Start comparing all other hashtable elements to this golden list of testcases*/ |
| |
| int totalkeys = keylist.size(); |
| if(debug){ |
| System.out.println("Total number of testcases gathered: "+totalkeys); |
| } |
| for(int keyno=0; keyno<totalkeys; keyno++){ |
| String keyObj = (String)keylist.get(keyno); |
| Object val = null; |
| Object bigHashVal = null; |
| // for all hashtables in the array... |
| if(debug){ |
| System.out.println("checking out key:"+keyObj); |
| } |
| for(int i = 0; i<hashtables ; i++){ |
| if(i==bigHash){ |
| continue; |
| } |
| // key exists |
| if((bigHashVal=hashes[bigHash].get(keyObj))!=null){ // key exists in bigHash |
| if((val = hashes[i].get(keyObj))!=null){ |
| if (val.equals(bigHashVal)){ |
| // key and value pair match the golden file |
| continue; |
| } else { |
| // key exists but the values are different |
| // add it into both the vectors, if not already there. |
| String diffObj = "<font color=blue>"+keyObj+ |
| " has an inconsistent status:"+(String)val+ |
| "</font>"; |
| String bigdiffObj = "<font color=blue>"+keyObj+ |
| " has an inconsistent status:"+(String)bigHashVal+ |
| "</font>"; |
| if(!fileDiffs[i].contains(diffObj)){ |
| fileDiffs[i].add(diffObj); |
| } |
| if(!fileDiffs[bigHash].contains(bigdiffObj)){ |
| fileDiffs[bigHash].add(bigdiffObj); |
| } |
| } |
| } else { |
| // key doesn't exist |
| /*add it into the vector for smaller tables, if not already there.*/ |
| String diffObj = "<font color=red>"+keyObj+ |
| " testcase is missing </font>"; |
| if(!fileDiffs[i].contains(diffObj)){ |
| fileDiffs[i].add(diffObj); |
| }// end missing-key if |
| } // end missing-key else |
| // end key-exists if in bighash |
| } else { |
| // add the missing key into the vector for bighash |
| String bigdiffObj = "<font color=red>"+keyObj+ |
| " testcase is missing </font>"; |
| if(!fileDiffs[bigHash].contains(bigdiffObj)){ |
| fileDiffs[bigHash].add(bigdiffObj); |
| }// end missing-key if |
| } |
| } // end for-loop for going through the hashtable array |
| } // end for-loop for keys in the bigHash hashtable |
| } // end diff-hash method |
| |
| public void usage(){ |
| String usageStr = "Usage:\n java ParseML <xml_file_1> <xml_file_2> <xml_file_3>..."+ |
| "\n\tThis Utility will let you 'diff' multiple xml"+ |
| "\n\t files and produce a fileDiff.html file in the "+ |
| "\n\t directory where this file is run from."+ |
| "\n\tDiff results are produced only by matching the contents "+ |
| "\n\tof the xml trees and not by comparing text characters."+ |
| "\n\n\tThis program takes arguments of two or more 'well_formed_xml' files."; |
| System.out.println(usageStr); |
| System.exit(0); |
| } |
| } |