blob: 63a66f765d637416c466e425d57214819580109b [file] [log] [blame]
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.pack.verify;
import java.io.*;
import java.util.*;
import java.util.jar.*;
import xmlkit.*;
public class ClassCompare {
/*
* @author ksrini
*/
private static XMLKit.Element getXMLelement(InputStream is,
boolean ignoreUnkAttrs,
List<String> ignoreElements) throws IOException {
ClassReader cr = new ClassReader();
cr.keepOrder = false;
XMLKit.Element e = cr.readFrom(is);
if (ignoreElements != null) {
XMLKit.Filter filter = XMLKit.elementFilter(ignoreElements);
e.removeAllInTree(filter);
}
if (ignoreUnkAttrs == true) {
// This removes any unknown attributes
e.removeAllInTree(XMLKit.elementFilter("Attribute"));
}
return e;
}
private static String getXMLPrettyString(XMLKit.Element e) throws IOException {
StringWriter out = new StringWriter();
e.writePrettyTo(out);
return out.toString();
}
private static boolean compareClass0(JarFile jf1, JarFile jf2,
JarEntry je, boolean ignoreUnkAttrs,
List<String> ignoreElements)
throws IOException {
InputStream is1 = jf1.getInputStream(je);
InputStream is2 = jf2.getInputStream(je);
// First we try to compare the bits if they are the same
boolean bCompare = JarFileCompare.compareStreams(is1, is2);
// If they are the same there is nothing more to do.
if (bCompare) {
Globals.println("+++" + je.getName() + "+++\t"
+ "b/b:PASS");
return bCompare;
}
is1.close();
is2.close();
is1 = jf1.getInputStream(je);
is2 = jf2.getInputStream(je);
XMLKit.Element e1 = getXMLelement(is1, ignoreUnkAttrs, ignoreElements);
XMLKit.Element e2 = getXMLelement(is2, ignoreUnkAttrs, ignoreElements);
Globals.print("+++" + je.getName() + "+++\t"
+ e1.size() + "/" + e1.size() + ":");
boolean result = true;
if (e1.equals(e2)) {
Globals.println("PASS");
} else {
Globals.println("FAIL");
Globals.log("Strings differs");
Globals.log(getXMLPrettyString(e1));
Globals.log("----------");
Globals.log(getXMLPrettyString(e2));
result = false;
}
return result;
}
/*
* Given two Class Paths could be jars the first being a reference
* will execute a series of comparisons on the classname specified
* The className could be null in which case it will iterate through
* all the classes, otherwise it will compare one class and exit.
*/
public static boolean compareClass(String jar1, String jar2,
String className, boolean ignoreUnkAttrs,
List<String> ignoreElements)
throws IOException {
Globals.println("Unknown attributes ignored:" + ignoreUnkAttrs);
if (ignoreElements != null) {
Globals.println(ignoreElements.toString());
}
JarFile jf1 = new JarFile(jar1);
JarFile jf2 = new JarFile(jar2);
boolean result = true;
if (className == null) {
for (JarEntry je1 : Collections.list((Enumeration<JarEntry>) jf1.entries())) {
if (je1.getName().endsWith(".class")) {
JarEntry je2 = jf2.getJarEntry(je1.getName());
boolean pf = compareClass0(jf1, jf2, je1, ignoreUnkAttrs, ignoreElements);
if (result == true) {
result = pf;
}
}
}
} else {
JarEntry je1 = jf1.getJarEntry(className);
result = compareClass0(jf1, jf2, je1, ignoreUnkAttrs, ignoreElements);
}
if (result == false) {
throw new RuntimeException("Class structural comparison failure");
}
return result;
}
public static boolean compareClass(String jar1, String jar2,
String className) throws IOException {
Stack<String> s = new Stack();
if (Globals.ignoreDebugAttributes()) {
s = new Stack();
s.push("LocalVariable");
s.push("LocalVariableType");
s.push("LineNumber");
s.push("SourceFile");
}
return compareClass(jar1, jar2, className, Globals.ignoreUnknownAttributes(), s);
}
}