All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ow2.spec.testengine.SignatureCompare Maven / Gradle / Ivy

There is a newer version: 1.0.13
Show newest version
/**
 * EasyBeans
 * Copyright (C) 2006 Bull S.A.S.
 * Contact: [email protected]
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * --------------------------------------------------------------------------
 * $Id: SignatureCompare.java 5276 2010-01-08 16:22:04Z benoitf $
 * --------------------------------------------------------------------------
 */

package org.ow2.spec.testengine;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.ow2.spec.testengine.metadata.AnnotationMetadata;
import org.ow2.spec.testengine.metadata.ClassMetadata;
import org.ow2.spec.testengine.metadata.EnumAnnotationMetadata;
import org.ow2.spec.testengine.metadata.FieldMetadata;
import org.ow2.spec.testengine.metadata.InnerClassMetadata;
import org.ow2.spec.testengine.metadata.MethodMetadata;
import org.ow2.spec.testengine.xml.DocumentParser;
import org.ow2.spec.testengine.xml.DocumentParserException;
import org.ow2.spec.testengine.xml.XMLUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class SignatureCompare {

    private static final String APICHECK_NS = "http://org.ow2.spec/ns/apicheck";

    private static final String PACKAGE_ELEMENT = "package";

    private static final String CLASS_ELEMENT = "class";

    private static final String INTERFACE_ELEMENT = "interface";

    private static final String METHOD_ELEMENT = "method";

    private static final String ANNOTATION_ELEMENT = "annotation";

    private static final String ENUM_ANNOTATION_ELEMENT = "enum-annotation";

    private static final String FIELD_ELEMENT = "field";

    private static final String INNER_CLASS_ELEMENT = "inner-class";

    private static final String EXCEPTION_ELEMENT = "exception";

    /**
     * Jar File to analyze.
     */
    private JarFile jarFile = null;

    /**
     * URL of the XML data file.
     */
    private URL urlXML = null;

    /**
     * Reference build from XML file
* Map between package name and Map of . */ private Map> referencePackageClassesMetadataMap = null; /** * Map build ith jar file for the check
* Map between package name and Map of . */ private Map> packageClassesMetadataMap = null; /** * Analyzer visitor. (ASM visitor). */ private AnalyzerClassVisitor analyzerClassVisitor = null; /** * Files to analyze */ private List allFiles = null; /** * Only for exceptions. */ private File tmpFile; public SignatureCompare(String[] args) { if (args == null) { usage(); throw new IllegalArgumentException("No arguments"); } if (args.length < 2) { usage(); throw new IllegalArgumentException("Needs at least 2 arguments"); } tmpFile = new File(args[0]); if (!tmpFile.exists()) { usage(); throw new IllegalArgumentException("The file '" + tmpFile.getAbsolutePath() + "' doesn't exists"); } // first arg = JAR File if (tmpFile.isDirectory()) { allFiles = new ArrayList(); addFilesFromDirectory(allFiles, tmpFile); } else { try { jarFile = new JarFile(tmpFile); } catch (IOException e) { usage(); throw new IllegalArgumentException("The argument '" + args[0] + "' is not a valid JAR file.", e); } } // Second arg = output dir ClassLoader cl = Thread.currentThread().getContextClassLoader(); urlXML = cl.getResource(args[1]); if (urlXML == null) { throw new IllegalArgumentException("Resource '" + args[1] + "' not found in the classloader '" + cl + "'."); } referencePackageClassesMetadataMap = new HashMap>(); packageClassesMetadataMap = new HashMap>(); analyzerClassVisitor = new AnalyzerClassVisitor(packageClassesMetadataMap); } public void check() throws IOException { readXML(urlXML); if (jarFile != null) { analyzeJarFile(); } if (allFiles != null) { analyzeDirectory(); } SignatureResultSet rs = compare(); if (rs.hasErrors()) { throw new IOException(rs.toString()); } } private void addFilesFromDirectory(List allFiles, File directory) { File[] files = directory.listFiles(); for (File f : files) { if (f.isFile()) { allFiles.add(f); } else { addFilesFromDirectory(allFiles, f); } } } private void analyzeDirectory() throws IOException { ClassVisitor classVisitor = new SerialVersionUIDReader(analyzerClassVisitor); for (File f : allFiles) { if (f.getName().toLowerCase().endsWith(".class")) { InputStream inputStream = new FileInputStream(f); new ClassReader(inputStream).accept(classVisitor, 0); inputStream.close(); } } } private void analyzeJarFile() throws IOException { ClassVisitor classVisitor = new SerialVersionUIDReader(analyzerClassVisitor); Enumeration entries = jarFile.entries(); while (entries.hasMoreElements()) { JarEntry jarEntry = entries.nextElement(); if (jarEntry.getName().toLowerCase().endsWith(".class")) { InputStream inputStream = jarFile.getInputStream(jarEntry); new ClassReader(inputStream).accept(classVisitor, 0); } } } // compare private SignatureResultSet compare() { SignatureResultSet rs = new SignatureResultSet(); Set packagesOfFile = packageClassesMetadataMap.keySet(); for (String packageName : packagesOfFile) { if (packageName.startsWith("org.ow2")) { continue; } System.out.println("Checking package '" + packageName + "'."); // reference = package loaded from XML Map referenceClassMetadataMap = referencePackageClassesMetadataMap.get(packageName); // analyzed Map analyzedClassMetadataMap = packageClassesMetadataMap.get(packageName); // Ignore it if (referenceClassMetadataMap == null) { referenceClassMetadataMap = new HashMap(); } int referenceSize = referenceClassMetadataMap.size(); int analyzedSite = analyzedClassMetadataMap.size(); // compare to each other the class // first check from reference Set referenceClassKeys = referenceClassMetadataMap.keySet(); for (String className : referenceClassKeys) { if (!analyzedClassMetadataMap.containsKey(className)) { rs.addError(new ComparisonError("Missing class '" + className + "' in analyzed jar file '" + tmpFile.getName() + "'.")); } } // compare from analyzed to reference Set analyzedClassKeys = analyzedClassMetadataMap.keySet(); for (String className : analyzedClassKeys) { if (!referenceClassMetadataMap.containsKey(className)) { rs.addError(new ComparisonError("The class '" + className + "' is present in the jar file '" + tmpFile.getName() + "' but not in the reference.")); } } if (referenceSize != analyzedSite) { rs.addError(new ComparisonError("Invalid package size")); } // As each class is present in the both packages, compare each of // them for (String className : referenceClassKeys) { ClassMetadata referenceClassMetadata = referenceClassMetadataMap.get(className); ClassMetadata analyzedClassMetadata = analyzedClassMetadataMap.get(className); if (analyzedClassMetadata == null) { rs.addError(new ComparisonError("'" + className +"' is missing.")); } else { referenceClassMetadata.compare(analyzedClassMetadata, rs); } } } return rs; } // read XML and fill struct private void readXML(URL url) { // Parse the XML file and build all configuration process. Document xmlConfigurationDocument = null; try { xmlConfigurationDocument = DocumentParser.getDocument(url, false, null); } catch (DocumentParserException e) { throw new IllegalArgumentException("Cannot get a document on the given url '" + url + "'.", e); } // Get the root element Element rootElement = xmlConfigurationDocument.getDocumentElement(); NodeList packagesList = rootElement.getElementsByTagNameNS(APICHECK_NS, PACKAGE_ELEMENT); // Loop on this list for (int i = 0; i < packagesList.getLength(); i++) { Element packageElement = (Element) packagesList.item(i); // Get name String packageName = XMLUtils.getAttributeValue(packageElement, "name"); // Add package if not existing Map classMetadataMap = referencePackageClassesMetadataMap.get(packageName); if (classMetadataMap == null) { classMetadataMap = new HashMap(); referencePackageClassesMetadataMap.put(packageName, classMetadataMap); } // Now analyze class element of package NodeList classesList = packageElement.getElementsByTagNameNS(APICHECK_NS, CLASS_ELEMENT); // Loop on this list for (int c = 0; c < classesList.getLength(); c++) { Element classElement = (Element) classesList.item(c); String className = XMLUtils.getAttributeValue(classElement, "name"); String classSuperName = XMLUtils.getAttributeValue(classElement, "super-name"); String classAccess = XMLUtils.getAttributeValue(classElement, "access"); String classSignature = XMLUtils.getAttributeValue(classElement, "signature"); String classUid = XMLUtils.getAttributeValue(classElement, "uid"); // Interfaces String[] interfaces = null; NodeList interfacesList = classElement.getElementsByTagNameNS(APICHECK_NS, INTERFACE_ELEMENT); if (interfacesList.getLength() > 0) { interfaces = new String[interfacesList.getLength()]; for (int j = 0; j < interfacesList.getLength(); j++) { Element interfaceElement = (Element) interfacesList.item(j); String interfaceName = XMLUtils.getAttributeValue(interfaceElement, "name"); interfaces[j] = interfaceName; } } // build metadata ClassMetadata classMetadata = new ClassMetadata(Integer.valueOf(classAccess), className, classSignature, classSuperName, interfaces); if (classUid != null) { classMetadata.setUID(Long.valueOf(classUid)); } // store classMetadataMap.put(className, classMetadata); // Analyze class sub elements // like methods NodeList methodsList = classElement.getElementsByTagNameNS(APICHECK_NS, METHOD_ELEMENT); for (int m = 0; m < methodsList.getLength(); m++) { Element methodElement = (Element) methodsList.item(m); String methodName = XMLUtils.getAttributeValue(methodElement, "name"); String methodDesc = XMLUtils.getAttributeValue(methodElement, "desc"); String methodAccess = XMLUtils.getAttributeValue(methodElement, "access"); String methodSignature = XMLUtils.getAttributeValue(methodElement, "signature"); // Exceptions String[] methodExceptions = null; NodeList methodExceptionsList = methodElement.getElementsByTagNameNS(APICHECK_NS, EXCEPTION_ELEMENT); // no exceptions --> null value if (methodExceptionsList.getLength() > 0) { methodExceptions = new String[methodExceptionsList.getLength()]; for (int j = 0; j < methodExceptionsList.getLength(); j++) { Element methodExceptionElement = (Element) methodExceptionsList.item(j); String methodExceptionName = XMLUtils.getAttributeValue(methodExceptionElement, "name"); methodExceptions[j] = methodExceptionName; } } MethodMetadata methodMetadata = new MethodMetadata(Integer.valueOf(methodAccess), methodName, methodDesc, methodSignature, methodExceptions); classMetadata.addMethodMetadata(methodMetadata); } // Now fields NodeList fieldsList = classElement.getElementsByTagNameNS(APICHECK_NS, FIELD_ELEMENT); for (int f = 0; f < fieldsList.getLength(); f++) { Element fieldElement = (Element) fieldsList.item(f); String fieldName = XMLUtils.getAttributeValue(fieldElement, "name"); String fieldDesc = XMLUtils.getAttributeValue(fieldElement, "desc"); String fieldAccess = XMLUtils.getAttributeValue(fieldElement, "access"); String fieldValue = XMLUtils.getAttributeValue(fieldElement, "value"); String fieldSignature = XMLUtils.getAttributeValue(fieldElement, "signature"); FieldMetadata fieldMetadata = new FieldMetadata(Integer.valueOf(fieldAccess), fieldName, fieldDesc, fieldSignature, fieldValue); classMetadata.addFieldMetadata(fieldMetadata); } // Now inner class NodeList innerClassesList = classElement.getElementsByTagNameNS(APICHECK_NS, INNER_CLASS_ELEMENT); for (int k = 0; k < innerClassesList.getLength(); k++) { Element innerClassElement = (Element) innerClassesList.item(k); String innerClassName = XMLUtils.getAttributeValue(innerClassElement, "name"); String innerClassOuterName = XMLUtils.getAttributeValue(innerClassElement, "outer-name"); String innerClassInnerName = XMLUtils.getAttributeValue(innerClassElement, "inner-name"); String innerClassAccess = XMLUtils.getAttributeValue(innerClassElement, "access"); InnerClassMetadata innerClassMetadata = new InnerClassMetadata(innerClassName, innerClassOuterName, innerClassInnerName, Integer.valueOf(innerClassAccess)); classMetadata.addInnerClassMetadata(innerClassMetadata); } // Annotations NodeList annotationsList = classElement.getElementsByTagNameNS(APICHECK_NS, ANNOTATION_ELEMENT); for (int a = 0; a < annotationsList.getLength(); a++) { Element annotationElement = (Element) annotationsList.item(a); String annotationDesc = XMLUtils.getAttributeValue(annotationElement, "desc"); String annotationVisible = XMLUtils.getAttributeValue(annotationElement, "visible"); AnnotationMetadata annotationMetadata = new AnnotationMetadata(annotationDesc, Boolean .valueOf(annotationVisible)); classMetadata.addAnnotationMetadata(annotationMetadata); // enum-annotation NodeList enumAnnotationsList = annotationElement.getElementsByTagNameNS(APICHECK_NS, ENUM_ANNOTATION_ELEMENT); for (int e = 0; e < enumAnnotationsList.getLength(); e++) { Element enumAnnotationElement = (Element) enumAnnotationsList.item(e); String enumAnnotationName = XMLUtils.getAttributeValue(enumAnnotationElement, "name"); String enumAnnotationDesc = XMLUtils.getAttributeValue(enumAnnotationElement, "desc"); String enumAnnotationValue = XMLUtils.getAttributeValue(enumAnnotationElement, "value"); EnumAnnotationMetadata enumAnnotationMetadata = new EnumAnnotationMetadata(enumAnnotationName, enumAnnotationDesc, enumAnnotationValue); annotationMetadata.addEnumAnnotationMetadata(enumAnnotationMetadata); } } } } System.out.println("packages = " + referencePackageClassesMetadataMap.keySet()); } /** * @param args */ public static void main(String[] args) throws IOException { String[] newArgs = new String[2]; newArgs[0] = "/home/test/workspace/ow2-spec/ee/ejb-3.0/target/ow2-ejb-3.0-spec.jar"; //"ejb-3.0/target/ow2-ejb-3.0-spec.jar" newArgs[1] = "/tmp/report"; SignatureCompare signatureCompare = new SignatureCompare(newArgs); signatureCompare.check(); } public void usage() { System.out.println("Usage : SignatureCompare "); System.out.println("Usage : example : SignatureCompare /tmp/ejb.jar /tmp/data"); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy