[Clirr-devel] CVS: clirr/core/src/java/net/sf/clirr/core Checker.java,1.7,1.8 CheckerException.java,
Status: Alpha
Brought to you by:
lkuehne
From: <lk...@us...> - 2005-08-26 05:36:01
|
Update of /cvsroot/clirr/clirr/core/src/java/net/sf/clirr/core In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8502/src/java/net/sf/clirr/core Modified Files: Checker.java CheckerException.java ScopeSelector.java Log Message: moved clirr implementation to new SPI infrastructure Index: Checker.java =================================================================== RCS file: /cvsroot/clirr/clirr/core/src/java/net/sf/clirr/core/Checker.java,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- Checker.java 7 Aug 2005 13:54:03 -0000 1.7 +++ Checker.java 26 Aug 2005 05:35:53 -0000 1.8 @@ -32,6 +32,7 @@ import java.net.MalformedURLException; import java.net.URLClassLoader; +import net.sf.clirr.core.internal.bcel.BcelJavaType; import net.sf.clirr.core.internal.checks.ClassHierarchyCheck; import net.sf.clirr.core.internal.checks.ClassScopeCheck; import net.sf.clirr.core.internal.checks.ClassModifierCheck; @@ -42,12 +43,13 @@ import net.sf.clirr.core.internal.ApiDiffDispatcher; import net.sf.clirr.core.internal.ClassChangeCheck; import net.sf.clirr.core.internal.CoIterator; -import net.sf.clirr.core.internal.JavaClassNameComparator; import net.sf.clirr.core.internal.ExceptionUtil; +import net.sf.clirr.core.internal.NameComparator; +import net.sf.clirr.core.spi.JavaType; +import net.sf.clirr.core.spi.Scope; import org.apache.bcel.classfile.JavaClass; import org.apache.bcel.classfile.ClassParser; -import org.apache.bcel.util.ClassSet; import org.apache.bcel.util.Repository; import org.apache.bcel.util.ClassLoaderRepository; @@ -169,10 +171,10 @@ classSelector = new ClassSelector(ClassSelector.MODE_UNLESS); } - final ClassSet origClasses = + final JavaType[] origClasses = createClassSet(origJars, origThirdPartyLoader, classSelector); - final ClassSet newClasses = + final JavaType[] newClasses = createClassSet(newJars, newThirdPartyLoader, classSelector); reportDiffs(origClasses, newClasses); @@ -190,7 +192,7 @@ * old and new jars are to be compared. This parameter may be null, in * which case all classes in the old and new jars are compared. */ - private static ClassSet createClassSet( + private static JavaType[] createClassSet( File[] jarFiles, ClassLoader thirdPartyClasses, ClassFilter classSelector) throws CheckerException { @@ -204,7 +206,7 @@ Repository repository = new ClassLoaderRepository(classLoader); - ClassSet ret = new ClassSet(); + List selected = new ArrayList(); for (int i = 0; i < jarFiles.length; i++) { @@ -228,13 +230,15 @@ JavaClass clazz = extractClass(zipEntry, zip, repository); if (classSelector.isSelected(clazz)) { - ret.add(clazz); + selected.add(new BcelJavaType(clazz)); repository.storeClass(clazz); } } } } + JavaType[] ret = new JavaType[selected.size()]; + selected.toArray(ret); return ret; } @@ -312,7 +316,7 @@ * compatibility with compatibilityBaseline */ private void reportDiffs( - ClassSet compatibilityBaseline, ClassSet currentVersion) + JavaType[] compatibilityBaseline, JavaType[] currentVersion) throws CheckerException { fireStart(); @@ -321,29 +325,26 @@ } private void runClassChecks( - ClassSet compatBaseline, ClassSet currentVersion) + JavaType[] compat, JavaType[] current) throws CheckerException { - JavaClass[] compat = compatBaseline.toArray(); - JavaClass[] current = currentVersion.toArray(); - CoIterator iter = new CoIterator( - JavaClassNameComparator.COMPARATOR, compat, current); + new NameComparator(), compat, current); while (iter.hasNext()) { iter.next(); - JavaClass compatBaselineClass = (JavaClass) iter.getLeft(); - JavaClass currentClass = (JavaClass) iter.getRight(); + JavaType compatBaselineClass = (JavaType) iter.getLeft(); + JavaType currentClass = (JavaType) iter.getRight(); if (compatBaselineClass == null) { - if (!scopeSelector.isSelected(ScopeSelector.getClassScope(currentClass))) + if (!scopeSelector.isSelected(currentClass.getEffectiveScope())) { continue; } - final String className = currentClass.getClassName(); + final String className = currentClass.getName(); final ApiDifference diff = new ApiDifference( MSG_CLASS_ADDED, Severity.INFO, className, @@ -352,14 +353,14 @@ } else if (currentClass == null) { - final ScopeSelector.Scope classScope = ScopeSelector.getClassScope(compatBaselineClass); + final Scope classScope = compatBaselineClass.getEffectiveScope(); if (!scopeSelector.isSelected(classScope)) { continue; } - final String className = compatBaselineClass.getClassName(); + final String className = compatBaselineClass.getName(); final Severity severity = classScope.isLessVisibleThan( - ScopeSelector.SCOPE_PROTECTED) ? Severity.INFO : Severity.ERROR; + Scope.PROTECTED) ? Severity.INFO : Severity.ERROR; final ApiDifference diff = new ApiDifference( MSG_CLASS_REMOVED, severity, className, Index: CheckerException.java =================================================================== RCS file: /cvsroot/clirr/clirr/core/src/java/net/sf/clirr/core/CheckerException.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- CheckerException.java 3 Aug 2005 17:16:10 -0000 1.3 +++ CheckerException.java 26 Aug 2005 05:35:53 -0000 1.4 @@ -30,7 +30,7 @@ * Unchecked exceptions are used for errors that are due to bugs within * clirr code (assertion-violation type problems). */ -public class CheckerException extends Exception +public class CheckerException extends RuntimeException // TODO: revert this back to Exception to match the class doc above { public CheckerException(String msg) { Index: ScopeSelector.java =================================================================== RCS file: /cvsroot/clirr/clirr/core/src/java/net/sf/clirr/core/ScopeSelector.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- ScopeSelector.java 3 Aug 2005 17:16:13 -0000 1.5 +++ ScopeSelector.java 26 Aug 2005 05:35:53 -0000 1.6 @@ -18,16 +18,8 @@ ////////////////////////////////////////////////////////////////////////////// package net.sf.clirr.core; -import org.apache.bcel.Constants; -import org.apache.bcel.classfile.AccessFlags; -import org.apache.bcel.classfile.Attribute; -import org.apache.bcel.classfile.ConstantClass; -import org.apache.bcel.classfile.ConstantPool; -import org.apache.bcel.classfile.ConstantUtf8; -import org.apache.bcel.classfile.InnerClass; -import org.apache.bcel.classfile.InnerClasses; -import org.apache.bcel.classfile.JavaClass; -import org.apache.bcel.util.Repository; +import net.sf.clirr.core.spi.Scope; +import net.sf.clirr.core.spi.Scoped; /** * Selects zero or more java scope values (public, protected, package, @@ -42,62 +34,7 @@ */ public final class ScopeSelector { - /** - * Represents an "accessibility" level for a java class, field or method. - * <p> - * Change of access rights from lower to higher visibility rating is a - * binary-compatible change. Change of access rights from higher to - * lower is a binary-incompatible change. - * <p> - * Public > Protected > Package > Private - */ - public static final class Scope - { - private int vis; - private String desc; - private String decl; - - private Scope(int vis, String desc, String decl) - { - this.vis = vis; - this.desc = desc; - this.decl = decl; - } - - public boolean isMoreVisibleThan(Scope v) - { - return this.vis > v.vis; - } - - public boolean isLessVisibleThan(Scope v) - { - return this.vis < v.vis; - } - - public String getDesc() - { - return desc; - } - - public String getDecl() - { - return decl; - } - } - - /** Object representing private scoped objects. */ - public static final Scope SCOPE_PRIVATE = new Scope(0, "private", "private"); - - /** Object representing package scoped objects. */ - public static final Scope SCOPE_PACKAGE = new Scope(1, "package", ""); - - /** Object representing protected scoped objects. */ - public static final Scope SCOPE_PROTECTED = new Scope(2, "protected", "protected"); - - /** Object representing public scoped objects. */ - public static final Scope SCOPE_PUBLIC = new Scope(3, "public", "public"); - - private Scope scope = SCOPE_PROTECTED; + private Scope scope = Scope.PROTECTED; /** * Construct an instance which selects public and protected objects and @@ -158,9 +95,9 @@ * @param object is the object whose scope is to be checked. * @return true if the object is selected. */ - public boolean isSelected(AccessFlags object) + public boolean isSelected(Scoped scoped) { - return !getScope(object).isLessVisibleThan(scope); + return !scoped.getEffectiveScope().isLessVisibleThan(scope); } /** @@ -175,205 +112,5 @@ return !scope.isLessVisibleThan(this.scope); } - /** - * Given a BCEL object, return the string which would be used in java - * source code to declare that object's scope. <p> - * <p> - * Note that BCEL classes Field and Method inherit from the AccessFlags - * base class and so are valid parameters to this method. - * <p> - * Note that despite JavaClass objects extending AccessFlags, the - * methods which determine the accessibility of a JavaClass fail - * miserably (bad bcel design) for nested classes. Therefore this - * method <i>must not</i> be passed a JavaClass object as a parameter. - * If this is done, a RuntimeException will be thrown to indicate a - * programmer error. - */ - public static String getScopeDecl(AccessFlags object) - { - return getScope(object).getDecl(); - } - - /** - * Given an integer representing an object's access flags, return the - * string which would be used in java source code to declare that object's - * scope. - * <p> - * Note that this method gives the wrong results for JavaClass objects - * which are nested classes. Use getClassScope(jclass).getDecl() instead. - */ - public static String getScopeDecl(int accessFlags) - { - return getScope(accessFlags).getDecl(); - } - - /** - * Given a BCEL object, return a string indicating whether the object is - * public/protected/private/package scope. This is similar to - * getScopeName, except for package-scope objects where this method - * returns the string "package". - * <p> - * Note that BCEL classes Field and Method inherit from the AccessFlags - * base class and so are valid parameters to this method. - * <p> - * Note that despite JavaClass objects extending AccessFlags, the - * methods which determine the accessibility of a JavaClass fail - * miserably (bad bcel design) for nested classes. Therefore this - * method <i>must not</i> be passed a JavaClass object as a parameter. - * If this is done, a RuntimeException will be thrown to indicate a - * programmer error. - */ - public static String getScopeDesc(AccessFlags object) - { - return getScope(object).getDesc(); - } - - /** - * Given an integer representing the object's access flags, return a string - * indicating whether the object is public/protected/private/package scope. - * <p> - * This is similar to getScopeName, except for package-scope objects where - * this method returns the string "package". - * <p> - * Note that this method gives the wrong results for JavaClass objects - * which are nested classes. Use getClassScope(jclass).getDesc() instead. - */ - public static String getScopeDesc(int accessFlags) - { - return getScope(accessFlags).getDesc(); - } - - /** - * Get a Scope object representing the accessibility of the specified - * object. - * <p> - * Note that BCEL classes Field and Method inherit from the AccessFlags - * base class and so are valid parameters to this method. - * <p> - * Note that despite JavaClass objects extending AccessFlags, the - * methods which determine the accessibility of a JavaClass fail - * miserably (bad bcel design) for nested classes. Therefore this - * method <i>must not</i> be passed a JavaClass object as a parameter. - * If this is done, a RuntimeException will be thrown to indicate a - * programmer error. Use getClassScope instead. - */ - public static Scope getScope(AccessFlags object) - { - if (object instanceof JavaClass) - { - throw new RuntimeException( - "getScope called for JavaClass object. This is not permitted;" - + " use method getClassScope for JavaClass objects."); - - } - - return getScope(object.getAccessFlags()); - } - - /** - * Get a Scope object representing the accessibility of the specified - * object. - * <p> - * Note that this method gives the wrong results for JavaClass objects - * which are nested classes. Use getClassScope(jclass) instead. - */ - public static Scope getScope(int accessFlags) - { - if ((accessFlags & Constants.ACC_PUBLIC) > 0) - { - return SCOPE_PUBLIC; - } - - if ((accessFlags & Constants.ACC_PROTECTED) > 0) - { - return SCOPE_PROTECTED; - } - - if ((accessFlags & Constants.ACC_PRIVATE) > 0) - { - return SCOPE_PRIVATE; - } - - return SCOPE_PACKAGE; - } - - /** - * Java class files only ever contain scope specifiers of "public" or - * "package". For top-level classes, this is expected: it is not possible - * to have a top-level protected or private class. - * <p> - * However nested classes <i>can</i> be declared as protected or private. The - * way to tell the real scope of a nested class is to ignore the scope in - * the actual class file itself, and instead look in the "InnerClasses" - * attribute stored on the enclosing class. This is exactly what the java - * compiler does when compiling, and what the jvm does when verifying class - * linkage at runtime. - * <p> - * For a "top-level" class, this method just returns the access scope for - * the class itself. For nested classes, the enclosing class of the - * specified class is retrieved and its InnerClasses attribute checked to - * find the true scope for the specified class. - * <p> - * @throws CheckerException if the specified class is a nested class and - * the enclosing class could not be found, or if the supposedly enclosing - * class has no reference to the nested class. This exception is not - * expected to occur in practice, unless a truly screwed-up jar file is - * passed to clirr for inspection. - */ - public static Scope getClassScope(JavaClass jclass) throws CheckerException - { - int dollarPos = jclass.getClassName().lastIndexOf('$'); - if (dollarPos == -1) - { - // not a nested class - return getScope(jclass.getAccessFlags()); - } - - // ok this is a nested class - String jclassName = jclass.getClassName(); - String enclosingClassName = jclassName.substring(0, dollarPos); - Repository repo = jclass.getRepository(); - JavaClass enclosingClass = repo.findClass(enclosingClassName); - - if (enclosingClass == null) - { - throw new CheckerException( - "Unable to locate enclosing class " + enclosingClassName - + " for nested class " + jclassName); - } - - ConstantPool pool = enclosingClass.getConstantPool(); - Attribute[] attrs = enclosingClass.getAttributes(); - for (int i = 0; i < attrs.length; ++i) - { - if (attrs[i] instanceof InnerClasses) - { - InnerClasses ics = (InnerClasses) attrs[i]; - InnerClass[] icarray = ics.getInnerClasses(); - for (int j = 0; j < icarray.length; ++j) - { - // in the code below, instanceof checks should not be necessary - // before casting Constants because the classfile format ensures - // that instanceof would always be true - InnerClass ic = icarray[j]; - int classIndex = ic.getInnerClassIndex(); - ConstantClass constClass = (ConstantClass) pool.getConstant(classIndex); - int nameIndex = constClass.getNameIndex(); - ConstantUtf8 nameconst = (ConstantUtf8) pool.getConstant(nameIndex); - String classname = nameconst.getBytes().replace('/', '.'); - if (jclassName.equals(classname)) - { - return getScope(ic.getInnerAccessFlags()); - } - } - } - } - - // weird; no nested class info found - throw new CheckerException( - "Unable to find information in class " + enclosingClass.getClassName() - + " referring back to nested class " + jclassName); - - } } |