/* * 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); } }