Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.ow2.spec.testengine.SignatureCompare Maven / Gradle / Ivy
/**
* 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");
}
}