update dev300-m58
[ooovba.git] / xmerge / workben / XmlDiff.java
blobdd7411e435e7114c072679f9946c2d986b1bf175
1 /************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: XmlDiff.java,v $
10 * $Revision: 1.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 import java.io.FileWriter;
32 import java.io.InputStream;
33 import java.io.FileInputStream;
34 import java.io.BufferedInputStream;
35 import java.io.BufferedWriter;
36 import java.io.IOException;
37 import java.io.FileNotFoundException;
38 import java.io.OutputStream;
39 import java.io.OutputStreamWriter;
40 import java.io.Writer;
41 import java.io.PrintWriter;
42 import java.util.Vector;
43 import java.util.Properties;
45 import javax.xml.parsers.DocumentBuilderFactory;
46 import javax.xml.parsers.DocumentBuilder;
47 import javax.xml.parsers.ParserConfigurationException;
49 import org.w3c.dom.Node;
50 import org.w3c.dom.Document;
51 import org.w3c.dom.NodeList;
52 import org.xml.sax.SAXException;
53 import org.xml.sax.SAXParseException;
54 /**
55 * This class will diff 2 Xml files.
57 * @author Stephen Mak
60 public final class XmlDiff {
62 private static final String PROPSFILE = "XmlDiff.properties";
63 private static final String FILE1 = "XmlDiff.file1";
64 private static final String FILE2 = "XmlDiff.file2";
65 private static final String OUTPUT= "XmlDiff.output";
66 private static final String IGNORE_TAGS= "XmlDiff.tags";
68 private Properties props_ = null;
69 private static PrintWriter writer_ = null;
70 private String[] tags_ = null;
71 private String file1_ = null;
72 private String file2_ = null;
74 /**
75 * Constructor. Load the properties file.
78 public XmlDiff() throws IOException {
80 Class c = this.getClass();
81 InputStream is = c.getResourceAsStream(PROPSFILE);
82 BufferedInputStream bis = new BufferedInputStream(is);
83 props_ = new Properties();
84 props_.load(bis);
85 bis.close();
87 String file1 = props_.getProperty(FILE1, "");
88 String file2 = props_.getProperty(FILE2, "");
89 String tagsString = props_.getProperty(IGNORE_TAGS, "");
90 String output = props_.getProperty("debug.output", "System.out");
91 setOutput(output);
92 tags_ = parseTags(tagsString);
95 /**
96 * diff 2 xml, but overwrite the property file's file1/2 setting with
97 * the input argument
99 public boolean diff(String file1, String file2) throws IOException {
100 file1_ = file1;
101 file2_ = file2;
102 return diff();
105 public boolean diff() throws IOException {
107 boolean result = false;
109 writer_.println("parsing "+ file1_ + "...");
110 // parse the Xml file
111 Document doc1 = parseXml(file1_);
113 writer_.println("parsing "+ file1_ + "...");
114 Document doc2 = parseXml(file2_);
116 if (doc1 != null && doc2 != null) {
117 writer_.println("diffing "+ file1_ + " & " + file2_ + "...");
118 result = compareNode(doc1, doc2);
120 return result;
123 private void diffLog(String errMsg, Node node1, Node node2) {
125 String node1Str = "";
126 String node2Str = "";
128 if (node1 != null) {
129 node1Str = "[Type]:" + nodeInfo(node1) +
130 " [Name]:" + node1.getNodeName();
131 if (node1.getNodeValue() != null)
132 node1Str += " [Value]:" + node1.getNodeValue();
135 if (node2 != null) {
136 node2Str = "[Type]:" + nodeInfo(node2) +
137 " [Name]:" + node2.getNodeName();
138 if (node2.getNodeValue() != null)
139 node2Str += " [Value]:" + node2.getNodeValue();
142 writer_.println(errMsg);
143 writer_.println(" Node1 - " + node1Str);
144 writer_.println(" Node2 - " + node2Str);
147 private String nodeInfo(Node node) {
149 String str = null;
150 switch (node.getNodeType()) {
152 case Node.ELEMENT_NODE:
153 str = "ELEMENT";
154 break;
155 case Node.ATTRIBUTE_NODE:
156 str = "ATTRIBUTE";
157 break;
158 case Node.TEXT_NODE:
159 str = "TEXT";
160 break;
161 case Node.CDATA_SECTION_NODE:
162 str = "CDATA_SECTION";
163 break;
164 case Node.ENTITY_REFERENCE_NODE:
165 str = "ENTITY_REFERENCE";
166 break;
167 case Node.ENTITY_NODE:
168 str = "ENTITY";
169 break;
170 case Node.PROCESSING_INSTRUCTION_NODE:
171 str = "PROCESSING_INSTRUCTION";
172 break;
173 case Node.COMMENT_NODE:
174 str = "COMMENT";
175 break;
176 case Node.DOCUMENT_NODE:
177 str = "DOCUMENT";
178 break;
179 case Node.DOCUMENT_TYPE_NODE:
180 str = "DOCUMENT_TYPE";
181 break;
182 case Node.DOCUMENT_FRAGMENT_NODE:
183 str = "DOCUMENT_FRAGMENT";
184 break;
185 case Node.NOTATION_NODE:
186 str = "NOTATION";
187 break;
189 return str;
192 private boolean ignoreTag(String nodeName) {
195 if (tags_ != null) {
196 for (int i = 0; i < tags_.length; i++) {
197 if (tags_[i].equals(nodeName))
198 return true;
201 return false;
204 // for future use if we want to compare attributes
205 private boolean attributesEqual(Node node1, Node node2) {
206 return true;
209 private boolean compareNode(Node node1, Node node2) {
210 boolean equal = false;
212 while (true) {
214 if (node1 == null && node2 == null) {
215 equal = true;
216 break;
217 } else if (node1 == null || node2 == null) {
218 diffLog("DIFF: one of the node is null", node1, node2);
219 break;
222 if (node1.getNodeType() != node2.getNodeType()) {
223 diffLog("DIFF: nodetype is different", node1, node2);
224 break;
227 if (node1.getNodeName() == null && node2.getNodeName() == null) {
228 // empty
229 } else if (node1.getNodeName() == null ||
230 node2.getNodeName() == null) {
231 diffLog("DIFF: one of the nodeName is null", node1, node2);
232 break;
233 } else if (!node1.getNodeName().equals(node2.getNodeName())) {
234 diffLog("DIFF: nodeName is different", node1, node2);
235 break;
238 if (ignoreTag(node1.getNodeName())) {
239 diffLog("DIFF: Some tag(s) is ignored", node1, node2);
240 equal = true;
241 break;
244 if (node1.getNodeValue() == null && node2.getNodeValue() == null) {
245 // empty
246 } else if (node1.getNodeValue() == null ||
247 node2.getNodeValue() == null) {
248 diffLog("DIFF: one of the nodevalue is null", node1, node2);
249 break;
250 } else if (!node1.getNodeValue().equals(node2.getNodeValue())) {
251 diffLog("DIFF: nodeValue is different", node1, node2);
252 break;
255 // try to compare attributes if necessary
256 if (!attributesEqual(node1, node2))
257 break;
259 NodeList node1Children = node1.getChildNodes();
260 NodeList node2Children = node2.getChildNodes();
262 // number of children have to be the same
263 if (node1Children == null && node2Children == null) {
264 equal = true;
265 break;
268 if (node1Children == null || node2Children == null) {
269 diffLog("DIFF: one node's children is null", node1, node2);
270 break;
273 if (node1Children.getLength() != node2Children.getLength()) {
274 diffLog("DIFF: num of children is different", node1, node2);
275 break;
278 // compare all the childrens
279 equal = true;
281 for (int i = 0; i < node1Children.getLength(); i++) {
282 if (!compareNode(node1Children.item(i),
283 node2Children.item(i))) {
284 equal = false;
285 break;
288 break;
291 return equal;
294 private Document parseXml (String filename) throws IOException {
296 Document w3cDocument = null;
298 FileInputStream fis;
300 try {
301 fis = new FileInputStream(filename);
302 } catch (FileNotFoundException ex) {
303 ex.printStackTrace(writer_);
304 writer_.println(ex.getMessage());
305 return w3cDocument;
308 /** factory for DocumentBuilder objects */
309 DocumentBuilderFactory factory = null;
310 factory = DocumentBuilderFactory.newInstance();
311 factory.setNamespaceAware(true);
312 factory.setValidating(false);
314 /** DocumentBuilder object */
315 DocumentBuilder builder = null;
317 try {
318 builder = factory.newDocumentBuilder();
319 } catch (ParserConfigurationException ex) {
320 ex.printStackTrace(writer_);
321 writer_.println(ex.getMessage());
322 return null;
326 builder.setErrorHandler(
327 new org.xml.sax.ErrorHandler() {
328 // ignore fatal errors (an exception is guaranteed)
329 public void fatalError(SAXParseException e)
330 throws SAXException {
331 throw e;
334 public void error(SAXParseException e)
335 throws SAXParseException {
336 // make sure validation error is thrown.
337 throw e;
340 public void warning(SAXParseException e)
341 throws SAXParseException {
346 try {
347 w3cDocument = builder.parse(fis);
348 w3cDocument.getDocumentElement().normalize();
349 } catch (SAXException ex) {
350 ex.printStackTrace(writer_);
351 writer_.println(ex.getMessage());
352 return w3cDocument;
355 return w3cDocument;
358 private String [] parseTags(String tagsString) {
359 Vector tagsVector = new Vector();
360 if (tagsString.length() == 0)
361 return null;
363 int start = 0;
364 int end = 0;
365 // break the tag string into a vector of strings by words
366 for (end = tagsString.indexOf(" ", start);
367 end != -1 ;
368 start = end + 1, end = tagsString.indexOf(" ", start)) {
369 tagsVector.add(tagsString.substring(start,end));
372 tagsVector.add(tagsString.substring(start,tagsString.length()));
374 // convert the vector to array
375 String[] tags= new String[tagsVector.size()];
376 tagsVector.copyInto(tags);
378 return tags;
383 * Set the output to the specified argument.
384 * This method is only used internally to prevent
385 * invalid string parameter.
387 * @param str output specifier
389 private static void setOutput(String str) {
391 if (writer_ == null) {
393 if (str.equals("System.out")) {
395 setOutput(System.out);
397 } else if (str.equals("System.err")) {
399 setOutput(System.err);
401 } else {
403 try {
405 setOutput(new FileWriter(str));
407 } catch (IOException e) {
409 e.printStackTrace(System.err);
416 * Set the output to an OutputStream object.
418 * @param stream OutputStream object
421 private static void setOutput(OutputStream stream) {
423 setOutput(new OutputStreamWriter(stream));
427 * Set the Writer object to manage the output.
429 * @param w Writer object to write out
432 private static void setOutput(Writer w) {
434 if (writer_ != null) {
436 writer_.close();
439 writer_ = new PrintWriter(new BufferedWriter(w), true);
442 public static void main(String args[]) throws IOException {
444 if (args.length != 0 && args.length != 2) {
445 System.out.println("Usage: XmlDiff [<file1> <file2>].");
446 return;
449 XmlDiff xmldiff = new XmlDiff();
451 boolean same = false;
452 if (args.length == 2) {
453 same = xmldiff.diff(args[0], args[1]);
454 } else {
455 same = xmldiff.diff();
458 System.out.println("Diff result: " + same);