aboutsummaryrefslogtreecommitdiffstats
path: root/api/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'api/src/main')
-rw-r--r--api/src/main/java/org/osjava/jardiff/AbstractMemberInfo.java25
-rw-r--r--api/src/main/java/org/osjava/jardiff/ClassInfoVisitor.java30
-rw-r--r--api/src/main/java/org/osjava/jardiff/FieldInfo.java7
-rw-r--r--api/src/main/java/org/osjava/jardiff/JarDiff.java90
-rw-r--r--api/src/main/java/org/osjava/jardiff/MethodInfo.java7
-rw-r--r--api/src/main/java/org/osjava/jardiff/PublicDiffCriteria.java15
-rw-r--r--api/src/main/java/org/osjava/jardiff/SimpleDiffCriteria.java15
-rwxr-xr-xapi/src/main/java/org/semver/Dumper.java34
8 files changed, 172 insertions, 51 deletions
diff --git a/api/src/main/java/org/osjava/jardiff/AbstractMemberInfo.java b/api/src/main/java/org/osjava/jardiff/AbstractMemberInfo.java
new file mode 100644
index 0000000..4dc0ae9
--- /dev/null
+++ b/api/src/main/java/org/osjava/jardiff/AbstractMemberInfo.java
@@ -0,0 +1,25 @@
+package org.osjava.jardiff;
+
+public abstract class AbstractMemberInfo extends AbstractInfo {
+
+ /**
+ * The internal name of this member's class
+ */
+ private final String className;
+
+ public AbstractMemberInfo(final String className, final int access, final String name) {
+ super(access, name);
+ this.className = className;
+ }
+
+ /**
+ * Get the internal name of member's class
+ *
+ * @return the name
+ */
+ public final String getClassName() {
+ return className;
+ }
+
+
+}
diff --git a/api/src/main/java/org/osjava/jardiff/ClassInfoVisitor.java b/api/src/main/java/org/osjava/jardiff/ClassInfoVisitor.java
index be7d08b..7e91f58 100644
--- a/api/src/main/java/org/osjava/jardiff/ClassInfoVisitor.java
+++ b/api/src/main/java/org/osjava/jardiff/ClassInfoVisitor.java
@@ -24,7 +24,7 @@ import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
/**
- * A reusable class which uses the ASM to build up ClassInfo about a
+ * A reusable class which uses the ASM to build up ClassInfo about a
* java class file.
*
* @author <a href="mailto:[email protected]">Antony Riley</a>
@@ -51,7 +51,7 @@ public class ClassInfoVisitor extends ClassVisitor
* The signature of the class
*/
private String signature;
-
+
/**
* The internal name of the superclass.
*/
@@ -71,11 +71,11 @@ public class ClassInfoVisitor extends ClassVisitor
* A map of field signature to a FieldInfo describing the field.
*/
private Map<String, FieldInfo> fieldMap;
-
+
public ClassInfoVisitor() {
super(Opcodes.ASM5);
}
-
+
/**
* Reset this ClassInfoVisitor so that it can be used to visit another
* class.
@@ -84,7 +84,7 @@ public class ClassInfoVisitor extends ClassVisitor
methodMap = new HashMap<String, MethodInfo>();
fieldMap = new HashMap<String, FieldInfo>();
}
-
+
/**
* The the classInfo this ClassInfoVisitor has built up about a class
*/
@@ -92,7 +92,7 @@ public class ClassInfoVisitor extends ClassVisitor
return new ClassInfo(version, access, name, signature, supername,
interfaces, methodMap, fieldMap);
}
-
+
/**
* Receive notification of information about a class from ASM.
*
@@ -103,8 +103,8 @@ public class ClassInfoVisitor extends ClassVisitor
* @param supername the internal name of the super class.
* @param interfaces the internal names of interfaces implemented.
*/
- public void visit(int version, int access, String name, String signature,
- String supername, String[] interfaces) {
+ public void visit(final int version, final int access, final String name, final String signature,
+ final String supername, final String[] interfaces) {
this.version = version;
this.access = access;
this.name = name;
@@ -114,18 +114,18 @@ public class ClassInfoVisitor extends ClassVisitor
}
@Override
- public MethodVisitor visitMethod(int access, String name, String desc,
- String signature, String[] exceptions) {
- methodMap.put(name + desc, new MethodInfo(access, name, desc,
+ public MethodVisitor visitMethod(final int access, final String name, final String desc,
+ final String signature, final String[] exceptions) {
+ methodMap.put(name + desc, new MethodInfo(this.name, access, name, desc,
signature, exceptions));
return null;
}
-
+
@Override
- public FieldVisitor visitField(int access, String name, String desc,
- String signature, Object value) {
+ public FieldVisitor visitField(final int access, final String name, final String desc,
+ final String signature, final Object value) {
fieldMap.put(name,
- new FieldInfo(access, name, desc, signature, value));
+ new FieldInfo(this.name, access, name, desc, signature, value));
return null;
}
}
diff --git a/api/src/main/java/org/osjava/jardiff/FieldInfo.java b/api/src/main/java/org/osjava/jardiff/FieldInfo.java
index c159ba9..44bedd2 100644
--- a/api/src/main/java/org/osjava/jardiff/FieldInfo.java
+++ b/api/src/main/java/org/osjava/jardiff/FieldInfo.java
@@ -23,7 +23,7 @@ import java.util.Arrays;
*
* @author <a href="mailto:[email protected]">Antony Riley</a>
*/
-public final class FieldInfo extends AbstractInfo
+public final class FieldInfo extends AbstractMemberInfo
{
/**
* The field descriptor for this field.
@@ -43,15 +43,16 @@ public final class FieldInfo extends AbstractInfo
/**
* Create a new FieldInfo
*
+ * @param className The name of the class this field belongs to
* @param access The access flags.
* @param name The name of the field.
* @param desc The field descriptor.
* @param signature The signature of this field.
* @param value The initial value of the field.
*/
- public FieldInfo(final int access, final String name, final String desc, final String signature,
+ public FieldInfo(final String className, final int access, final String name, final String desc, final String signature,
final Object value) {
- super(access, name);
+ super(className, access, name);
this.desc = desc;
this.signature = signature;
this.value = value;
diff --git a/api/src/main/java/org/osjava/jardiff/JarDiff.java b/api/src/main/java/org/osjava/jardiff/JarDiff.java
index f32982c..1b20cb7 100644
--- a/api/src/main/java/org/osjava/jardiff/JarDiff.java
+++ b/api/src/main/java/org/osjava/jardiff/JarDiff.java
@@ -356,40 +356,81 @@ public class JarDiff
final Map<String, MethodInfo> extNewMethods = new HashMap<String, MethodInfo>(newMethods);
final Map<String, FieldInfo> extNewFields = new HashMap<String, FieldInfo>(newFields);
- String superClass = nci.getSupername();
- while (superClass != null && newClassInfo.containsKey(superClass)) {
- final ClassInfo sci = newClassInfo.get(superClass);
- for (final Map.Entry<String, FieldInfo> entry : sci.getFieldMap().entrySet()) {
- if (!(entry.getValue()).isPrivate()
- && !extNewFields.containsKey(entry.getKey())) {
- extNewFields.put(entry.getKey(), entry.getValue());
+ // For all super classes
+ // - Moving methods upward is OK!
+ // - static final fields are resolved at compile time!
+ {
+ String superClass = nci.getSupername();
+ ClassInfo sci;
+ while ( superClass != null && null != ( sci = newClassInfo.get(superClass) ) ) {
+ for (final Map.Entry<String, FieldInfo> entry : sci.getFieldMap().entrySet()) {
+ if ( !entry.getValue().isPrivate() &&
+ !extNewFields.containsKey(entry.getKey()) ) {
+ extNewFields.put(entry.getKey(), entry.getValue());
+ }
}
+ for (final Map.Entry<String, MethodInfo> entry : sci.getMethodMap().entrySet()) {
+ if ( !entry.getValue().isPrivate() &&
+ !extNewMethods.containsKey(entry.getKey()) ) {
+ extNewMethods.put(entry.getKey(), entry.getValue());
+ }
+ }
+ superClass = sci.getSupername();
}
- for (final Map.Entry<String, MethodInfo> entry : sci.getMethodMap().entrySet()) {
- if (!(entry.getValue()).isPrivate()
- && !extNewMethods.containsKey(entry.getKey())) {
- extNewMethods.put(entry.getKey(), entry.getValue());
+ }
+ // For all super interfaces
+ // - Moving methods upward is OK!
+ // - static final fields are resolved at compile time!
+ {
+ final ArrayList<String> superInterfaces = new ArrayList<String>(Arrays.asList(nci.getInterfaces()));
+ final Set<String> done = new HashSet<String>();
+ for(int i=0; i<superInterfaces.size(); i++) {
+ final String superFace = superInterfaces.get(i);
+ if( null != superFace && !done.contains(superFace) ) {
+ done.add(superFace);
+ final ClassInfo sii;
+ if( null != ( sii = newClassInfo.get(superFace) ) ) {
+ for (final Map.Entry<String, FieldInfo> entry : sii.getFieldMap().entrySet()) {
+ if ( !entry.getValue().isPrivate() &&
+ !extNewFields.containsKey(entry.getKey()) ) {
+ extNewFields.put(entry.getKey(), entry.getValue());
+ }
+ }
+ for (final Map.Entry<String, MethodInfo> entry : sii.getMethodMap().entrySet()) {
+ if ( !entry.getValue().isPrivate() &&
+ !extNewMethods.containsKey(entry.getKey()) ) {
+ extNewMethods.put(entry.getKey(), entry.getValue());
+ }
+ }
+ // Append this ssi's super interfaces in a unique manner
+ final List<String> ssi = new ArrayList<String>(Arrays.asList(sii.getInterfaces()));
+ ssi.removeAll(superInterfaces);
+ superInterfaces.addAll(ssi);
+ }
}
}
- superClass = sci.getSupername();
}
for (final Map.Entry<String, MethodInfo> entry : oldMethods.entrySet()) {
- if (criteria.validMethod(entry.getValue()))
+ if (criteria.validMethod(entry.getValue())) {
removedMethods.add(entry.getKey());
+ }
}
for (final Map.Entry<String, FieldInfo> entry : oldFields.entrySet()) {
- if (criteria.validField(entry.getValue()))
+ if (criteria.validField(entry.getValue())) {
removedFields.add(entry.getKey());
+ }
}
for (final Map.Entry<String, MethodInfo> entry : newMethods.entrySet()) {
- if (criteria.validMethod(entry.getValue()))
+ if (criteria.validMethod(entry.getValue())) {
addedMethods.add(entry.getKey());
+ }
}
for (final Map.Entry<String, FieldInfo> entry : newFields.entrySet()) {
- if (criteria.validField(entry.getValue()))
+ if (criteria.validField(entry.getValue())) {
addedFields.add(entry.getKey());
+ }
}
// We add all the old methods that match the criteria
@@ -397,12 +438,13 @@ public class JarDiff
// We keep the intersection of these with all the new methods
// to detect as changed a method that no longer match the
// criteria (i.e. a method that was public and is now private)
- changedMethods.retainAll(newMethods.keySet());
+ changedMethods.retainAll(extNewMethods.keySet());
removedMethods.removeAll(changedMethods);
removedMethods.removeAll(extNewMethods.keySet());
addedMethods.removeAll(changedMethods);
+
changedFields.addAll(removedFields);
- changedFields.retainAll(newFields.keySet());
+ changedFields.retainAll(extNewFields.keySet());
removedFields.removeAll(changedFields);
removedFields.removeAll(extNewFields.keySet());
addedFields.removeAll(changedFields);
@@ -411,7 +453,7 @@ public class JarDiff
while (j.hasNext()) {
final String desc = j.next();
final MethodInfo oldInfo = oldMethods.get(desc);
- final MethodInfo newInfo = newMethods.get(desc);
+ final MethodInfo newInfo = extNewMethods.get(desc);
if (!criteria.differs(oldInfo, newInfo)) {
j.remove();
}
@@ -420,7 +462,7 @@ public class JarDiff
while (j.hasNext()) {
final String desc = j.next();
final FieldInfo oldInfo = oldFields.get(desc);
- final FieldInfo newInfo = newFields.get(desc);
+ final FieldInfo newInfo = extNewFields.get(desc);
if (!criteria.differs(oldInfo, newInfo)) {
j.remove();
}
@@ -464,7 +506,7 @@ public class JarDiff
for (final String field : changedFields) {
final FieldInfo oldFieldInfo = oldFields.get(field);
- final FieldInfo newFieldInfo = newFields.get(field);
+ final FieldInfo newFieldInfo = extNewFields.get(field);
// Was only deprecated?
if (wasDeprecated(oldFieldInfo, newFieldInfo)
&& !criteria.differs(cloneDeprecated(oldFieldInfo), newFieldInfo)) {
@@ -477,7 +519,7 @@ public class JarDiff
}
for (final String method : changedMethods) {
final MethodInfo oldMethodInfo = oldMethods.get(method);
- final MethodInfo newMethodInfo = newMethods.get(method);
+ final MethodInfo newMethodInfo = extNewMethods.get(method);
// Was only deprecated?
if (wasDeprecated(oldMethodInfo, newMethodInfo)
&& !criteria.differs(cloneDeprecated(oldMethodInfo), newMethodInfo)) {
@@ -537,7 +579,7 @@ public class JarDiff
* @return the cloned and deprecated method info.
*/
private static MethodInfo cloneDeprecated(final MethodInfo methodInfo) {
- return new MethodInfo(methodInfo.getAccess() | Opcodes.ACC_DEPRECATED,
+ return new MethodInfo(methodInfo.getClassName(), methodInfo.getAccess() | Opcodes.ACC_DEPRECATED,
methodInfo.getName(), methodInfo.getDesc(),
methodInfo.getSignature(), methodInfo.getExceptions());
}
@@ -550,7 +592,7 @@ public class JarDiff
* @return the cloned and deprecated field info.
*/
private static FieldInfo cloneDeprecated(final FieldInfo fieldInfo) {
- return new FieldInfo(fieldInfo.getAccess() | Opcodes.ACC_DEPRECATED,
+ return new FieldInfo(fieldInfo.getClassName(), fieldInfo.getAccess() | Opcodes.ACC_DEPRECATED,
fieldInfo.getName(), fieldInfo.getDesc(),
fieldInfo.getSignature(), fieldInfo.getValue());
}
diff --git a/api/src/main/java/org/osjava/jardiff/MethodInfo.java b/api/src/main/java/org/osjava/jardiff/MethodInfo.java
index 797faa4..32f7b06 100644
--- a/api/src/main/java/org/osjava/jardiff/MethodInfo.java
+++ b/api/src/main/java/org/osjava/jardiff/MethodInfo.java
@@ -23,7 +23,7 @@ import java.util.Arrays;
*
* @author <a href="mailto:[email protected]">Antony Riley</a>
*/
-public final class MethodInfo extends AbstractInfo
+public final class MethodInfo extends AbstractMemberInfo
{
/**
* The method descriptor.
@@ -43,14 +43,15 @@ public final class MethodInfo extends AbstractInfo
/**
* Create a new MethodInfo with the specified parameters.
*
+ * @param className The name of the class this method belongs to
* @param access The access flags for the method.
* @param name The name of the method.
* @param signature The signature of the method.
* @param exceptions The exceptions thrown by the method.
*/
- public MethodInfo(final int access, final String name, final String desc, final String signature,
+ public MethodInfo(final String className, final int access, final String name, final String desc, final String signature,
final String[] exceptions) {
- super(access, name);
+ super(className, access, name);
this.desc = desc;
this.signature = signature;
this.exceptions = exceptions;
diff --git a/api/src/main/java/org/osjava/jardiff/PublicDiffCriteria.java b/api/src/main/java/org/osjava/jardiff/PublicDiffCriteria.java
index c5e2f02..54a33cc 100644
--- a/api/src/main/java/org/osjava/jardiff/PublicDiffCriteria.java
+++ b/api/src/main/java/org/osjava/jardiff/PublicDiffCriteria.java
@@ -28,6 +28,15 @@ import java.util.Set;
*/
public class PublicDiffCriteria implements DiffCriteria
{
+ final boolean ignoreClassName;
+
+ public PublicDiffCriteria() {
+ this.ignoreClassName = false;
+ }
+ public PublicDiffCriteria(final boolean ignoreClassName) {
+ this.ignoreClassName = ignoreClassName;
+ }
+
@Override
public boolean equals(final Object arg) {
if (arg == this) {
@@ -104,7 +113,8 @@ public class PublicDiffCriteria implements DiffCriteria
@Override
public boolean differs(final MethodInfo oldInfo, final MethodInfo newInfo) {
- return // Tools.isDescChange(oldInfo.getDesc(), newInfo.getDesc()) ||
+ return !ignoreClassName && !oldInfo.getClassName().equals(newInfo.getClassName()) ||
+ // Tools.isDescChange(oldInfo.getDesc(), newInfo.getDesc()) ||
Tools.isMethodAccessChange(oldInfo.getAccess(), newInfo.getAccess()) ||
Tools.isThrowsClauseChange(oldInfo.getExceptions(), newInfo.getExceptions());
}
@@ -116,7 +126,8 @@ public class PublicDiffCriteria implements DiffCriteria
@Override
public boolean differs(final FieldInfo oldInfo, final FieldInfo newInfo) {
- return Tools.isFieldTypeChange(oldInfo.getValue(), newInfo.getValue()) ||
+ return !ignoreClassName && !oldInfo.getClassName().equals(newInfo.getClassName()) ||
+ Tools.isFieldTypeChange(oldInfo.getValue(), newInfo.getValue()) ||
Tools.isFieldAccessChange(oldInfo.getAccess(), newInfo.getAccess()) ||
Tools.isFieldValueChange(oldInfo.getValue(), newInfo.getValue());
}
diff --git a/api/src/main/java/org/osjava/jardiff/SimpleDiffCriteria.java b/api/src/main/java/org/osjava/jardiff/SimpleDiffCriteria.java
index 09d1108..d9d47d0 100644
--- a/api/src/main/java/org/osjava/jardiff/SimpleDiffCriteria.java
+++ b/api/src/main/java/org/osjava/jardiff/SimpleDiffCriteria.java
@@ -28,6 +28,15 @@ import java.util.Set;
*/
public class SimpleDiffCriteria implements DiffCriteria
{
+ final boolean ignoreClassName;
+
+ public SimpleDiffCriteria() {
+ this.ignoreClassName = false;
+ }
+ public SimpleDiffCriteria(final boolean ignoreClassName) {
+ this.ignoreClassName = ignoreClassName;
+ }
+
@Override
public boolean equals(final Object arg) {
if (arg == this) {
@@ -104,7 +113,8 @@ public class SimpleDiffCriteria implements DiffCriteria
@Override
public boolean differs(final MethodInfo oldInfo, final MethodInfo newInfo) {
- return // Tools.isDescChange(oldInfo.getDesc(), newInfo.getDesc()) ||
+ return !ignoreClassName && !oldInfo.getClassName().equals(newInfo.getClassName()) ||
+ // Tools.isDescChange(oldInfo.getDesc(), newInfo.getDesc()) ||
Tools.isMethodAccessChange(oldInfo.getAccess(), newInfo.getAccess()) ||
Tools.isThrowsClauseChange(oldInfo.getExceptions(), newInfo.getExceptions());
}
@@ -116,7 +126,8 @@ public class SimpleDiffCriteria implements DiffCriteria
@Override
public boolean differs(final FieldInfo oldInfo, final FieldInfo newInfo) {
- return Tools.isFieldTypeChange(oldInfo.getValue(), newInfo.getValue()) ||
+ return !ignoreClassName && !oldInfo.getClassName().equals(newInfo.getClassName()) ||
+ Tools.isFieldTypeChange(oldInfo.getValue(), newInfo.getValue()) ||
Tools.isFieldAccessChange(oldInfo.getAccess(), newInfo.getAccess()) ||
Tools.isFieldValueChange(oldInfo.getValue(), newInfo.getValue());
}
diff --git a/api/src/main/java/org/semver/Dumper.java b/api/src/main/java/org/semver/Dumper.java
index 30824f5..0e628e0 100755
--- a/api/src/main/java/org/semver/Dumper.java
+++ b/api/src/main/java/org/semver/Dumper.java
@@ -29,6 +29,7 @@ import java.util.Map;
import java.util.Set;
import org.osjava.jardiff.AbstractInfo;
+import org.osjava.jardiff.AbstractMemberInfo;
import org.osjava.jardiff.ClassInfo;
import org.osjava.jardiff.FieldInfo;
import org.osjava.jardiff.MethodInfo;
@@ -76,10 +77,39 @@ public class Dumper {
return builder.toString();
}
+ private static int findCommonPrefix(final String strA, final String strB, final char c) {
+ int i = 0;
+ int lastC = -1;
+ final int end = Math.min(strA.length(), strB.length());
+ for (; i < end; i++) {
+ final char strAc = strA.charAt(i);
+ if (strAc != strB.charAt(i)) {
+ break;
+ } else if( 0 < c && strAc == c ) {
+ lastC = i;
+ }
+ }
+ return lastC >= 0 ? lastC+1 : i;
+ }
+
+ protected static StringBuilder appendNameChangeDetails(final StringBuilder builder, final AbstractInfo previousInfo, final AbstractInfo currentInfo) {
+ if( previousInfo instanceof AbstractMemberInfo && currentInfo instanceof AbstractMemberInfo ) {
+ final String preClz = ((AbstractMemberInfo)previousInfo).getClassName().replace('/', '.');
+ final String curClz = ((AbstractMemberInfo)currentInfo).getClassName().replace('/', '.');
+ final int prefixIdx = findCommonPrefix(preClz, curClz, '.');
+ final String common = preClz.substring(0, prefixIdx);
+ if( !preClz.equals(curClz) ) {
+ builder.append(common+"["+preClz.substring(prefixIdx, preClz.length())+" -> "+curClz.substring(prefixIdx, curClz.length())+"].");
+ }
+ }
+ builder.append(previousInfo.getName());
+ return builder;
+ }
+
protected static String extractChangeDetails(final AbstractInfo previousInfo, final AbstractInfo currentInfo) {
final StringBuilder builder = new StringBuilder();
if (!(previousInfo instanceof ClassInfo)) {
- builder.append(previousInfo.getName());
+ appendNameChangeDetails(builder, previousInfo, currentInfo);
final String pSig = previousInfo.getSignature();
final String pDesc = previousInfo.getDesc();
final String cSig = currentInfo.getSignature();
@@ -112,7 +142,7 @@ public class Dumper {
protected static String extractCompatChangeDetails(final AbstractInfo previousInfo, final AbstractInfo currentInfo) {
final StringBuilder builder = new StringBuilder();
if (!(previousInfo instanceof ClassInfo)) {
- builder.append(previousInfo.getName());
+ appendNameChangeDetails(builder, previousInfo, currentInfo);
}
if( previousInfo instanceof MethodInfo ) {
final MethodInfo mPreInfo = (MethodInfo)previousInfo;