mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-12 07:56:16 +00:00
updates
This commit is contained in:
parent
10d27316a6
commit
0b7e8dd8ca
@ -4,20 +4,40 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.apiupdate;
|
package org.sleuthkit.autopsy.apiupdate;
|
||||||
|
|
||||||
|
import com.google.common.collect.Comparators;
|
||||||
import japicmp.cmp.JApiCmpArchive;
|
import japicmp.cmp.JApiCmpArchive;
|
||||||
import japicmp.cmp.JarArchiveComparator;
|
import japicmp.cmp.JarArchiveComparator;
|
||||||
import japicmp.cmp.JarArchiveComparatorOptions;
|
import japicmp.cmp.JarArchiveComparatorOptions;
|
||||||
import japicmp.config.Options;
|
import japicmp.config.Options;
|
||||||
|
import japicmp.filter.BehaviorFilter;
|
||||||
|
import japicmp.filter.ClassFilter;
|
||||||
|
import japicmp.filter.FieldFilter;
|
||||||
|
import japicmp.model.JApiAnnotation;
|
||||||
import japicmp.model.JApiClass;
|
import japicmp.model.JApiClass;
|
||||||
|
import japicmp.model.JApiConstructor;
|
||||||
|
import japicmp.model.JApiField;
|
||||||
|
import japicmp.model.JApiHasChangeStatus;
|
||||||
|
import japicmp.model.JApiImplementedInterface;
|
||||||
|
import japicmp.model.JApiMethod;
|
||||||
|
import japicmp.model.JApiSuperclass;
|
||||||
|
import japicmp.output.Filter;
|
||||||
|
import japicmp.output.stdout.StdoutOutputGenerator;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileFilter;
|
import java.io.FileFilter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
import javassist.CtBehavior;
|
||||||
|
import javassist.CtClass;
|
||||||
|
import javassist.CtField;
|
||||||
|
import javassist.CtMember;
|
||||||
|
import javassist.Modifier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -57,107 +77,186 @@ public class APIDiff {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void getComparison(String prevVersion, String curVersion, File prevJar, File curJar) throws IOException {
|
// only fields, methods that are public or protected
|
||||||
|
static boolean excludeMember(CtMember member) {
|
||||||
|
return !Modifier.isPublic(member.getModifiers()) && !Modifier.isProtected(member.getModifiers());
|
||||||
|
}
|
||||||
|
|
||||||
|
static ComparisonRecord getComparison(String prevVersion, String curVersion, File prevJar, File curJar) throws IOException {
|
||||||
|
// scope only to previous or current public packages
|
||||||
|
Set<String> prevPublicApiPackages = getPublicPackages(prevJar);
|
||||||
|
Set<String> curPublicApiPackages = getPublicPackages(curJar);
|
||||||
|
|
||||||
|
Set<String> allPublicApiPackages = new HashSet<>();
|
||||||
|
allPublicApiPackages.addAll(prevPublicApiPackages);
|
||||||
|
allPublicApiPackages.addAll(curPublicApiPackages);
|
||||||
|
|
||||||
|
Set<String> onlyPrevApiPackages = new HashSet<>();
|
||||||
|
Set<String> onlyCurApiPackages = new HashSet<>();
|
||||||
|
Set<String> commonApiPackages = new HashSet<>();
|
||||||
|
for (String apiPackage : allPublicApiPackages) {
|
||||||
|
boolean inPrev = prevPublicApiPackages.contains(apiPackage);
|
||||||
|
boolean inCur = curPublicApiPackages.contains(apiPackage);
|
||||||
|
if (inPrev && !inCur) {
|
||||||
|
onlyPrevApiPackages.add(apiPackage);
|
||||||
|
} else if (!inPrev && inCur) {
|
||||||
|
onlyCurApiPackages.add(apiPackage);
|
||||||
|
} else {
|
||||||
|
commonApiPackages.add(apiPackage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JarArchiveComparatorOptions comparatorOptions = new JarArchiveComparatorOptions();
|
JarArchiveComparatorOptions comparatorOptions = new JarArchiveComparatorOptions();
|
||||||
//comparatorOptions.setAccessModifier(AccessModifier.);
|
// only classes in prev or current public api
|
||||||
|
comparatorOptions.getFilters().getExcludes().add((ClassFilter) (CtClass ctClass) -> !allPublicApiPackages.contains(ctClass.getPackageName()));
|
||||||
|
// only public classes
|
||||||
|
comparatorOptions.getFilters().getExcludes().add((ClassFilter) (CtClass ctClass) -> !Modifier.isPublic(ctClass.getModifiers()));
|
||||||
|
// only fields, methods that are public or protected and class is not final
|
||||||
|
comparatorOptions.getFilters().getExcludes().add((FieldFilter) (CtField ctField) -> excludeMember(ctField));
|
||||||
|
comparatorOptions.getFilters().getExcludes().add((BehaviorFilter) (CtBehavior ctBehavior) -> excludeMember(ctBehavior));
|
||||||
|
|
||||||
comparatorOptions.getIgnoreMissingClasses().setIgnoreAllMissingClasses(true);
|
comparatorOptions.getIgnoreMissingClasses().setIgnoreAllMissingClasses(true);
|
||||||
|
|
||||||
JarArchiveComparator jarArchiveComparator = new JarArchiveComparator(comparatorOptions);
|
JarArchiveComparator jarArchiveComparator = new JarArchiveComparator(comparatorOptions);
|
||||||
List<JApiClass> jApiClasses = jarArchiveComparator.compare(
|
List<JApiClass> jApiClasses = jarArchiveComparator.compare(
|
||||||
new JApiCmpArchive(prevJar, prevVersion),
|
new JApiCmpArchive(prevJar, prevVersion),
|
||||||
new JApiCmpArchive(curJar, curVersion)
|
new JApiCmpArchive(curJar, curVersion)
|
||||||
);
|
);
|
||||||
|
|
||||||
Set<String> prevPublicApiPackages = getPublicPackages(prevJar);
|
PublicApiChangeType changeType = getChangeType(jApiClasses);
|
||||||
Set<String> curPublicApiPackages = getPublicPackages(curJar);
|
|
||||||
|
|
||||||
// TODO handle diff in this list
|
|
||||||
Set<String> allPublicApiPackages = new HashSet<>();
|
|
||||||
allPublicApiPackages.addAll(prevPublicApiPackages);
|
|
||||||
allPublicApiPackages.addAll(curPublicApiPackages);
|
|
||||||
jApiClasses = jApiClasses.stream()
|
|
||||||
.filter(cls -> allPublicApiPackages.contains(cls.getNewClass().or(cls.getOldClass()).get().getPackageName()))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
Options options = Options.newDefault();
|
Options options = Options.newDefault();
|
||||||
options.setOutputOnlyModifications(true);
|
options.setOutputOnlyModifications(true);
|
||||||
|
|
||||||
System.out.println("Comparing " + prevJar.getName());
|
StdoutOutputGenerator stdoutOutputGenerator = new StdoutOutputGenerator(options, jApiClasses);
|
||||||
ChangeOutputGenerator stdoutOutputGenerator = new ChangeOutputGenerator(options, jApiClasses);
|
String humanReadableApiChange = stdoutOutputGenerator.generate();
|
||||||
String output = stdoutOutputGenerator.generate();
|
return new ComparisonRecord(prevVersion, curVersion, prevJar, curJar, humanReadableApiChange, changeType, onlyPrevApiPackages, onlyCurApiPackages, commonApiPackages);
|
||||||
System.out.println(output);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void generateOutput(Options options, List<JApiClass> jApiClasses, JarArchiveComparator jarArchiveComparator) {
|
private static void updateToMax(AtomicReference<PublicApiChangeType> apiChangeRef, JApiHasChangeStatus tp) {
|
||||||
// for (JApiClass cls: jApiClasses) {
|
PublicApiChangeType apiChangeType;
|
||||||
// cls.is
|
switch (tp.getChangeStatus()) {
|
||||||
// }
|
case UNCHANGED:
|
||||||
//
|
apiChangeType = PublicApiChangeType.NONE;
|
||||||
|
break;
|
||||||
|
case NEW:
|
||||||
|
apiChangeType = PublicApiChangeType.COMPATIBLE_CHANGE;
|
||||||
|
break;
|
||||||
|
case MODIFIED:
|
||||||
|
case REMOVED:
|
||||||
|
default:
|
||||||
|
apiChangeType = PublicApiChangeType.INCOMPATIBLE_CHANGE;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
final PublicApiChangeType finalApiChangeType = apiChangeType;
|
||||||
|
apiChangeRef.updateAndGet((refType) -> Comparators.max(refType, finalApiChangeType));
|
||||||
|
}
|
||||||
|
|
||||||
|
static PublicApiChangeType getChangeType(List<JApiClass> jApiClasses) {
|
||||||
|
AtomicReference<PublicApiChangeType> apiChange = new AtomicReference<PublicApiChangeType>(PublicApiChangeType.NONE);
|
||||||
|
|
||||||
|
Filter.filter(jApiClasses, new Filter.FilterVisitor() {
|
||||||
|
@Override
|
||||||
|
public void visit(Iterator<JApiClass> itrtr, JApiClass jac) {
|
||||||
|
updateToMax(apiChange, jac);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Iterator<JApiMethod> itrtr, JApiMethod jam) {
|
||||||
|
updateToMax(apiChange, jam);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Iterator<JApiConstructor> itrtr, JApiConstructor jac) {
|
||||||
|
updateToMax(apiChange, jac);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Iterator<JApiImplementedInterface> itrtr, JApiImplementedInterface jaii) {
|
||||||
|
updateToMax(apiChange, jaii);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Iterator<JApiField> itrtr, JApiField jaf) {
|
||||||
|
updateToMax(apiChange, jaf);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Iterator<JApiAnnotation> itrtr, JApiAnnotation jaa) {
|
||||||
|
updateToMax(apiChange, jaa);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(JApiSuperclass jas) {
|
||||||
|
updateToMax(apiChange, jas);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return apiChange.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ComparisonRecord {
|
||||||
|
|
||||||
|
private final String prevVersion;
|
||||||
|
private final String curVersion;
|
||||||
|
private final File prevJar;
|
||||||
|
private final File curJar;
|
||||||
|
private final String humanReadableApiChange;
|
||||||
|
private final PublicApiChangeType changeType;
|
||||||
|
private final Set<String> onlyPrevApiPackages;
|
||||||
|
private final Set<String> onlyCurrApiPackages;
|
||||||
|
private final Set<String> commonApiPackages;
|
||||||
|
|
||||||
|
public ComparisonRecord(String prevVersion, String curVersion, File prevJar, File curJar, String humanReadableApiChange, PublicApiChangeType changeType, Set<String> onlyPrevApiPackages, Set<String> onlyCurrApiPackages, Set<String> commonApiPackages) {
|
||||||
|
this.prevVersion = prevVersion;
|
||||||
|
this.curVersion = curVersion;
|
||||||
|
this.prevJar = prevJar;
|
||||||
|
this.curJar = curJar;
|
||||||
|
this.humanReadableApiChange = humanReadableApiChange;
|
||||||
|
this.changeType = changeType;
|
||||||
|
this.onlyPrevApiPackages = onlyPrevApiPackages;
|
||||||
|
this.onlyCurrApiPackages = onlyCurrApiPackages;
|
||||||
|
this.commonApiPackages = commonApiPackages;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrevVersion() {
|
||||||
|
return prevVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCurVersion() {
|
||||||
|
return curVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getPrevJar() {
|
||||||
|
return prevJar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getCurJar() {
|
||||||
|
return curJar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHumanReadableApiChange() {
|
||||||
|
return humanReadableApiChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PublicApiChangeType getChangeType() {
|
||||||
|
return changeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getOnlyPrevApiPackages() {
|
||||||
|
return onlyPrevApiPackages;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getOnlyCurrApiPackages() {
|
||||||
|
return onlyCurrApiPackages;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getCommonApiPackages() {
|
||||||
|
return commonApiPackages;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// if (options.isSemanticVersioning()) {
|
|
||||||
// SemverOut semverOut = new SemverOut(options, jApiClasses);
|
|
||||||
// String output = semverOut.generate();
|
|
||||||
// System.out.println(output);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// if (options.getXmlOutputFile().isPresent() || options.getHtmlOutputFile().isPresent()) {
|
|
||||||
// SemverOut semverOut = new SemverOut(options, jApiClasses);
|
|
||||||
// XmlOutputGeneratorOptions xmlOutputGeneratorOptions = new XmlOutputGeneratorOptions();
|
|
||||||
// xmlOutputGeneratorOptions.setCreateSchemaFile(true);
|
|
||||||
// xmlOutputGeneratorOptions.setSemanticVersioningInformation(semverOut.generate());
|
|
||||||
// XmlOutputGenerator xmlGenerator = new XmlOutputGenerator(jApiClasses, options, xmlOutputGeneratorOptions);
|
|
||||||
// try (XmlOutput xmlOutput = xmlGenerator.generate()) {
|
|
||||||
// XmlOutputGenerator.writeToFiles(options, xmlOutput);
|
|
||||||
// } catch (Exception e) {
|
|
||||||
// throw new JApiCmpException(JApiCmpException.Reason.IoException, "Could not close output streams: " + e.getMessage(), e);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// StdoutOutputGenerator stdoutOutputGenerator = new StdoutOutputGenerator(options, jApiClasses);
|
|
||||||
// String output = stdoutOutputGenerator.generate();
|
|
||||||
// System.out.println(output);
|
|
||||||
|
|
||||||
// if (options.isErrorOnBinaryIncompatibility()
|
|
||||||
// || options.isErrorOnSourceIncompatibility()
|
|
||||||
// || options.isErrorOnExclusionIncompatibility()
|
|
||||||
// || options.isErrorOnModifications()
|
|
||||||
// || options.isErrorOnSemanticIncompatibility()) {
|
|
||||||
// IncompatibleErrorOutput errorOutput = new IncompatibleErrorOutput(options, jApiClasses, jarArchiveComparator);
|
|
||||||
// errorOutput.generate();
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// enum ChangeType { CHANGE, ADD, REMOVE }
|
|
||||||
//
|
|
||||||
// public class ClassChangeDTO {
|
|
||||||
// private final String packageStr;
|
|
||||||
// private final String fullyQualifiedClassName;
|
|
||||||
// private final ChangeType changeType;
|
|
||||||
//
|
|
||||||
// private final ClassDataDTO prevClassRecord;
|
|
||||||
// private final ClassDataDTO currClassRecord;
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public class ClassDataDTO {
|
|
||||||
// private final String packageStr;
|
|
||||||
// private final String fullyQualifiedClassName;
|
|
||||||
// private final AccessModifier accessModifier;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,153 +0,0 @@
|
|||||||
/*
|
|
||||||
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
|
|
||||||
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
|
|
||||||
*/
|
|
||||||
package org.sleuthkit.autopsy.apiupdate;
|
|
||||||
|
|
||||||
import japicmp.model.JApiChangeStatus;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author gregd
|
|
||||||
*/
|
|
||||||
public class ApiChangeDTO {
|
|
||||||
//NEW, REMOVED, UNCHANGED, MODIFIED
|
|
||||||
|
|
||||||
public interface PublicApiChangeable {
|
|
||||||
|
|
||||||
PublicApiChangeType getChangeType();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ClassChangeDTO {
|
|
||||||
|
|
||||||
private final JApiChangeStatus changeStatus;
|
|
||||||
private final Optional<String> oldDeclaration;
|
|
||||||
private final Optional<Long> oldSerialId;
|
|
||||||
|
|
||||||
private final Optional<String> newDeclaration;
|
|
||||||
private final Optional<Long> newSerialId;
|
|
||||||
|
|
||||||
public ClassChangeDTO(JApiChangeStatus changeStatus, Optional<String> oldDeclaration, Optional<Long> oldSerialId, Optional<String> newDeclaration, Optional<Long> newSerialId) {
|
|
||||||
this.changeStatus = changeStatus;
|
|
||||||
this.oldDeclaration = oldDeclaration;
|
|
||||||
this.oldSerialId = oldSerialId;
|
|
||||||
this.newDeclaration = newDeclaration;
|
|
||||||
this.newSerialId = newSerialId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JApiChangeStatus getChangeStatus() {
|
|
||||||
return changeStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<String> getOldDeclaration() {
|
|
||||||
return oldDeclaration;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<Long> getOldSerialId() {
|
|
||||||
return oldSerialId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<String> getNewDeclaration() {
|
|
||||||
return newDeclaration;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<Long> getNewSerialId() {
|
|
||||||
return newSerialId;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// public static class SuperclassChangeDTO {
|
|
||||||
//
|
|
||||||
// private final Optional<String> oldFullyQualifiedClassName;
|
|
||||||
// private final Optional<String> newFullyQualifiedClassName;
|
|
||||||
//
|
|
||||||
// public SuperclassChangeDTO(Optional<String> oldFullyQualifiedClassName, Optional<String> newFullyQualifiedClassName) {
|
|
||||||
// this.oldFullyQualifiedClassName = oldFullyQualifiedClassName;
|
|
||||||
// this.newFullyQualifiedClassName = newFullyQualifiedClassName;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public Optional<String> getOldFullyQualifiedClassName() {
|
|
||||||
// return oldFullyQualifiedClassName;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public Optional<String> getNewFullyQualifiedClassName() {
|
|
||||||
// return newFullyQualifiedClassName;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public static class InterfaceChangeDTO {
|
|
||||||
//
|
|
||||||
// private final JApiChangeStatus changeStatus;
|
|
||||||
// private final String fullyQualifiedName;
|
|
||||||
//
|
|
||||||
// public InterfaceChangeDTO(JApiChangeStatus changeStatus, String fullyQualifiedName) {
|
|
||||||
// this.changeStatus = changeStatus;
|
|
||||||
// this.fullyQualifiedName = fullyQualifiedName;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public JApiChangeStatus getChangeStatus() {
|
|
||||||
// return changeStatus;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public String getFullyQualifiedName() {
|
|
||||||
// return fullyQualifiedName;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
public static class MethodChangeDTO {
|
|
||||||
|
|
||||||
private final JApiChangeStatus changeStatus;
|
|
||||||
private final Optional<String> oldMethodDeclaration;
|
|
||||||
private final Optional<String> newMethodDeclaration;
|
|
||||||
|
|
||||||
public MethodChangeDTO(JApiChangeStatus changeStatus, Optional<String> oldMethodDeclaration, Optional<String> newMethodDeclaration) {
|
|
||||||
this.changeStatus = changeStatus;
|
|
||||||
this.oldMethodDeclaration = oldMethodDeclaration;
|
|
||||||
this.newMethodDeclaration = newMethodDeclaration;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JApiChangeStatus getChangeStatus() {
|
|
||||||
return changeStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<String> getOldMethodDeclaration() {
|
|
||||||
return oldMethodDeclaration;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<String> getNewMethodDeclaration() {
|
|
||||||
return newMethodDeclaration;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class FieldChangeDTO {
|
|
||||||
|
|
||||||
private final JApiChangeStatus changeStatus;
|
|
||||||
private final Optional<String> oldFieldDeclaration;
|
|
||||||
private final Optional<String> newFieldDeclaration;
|
|
||||||
|
|
||||||
public FieldChangeDTO(JApiChangeStatus changeStatus, Optional<String> oldFieldDeclaration, Optional<String> newFieldDeclaration) {
|
|
||||||
this.changeStatus = changeStatus;
|
|
||||||
this.oldFieldDeclaration = oldFieldDeclaration;
|
|
||||||
this.newFieldDeclaration = newFieldDeclaration;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JApiChangeStatus getChangeStatus() {
|
|
||||||
return changeStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<String> getOldFieldDeclaration() {
|
|
||||||
return oldFieldDeclaration;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<String> getNewFieldDeclaration() {
|
|
||||||
return newFieldDeclaration;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -5,6 +5,7 @@
|
|||||||
package org.sleuthkit.autopsy.apiupdate;
|
package org.sleuthkit.autopsy.apiupdate;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.nio.file.Paths;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -37,7 +38,7 @@ public class CLIProcessor {
|
|||||||
.hasArg(true)
|
.hasArg(true)
|
||||||
.longOpt("curr-path")
|
.longOpt("curr-path")
|
||||||
.option("c")
|
.option("c")
|
||||||
.required(true)
|
.required(false)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
static Option PREV_VERS_OPT = Option.builder()
|
static Option PREV_VERS_OPT = Option.builder()
|
||||||
@ -46,7 +47,7 @@ public class CLIProcessor {
|
|||||||
.hasArg(true)
|
.hasArg(true)
|
||||||
.longOpt("prev-version")
|
.longOpt("prev-version")
|
||||||
.option("pv")
|
.option("pv")
|
||||||
.required(true)
|
.required(false)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
static Option CUR_VERS_OPT = Option.builder()
|
static Option CUR_VERS_OPT = Option.builder()
|
||||||
@ -55,7 +56,7 @@ public class CLIProcessor {
|
|||||||
.hasArg(true)
|
.hasArg(true)
|
||||||
.longOpt("curr-version")
|
.longOpt("curr-version")
|
||||||
.option("cv")
|
.option("cv")
|
||||||
.required(true)
|
.required(false)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
static Option SRC_LOC_OPT = Option.builder()
|
static Option SRC_LOC_OPT = Option.builder()
|
||||||
@ -67,15 +68,27 @@ public class CLIProcessor {
|
|||||||
.required(true)
|
.required(true)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
static Option UPDATE_OPT = Option.builder()
|
||||||
|
.desc("Update source code versions")
|
||||||
|
.hasArg(false)
|
||||||
|
.longOpt("update")
|
||||||
|
.option("u")
|
||||||
|
.required(false)
|
||||||
|
.build();
|
||||||
|
|
||||||
static List<Option> ALL_OPTIONS = Arrays.asList(
|
static List<Option> ALL_OPTIONS = Arrays.asList(
|
||||||
PREV_VERS_PATH_OPT,
|
PREV_VERS_PATH_OPT,
|
||||||
CUR_VERS_PATH_OPT,
|
CUR_VERS_PATH_OPT,
|
||||||
PREV_VERS_OPT,
|
PREV_VERS_OPT,
|
||||||
CUR_VERS_OPT,
|
CUR_VERS_OPT,
|
||||||
SRC_LOC_OPT
|
SRC_LOC_OPT,
|
||||||
|
UPDATE_OPT
|
||||||
);
|
);
|
||||||
|
|
||||||
static Options CLI_OPTIONS = getCliOptions(ALL_OPTIONS);
|
static Options CLI_OPTIONS = getCliOptions(ALL_OPTIONS);
|
||||||
|
private static final String DEFAULT_CURR_VERSION = "Current Version";
|
||||||
|
private static final String DEFAULT_PREV_VERSION = "Previous Version";
|
||||||
|
private static final String BUILD_REL_PATH = "build/cluster/modules";
|
||||||
|
|
||||||
private static Options getCliOptions(List<Option> opts) {
|
private static Options getCliOptions(List<Option> opts) {
|
||||||
Options toRet = new Options();
|
Options toRet = new Options();
|
||||||
@ -112,15 +125,19 @@ public class CLIProcessor {
|
|||||||
CommandLine helpCmd = parser.parse(HELP_OPTIONS, args, true);
|
CommandLine helpCmd = parser.parse(HELP_OPTIONS, args, true);
|
||||||
boolean isHelp = helpCmd.hasOption(HELP_OPT);
|
boolean isHelp = helpCmd.hasOption(HELP_OPT);
|
||||||
if (isHelp) {
|
if (isHelp) {
|
||||||
return new CLIArgs(null, null, null, null, null, true);
|
return new CLIArgs(null, null, null, null, null, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandLine cmd = parser.parse(CLI_OPTIONS, args);
|
CommandLine cmd = parser.parse(CLI_OPTIONS, args);
|
||||||
String curVers = cmd.getOptionValue(CUR_VERS_OPT);
|
String curVers = cmd.hasOption(CUR_VERS_OPT) ? cmd.getOptionValue(CUR_VERS_OPT) : DEFAULT_CURR_VERSION;
|
||||||
String prevVers = cmd.getOptionValue(PREV_VERS_OPT);
|
String prevVers = cmd.hasOption(PREV_VERS_OPT) ? cmd.getOptionValue(PREV_VERS_OPT) : DEFAULT_PREV_VERSION;
|
||||||
String curVersPath = cmd.getOptionValue(CUR_VERS_PATH_OPT);
|
String curVersPath = cmd.hasOption(CUR_VERS_PATH_OPT)
|
||||||
|
? cmd.getOptionValue(CUR_VERS_PATH_OPT)
|
||||||
|
: Paths.get(cmd.getOptionValue(SRC_LOC_OPT), BUILD_REL_PATH).toString();
|
||||||
|
|
||||||
String prevVersPath = cmd.getOptionValue(PREV_VERS_PATH_OPT);
|
String prevVersPath = cmd.getOptionValue(PREV_VERS_PATH_OPT);
|
||||||
String srcPath = cmd.getOptionValue(SRC_LOC_OPT);
|
String srcPath = cmd.getOptionValue(SRC_LOC_OPT);
|
||||||
|
boolean makeUpdate = cmd.hasOption(UPDATE_OPT);
|
||||||
File curVersFile = new File(curVersPath);
|
File curVersFile = new File(curVersPath);
|
||||||
File prevVersFile = new File(prevVersPath);
|
File prevVersFile = new File(prevVersPath);
|
||||||
File srcPathFile = new File(srcPath);
|
File srcPathFile = new File(srcPath);
|
||||||
@ -137,7 +154,7 @@ public class CLIProcessor {
|
|||||||
throw new ParseException("No directory found at " + srcPathFile.getAbsolutePath());
|
throw new ParseException("No directory found at " + srcPathFile.getAbsolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CLIArgs(curVers, prevVers, curVersFile, prevVersFile, srcPathFile, false);
|
return new CLIArgs(curVers, prevVers, curVersFile, prevVersFile, srcPathFile, makeUpdate, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class CLIArgs {
|
public static class CLIArgs {
|
||||||
@ -148,14 +165,16 @@ public class CLIProcessor {
|
|||||||
private final File previousVersPath;
|
private final File previousVersPath;
|
||||||
private final boolean isHelp;
|
private final boolean isHelp;
|
||||||
private final File srcPath;
|
private final File srcPath;
|
||||||
|
private final boolean makeUpdate;
|
||||||
|
|
||||||
public CLIArgs(String currentVersion, String previousVersion, File currentVersPath, File previousVersPath, File srcPath, boolean isHelp) {
|
public CLIArgs(String currentVersion, String previousVersion, File currentVersPath, File previousVersPath, File srcPath, boolean makeUpdate, boolean isHelp) {
|
||||||
this.currentVersion = currentVersion;
|
this.currentVersion = currentVersion;
|
||||||
this.previousVersion = previousVersion;
|
this.previousVersion = previousVersion;
|
||||||
this.currentVersPath = currentVersPath;
|
this.currentVersPath = currentVersPath;
|
||||||
this.previousVersPath = previousVersPath;
|
this.previousVersPath = previousVersPath;
|
||||||
this.srcPath = srcPath;
|
this.srcPath = srcPath;
|
||||||
this.isHelp = isHelp;
|
this.isHelp = isHelp;
|
||||||
|
this.makeUpdate = makeUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCurrentVersion() {
|
public String getCurrentVersion() {
|
||||||
@ -178,6 +197,10 @@ public class CLIProcessor {
|
|||||||
return isHelp;
|
return isHelp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isMakeUpdate() {
|
||||||
|
return makeUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
public File getSrcPath() {
|
public File getSrcPath() {
|
||||||
return srcPath;
|
return srcPath;
|
||||||
}
|
}
|
||||||
|
@ -1,662 +0,0 @@
|
|||||||
package org.sleuthkit.autopsy.apiupdate;
|
|
||||||
|
|
||||||
import japicmp.cli.CliParser;
|
|
||||||
import japicmp.config.Options;
|
|
||||||
import japicmp.model.*;
|
|
||||||
import japicmp.model.JApiAnnotationElementValue.Type;
|
|
||||||
import static japicmp.model.JApiChangeStatus.MODIFIED;
|
|
||||||
import static japicmp.model.JApiChangeStatus.NEW;
|
|
||||||
import static japicmp.model.JApiChangeStatus.REMOVED;
|
|
||||||
import static japicmp.model.JApiChangeStatus.UNCHANGED;
|
|
||||||
import japicmp.output.OutputFilter;
|
|
||||||
import japicmp.output.OutputGenerator;
|
|
||||||
import javassist.bytecode.annotation.MemberValue;
|
|
||||||
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static japicmp.util.GenericTemplateHelper.haveGenericTemplateInterfacesChanges;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
import javassist.CtClass;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.sleuthkit.autopsy.apiupdate.ApiChangeDTO.FieldChangeDTO;
|
|
||||||
import org.sleuthkit.autopsy.apiupdate.ApiChangeDTO.InterfaceChangeDTO;
|
|
||||||
import org.sleuthkit.autopsy.apiupdate.ApiChangeDTO.SuperclassChangeDTO;
|
|
||||||
|
|
||||||
// taken from https://raw.githubusercontent.com/siom79/japicmp/master/japicmp/src/main/java/japicmp/output/stdout/StdoutOutputGenerator.java
|
|
||||||
public class ChangeOutputGenerator extends OutputGenerator<ApiChangeDTO> {
|
|
||||||
|
|
||||||
static final String NO_CHANGES = "No changes.";
|
|
||||||
static final String WARNING = "WARNING";
|
|
||||||
|
|
||||||
public ChangeOutputGenerator(Options options, List<JApiClass> jApiClasses) {
|
|
||||||
super(options, jApiClasses);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String generate() {
|
|
||||||
OutputFilter outputFilter = new OutputFilter(options);
|
|
||||||
outputFilter.filter(jApiClasses);
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append(options.getDifferenceDescription()).append('\n');
|
|
||||||
if (options.getIgnoreMissingClasses().isIgnoreAllMissingClasses()) {
|
|
||||||
sb.append(WARNING).append(": You are using the option '").append(CliParser.IGNORE_MISSING_CLASSES)
|
|
||||||
.append("', i.e. superclasses and interfaces that could not be found on the classpath are ignored.")
|
|
||||||
.append(" Hence changes caused by these superclasses and interfaces are not reflected in the output.\n");
|
|
||||||
} else if (options.getIgnoreMissingClasses().getIgnoreMissingClassRegularExpression().size() > 0) {
|
|
||||||
sb.append(WARNING).append(": You have ignored certain classes, i.e. superclasses and interfaces that could not ")
|
|
||||||
.append("be found on the classpath are ignored. Hence changes caused by these superclasses and interfaces are not reflected in the output.\n");
|
|
||||||
}
|
|
||||||
if (jApiClasses.size() > 0) {
|
|
||||||
for (JApiClass jApiClass : jApiClasses) {
|
|
||||||
processClass(sb, jApiClass);
|
|
||||||
processConstructors(sb, jApiClass);
|
|
||||||
processMethods(sb, jApiClass);
|
|
||||||
processAnnotations(sb, jApiClass, 1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sb.append(NO_CHANGES);
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processAnnotations(StringBuilder sb, JApiHasAnnotations jApiClass, int numberofTabs) {
|
|
||||||
List<JApiAnnotation> annotations = jApiClass.getAnnotations();
|
|
||||||
for (JApiAnnotation jApiAnnotation : annotations) {
|
|
||||||
appendAnnotation(sb, signs(jApiAnnotation), jApiAnnotation, numberofTabs);
|
|
||||||
List<JApiAnnotationElement> elements = jApiAnnotation.getElements();
|
|
||||||
for (JApiAnnotationElement jApiAnnotationElement : elements) {
|
|
||||||
appendAnnotationElement(sb, signs(jApiAnnotationElement), jApiAnnotationElement, numberofTabs + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processConstructors(StringBuilder sb, JApiClass jApiClass) {
|
|
||||||
List<JApiConstructor> constructors = jApiClass.getConstructors();
|
|
||||||
for (JApiConstructor jApiConstructor : constructors) {
|
|
||||||
appendBehavior(sb, signs(jApiConstructor), jApiConstructor, "CONSTRUCTOR:");
|
|
||||||
processAnnotations(sb, jApiConstructor, 2);
|
|
||||||
processExceptions(sb, jApiConstructor, 2);
|
|
||||||
processGenericTemplateChanges(sb, jApiConstructor, 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processMethods(StringBuilder sb, JApiClass jApiClass) {
|
|
||||||
List<JApiMethod> methods = jApiClass.getMethods();
|
|
||||||
for (JApiMethod jApiMethod : methods) {
|
|
||||||
appendBehavior(sb, signs(jApiMethod), jApiMethod, "METHOD:");
|
|
||||||
processAnnotations(sb, jApiMethod, 2);
|
|
||||||
processExceptions(sb, jApiMethod, 2);
|
|
||||||
processGenericTemplateChanges(sb, jApiMethod, 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processExceptions(StringBuilder sb, JApiBehavior jApiBehavior, int indent) {
|
|
||||||
for (JApiException exception : jApiBehavior.getExceptions()) {
|
|
||||||
appendException(sb, signs(exception), exception, indent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void appendException(StringBuilder sb, String signs, JApiException jApiException, int indent) {
|
|
||||||
sb.append(tabs(indent)).append(signs).append(" ").append(jApiException.getChangeStatus()).append(" EXCEPTION: ").append(jApiException.getName()).append("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processClass(StringBuilder sb, JApiClass jApiClass) {
|
|
||||||
appendClass(sb, signs(jApiClass), jApiClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void appendBehavior(StringBuilder sb, String signs, JApiBehavior jApiBehavior, String classMemberType) {
|
|
||||||
sb.append("\t").append(signs).append(" ").append(jApiBehavior.getChangeStatus()).append(" ").append(classMemberType).append(" ")
|
|
||||||
.append(accessModifierAsString(jApiBehavior)).append(abstractModifierAsString(jApiBehavior)).append(staticModifierAsString(jApiBehavior))
|
|
||||||
.append(finalModifierAsString(jApiBehavior)).append(syntheticModifierAsString(jApiBehavior)).append(bridgeModifierAsString(jApiBehavior))
|
|
||||||
.append(returnType(jApiBehavior)).append(jApiBehavior.getName()).append("(");
|
|
||||||
int paramCount = 0;
|
|
||||||
for (JApiParameter jApiParameter : jApiBehavior.getParameters()) {
|
|
||||||
if (paramCount > 0) {
|
|
||||||
sb.append(", ");
|
|
||||||
}
|
|
||||||
sb.append(jApiParameter.getType());
|
|
||||||
appendGenericTypes(sb, jApiParameter);
|
|
||||||
paramCount++;
|
|
||||||
}
|
|
||||||
sb.append(")\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void appendGenericTypes(StringBuilder sb, JApiHasGenericTypes jApiHasGenericTypes) {
|
|
||||||
if (!jApiHasGenericTypes.getNewGenericTypes().isEmpty() || !jApiHasGenericTypes.getOldGenericTypes().isEmpty()) {
|
|
||||||
if (jApiHasGenericTypes instanceof JApiCompatibility) {
|
|
||||||
List<JApiCompatibilityChange> compatibilityChanges = ((JApiCompatibility) jApiHasGenericTypes).getCompatibilityChanges();
|
|
||||||
appendGenericTypesForCompatibilityChanges(sb, jApiHasGenericTypes, compatibilityChanges);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void appendGenericTypesForCompatibilityChanges(StringBuilder sb, JApiHasGenericTypes jApiHasGenericTypes, List<JApiCompatibilityChange> compatibilityChanges) {
|
|
||||||
if (compatibilityChanges.contains(JApiCompatibilityChange.METHOD_PARAMETER_GENERICS_CHANGED)
|
|
||||||
|| compatibilityChanges.contains(JApiCompatibilityChange.METHOD_RETURN_TYPE_GENERICS_CHANGED)
|
|
||||||
|| compatibilityChanges.contains(JApiCompatibilityChange.FIELD_GENERICS_CHANGED)
|
|
||||||
|| compatibilityChanges.contains(JApiCompatibilityChange.CLASS_GENERIC_TEMPLATE_GENERICS_CHANGED)) {
|
|
||||||
appendGenericTypes(sb, false, jApiHasGenericTypes.getNewGenericTypes());
|
|
||||||
appendGenericTypes(sb, true, jApiHasGenericTypes.getOldGenericTypes());
|
|
||||||
} else {
|
|
||||||
if (!jApiHasGenericTypes.getNewGenericTypes().isEmpty()) {
|
|
||||||
appendGenericTypes(sb, false, jApiHasGenericTypes.getNewGenericTypes());
|
|
||||||
}
|
|
||||||
if (!jApiHasGenericTypes.getOldGenericTypes().isEmpty()) {
|
|
||||||
appendGenericTypes(sb, false, jApiHasGenericTypes.getOldGenericTypes());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void appendGenericTypes(StringBuilder sb, boolean withChangeInParenthesis, List<JApiGenericType> genericTypes) {
|
|
||||||
if (!genericTypes.isEmpty()) {
|
|
||||||
if (withChangeInParenthesis) {
|
|
||||||
sb.append("(<- ");
|
|
||||||
}
|
|
||||||
sb.append("<");
|
|
||||||
int count = 0;
|
|
||||||
for (JApiGenericType genericType : genericTypes) {
|
|
||||||
if (count > 0) {
|
|
||||||
sb.append(",");
|
|
||||||
}
|
|
||||||
appendGenericType(sb, genericType);
|
|
||||||
if (!genericType.getGenericTypes().isEmpty()) {
|
|
||||||
appendGenericTypes(sb, false, genericType.getGenericTypes());
|
|
||||||
}
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
sb.append(">");
|
|
||||||
if (withChangeInParenthesis) {
|
|
||||||
sb.append(")");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void appendGenericType(StringBuilder sb, JApiGenericType jApiGenericType) {
|
|
||||||
if (jApiGenericType.getGenericWildCard() == JApiGenericType.JApiGenericWildCard.NONE) {
|
|
||||||
sb.append(jApiGenericType.getType());
|
|
||||||
} else if (jApiGenericType.getGenericWildCard() == JApiGenericType.JApiGenericWildCard.UNBOUNDED) {
|
|
||||||
sb.append("?");
|
|
||||||
} else if (jApiGenericType.getGenericWildCard() == JApiGenericType.JApiGenericWildCard.EXTENDS) {
|
|
||||||
sb.append("? extends ").append(jApiGenericType.getType());
|
|
||||||
} else if (jApiGenericType.getGenericWildCard() == JApiGenericType.JApiGenericWildCard.SUPER) {
|
|
||||||
sb.append("? super ").append(jApiGenericType.getType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String returnType(JApiBehavior jApiBehavior) {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
if (jApiBehavior instanceof JApiMethod) {
|
|
||||||
JApiMethod method = (JApiMethod) jApiBehavior;
|
|
||||||
JApiReturnType jApiReturnType = method.getReturnType();
|
|
||||||
if (jApiReturnType.getChangeStatus() == JApiChangeStatus.UNCHANGED) {
|
|
||||||
sb.append(jApiReturnType.getNewReturnType());
|
|
||||||
appendGenericTypes(sb, jApiReturnType);
|
|
||||||
sb.append(" ");
|
|
||||||
} else if (jApiReturnType.getChangeStatus() == JApiChangeStatus.MODIFIED) {
|
|
||||||
sb.append(jApiReturnType.getNewReturnType());
|
|
||||||
appendGenericTypes(sb, jApiReturnType);
|
|
||||||
sb.append(" (<-");
|
|
||||||
sb.append(jApiReturnType.getOldReturnType());
|
|
||||||
appendGenericTypes(sb, jApiReturnType);
|
|
||||||
sb.append(") ");
|
|
||||||
} else if (jApiReturnType.getChangeStatus() == JApiChangeStatus.NEW) {
|
|
||||||
sb.append(jApiReturnType.getNewReturnType());
|
|
||||||
appendGenericTypes(sb, jApiReturnType);
|
|
||||||
sb.append(" ");
|
|
||||||
} else {
|
|
||||||
sb.append(jApiReturnType.getOldReturnType());
|
|
||||||
appendGenericTypes(sb, jApiReturnType);
|
|
||||||
sb.append(" ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void appendAnnotation(StringBuilder sb, String signs, JApiAnnotation jApiAnnotation, int numberOfTabs) {
|
|
||||||
sb.append(String.format("%s%s %s ANNOTATION: %s\n", tabs(numberOfTabs), signs, jApiAnnotation.getChangeStatus(), jApiAnnotation.getFullyQualifiedName()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void appendAnnotationElement(StringBuilder sb, String signs, JApiAnnotationElement jApiAnnotationElement, int numberOfTabs) {
|
|
||||||
sb.append(String.format("%s%s %s ELEMENT: %s=", tabs(numberOfTabs), signs, jApiAnnotationElement.getChangeStatus(), jApiAnnotationElement.getName()));
|
|
||||||
Optional<MemberValue> oldValue = jApiAnnotationElement.getOldValue();
|
|
||||||
Optional<MemberValue> newValue = jApiAnnotationElement.getNewValue();
|
|
||||||
if (oldValue.isPresent() && newValue.isPresent()) {
|
|
||||||
if (jApiAnnotationElement.getChangeStatus() == JApiChangeStatus.UNCHANGED) {
|
|
||||||
sb.append(elementValueList2String(jApiAnnotationElement.getNewElementValues()));
|
|
||||||
} else if (jApiAnnotationElement.getChangeStatus() == JApiChangeStatus.REMOVED) {
|
|
||||||
sb.append(String.format("%s (-)", elementValueList2String(jApiAnnotationElement.getOldElementValues())));
|
|
||||||
} else if (jApiAnnotationElement.getChangeStatus() == JApiChangeStatus.NEW) {
|
|
||||||
sb.append(String.format("%s (+)", elementValueList2String(jApiAnnotationElement.getNewElementValues())));
|
|
||||||
} else if (jApiAnnotationElement.getChangeStatus() == JApiChangeStatus.MODIFIED) {
|
|
||||||
sb.append(String.format("%s (<- %s)", elementValueList2String(jApiAnnotationElement.getNewElementValues()), elementValueList2String(jApiAnnotationElement.getOldElementValues())));
|
|
||||||
}
|
|
||||||
} else if (!oldValue.isPresent() && newValue.isPresent()) {
|
|
||||||
sb.append(String.format("%s (+)", elementValueList2String(jApiAnnotationElement.getNewElementValues())));
|
|
||||||
} else if (oldValue.isPresent() && !newValue.isPresent()) {
|
|
||||||
sb.append(String.format("%s (-)", elementValueList2String(jApiAnnotationElement.getOldElementValues())));
|
|
||||||
} else {
|
|
||||||
sb.append(" n.a.");
|
|
||||||
}
|
|
||||||
sb.append("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void appendClass(StringBuilder sb, String signs, JApiClass jApiClass) {
|
|
||||||
sb.append(signs).append(" ").append(jApiClass.getChangeStatus()).append(" ")
|
|
||||||
.append(processClassType(jApiClass)).append(": ")
|
|
||||||
.append(accessModifierAsString(jApiClass))
|
|
||||||
.append(abstractModifierAsString(jApiClass))
|
|
||||||
.append(staticModifierAsString(jApiClass))
|
|
||||||
.append(finalModifierAsString(jApiClass))
|
|
||||||
.append(syntheticModifierAsString(jApiClass))
|
|
||||||
.append(jApiClass.getFullyQualifiedName()).append(" ")
|
|
||||||
.append(javaObjectSerializationStatus(jApiClass)).append("\n");
|
|
||||||
|
|
||||||
processGenericTemplateChanges(sb, jApiClass, 1);
|
|
||||||
processInterfaceChanges(sb, jApiClass);
|
|
||||||
processSuperclassChanges(sb, jApiClass);
|
|
||||||
processFieldChanges(sb, jApiClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getClassString(JApiClass clz, boolean oldClass) {
|
|
||||||
// TODO serial version id
|
|
||||||
// TODO annotations
|
|
||||||
String accessModifier = str(get(clz.getAccessModifier(), oldClass).orElse(null));
|
|
||||||
String abstractModifier = str(get(clz.getAbstractModifier(), oldClass).orElse(null));
|
|
||||||
String staticModifier = str(get(clz.getStaticModifier(), oldClass).orElse(null));
|
|
||||||
String finalModifier = str(get(clz.getFinalModifier(), oldClass).orElse(null));
|
|
||||||
String syntheticModifier = str(get(clz.getSyntheticModifier(), oldClass).orElse(null));
|
|
||||||
|
|
||||||
String type = str(clz.getClassType(), oldClass);
|
|
||||||
String name = clz.getFullyQualifiedName();
|
|
||||||
|
|
||||||
String genericModifier = strGeneric(clz.getGenericTemplates(), oldClass);
|
|
||||||
|
|
||||||
String implementsModifier = strImplements(clz.getInterfaces(), oldClass);
|
|
||||||
String extendsModifier = str(clz.getSuperclass(), oldClass);
|
|
||||||
|
|
||||||
return Stream.of(
|
|
||||||
accessModifier,
|
|
||||||
abstractModifier,
|
|
||||||
staticModifier,
|
|
||||||
finalModifier,
|
|
||||||
syntheticModifier,
|
|
||||||
type,
|
|
||||||
name + (StringUtils.isBlank(genericModifier) ? "" : genericModifier),
|
|
||||||
implementsModifier,
|
|
||||||
extendsModifier)
|
|
||||||
.filter(StringUtils::isNotBlank)
|
|
||||||
.collect(Collectors.joining(" "));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private String str(JApiSuperclass supClz, boolean oldClass) {
|
|
||||||
Optional<CtClass> ctClass = convert(oldClass ? supClz.getOldSuperclass() : supClz.getNewSuperclass());
|
|
||||||
String supClassExt = ctClass.map(ctClz -> str(ctClz)).orElse(null);
|
|
||||||
return StringUtils.isBlank(supClassExt) ? null : "extends " + supClassExt;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String strImplements(List<JApiImplementedInterface> interfaces, boolean oldClass) {
|
|
||||||
if (interfaces.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
String interfaceStr = interfaces.stream()
|
|
||||||
.filter(i -> (oldClass && i.getChangeStatus() == NEW) || (!oldClass && i.getChangeStatus() == REMOVED))
|
|
||||||
.map(i -> str(i.getCtClass()))
|
|
||||||
.collect(Collectors.joining(", "));
|
|
||||||
|
|
||||||
return StringUtils.isNotBlank(interfaceStr) ? "implements " + interfaceStr : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private String str(CtClass ctClass) {
|
|
||||||
return ctClass.getName() + (StringUtils.isBlank(ctClass.getGenericSignature()) ? "" : "<" + ctClass.getGenericSignature() + ">");
|
|
||||||
}
|
|
||||||
|
|
||||||
private String str(JApiClassType classType, boolean oldClass) {
|
|
||||||
return Optional.ofNullable(classType)
|
|
||||||
.flatMap(ct -> convert(oldClass ? ct.getOldTypeOptional() : ct.getNewTypeOptional()))
|
|
||||||
.map(ct -> ct.name().toLowerCase())
|
|
||||||
.orElse("class");
|
|
||||||
}
|
|
||||||
|
|
||||||
private String strGeneric(List<JApiGenericTemplate> templates, boolean oldClass) {
|
|
||||||
if (templates.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
String genericParams = templates.stream()
|
|
||||||
.map(t -> convert(oldClass ?
|
|
||||||
str(t.getName(), convert(t.getOldTypeOptional()), t.getOldInterfaceTypes()) :
|
|
||||||
str(t.getName(), convert(t.getNewTypeOptional()), t.getNewInterfaceTypes())
|
|
||||||
)
|
|
||||||
.filter(Optional::isPresent)
|
|
||||||
.map(t -> t.get())
|
|
||||||
.collect(Collectors.joining(", "));
|
|
||||||
|
|
||||||
return StringUtils.isBlank(genericParams)
|
|
||||||
? null
|
|
||||||
: "<" + genericParams + ">";
|
|
||||||
}
|
|
||||||
|
|
||||||
private String strGeneric(String name, Optional<String> mainType, List<JApiGenericType> genericType) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// jApiGenericTemplate.getName() + ":" + interfaceTypes.join( "&")
|
|
||||||
//
|
|
||||||
// private List<GenericTemplateChangeDTO> getGenericTemplateChanges(JApiHasGenericTemplates jApiHasGenericTemplates) {
|
|
||||||
// if (!genericTemplates.isEmpty()) {
|
|
||||||
// sb.append(tabs(numberOfTabs)).append("GENERIC TEMPLATES: ");
|
|
||||||
// genericTemplates.sort(Comparator.comparing(JApiGenericTemplate::getName));
|
|
||||||
// int count = 0;
|
|
||||||
// for (JApiGenericTemplate jApiGenericTemplate : genericTemplates) {
|
|
||||||
// if (count > 0) {
|
|
||||||
// sb.append(", ");
|
|
||||||
// }
|
|
||||||
// count++;
|
|
||||||
// sb.append(signs(jApiGenericTemplate));
|
|
||||||
// if (sb.charAt(sb.length() - 1) != ' ') {
|
|
||||||
// sb.append(" ");
|
|
||||||
// }
|
|
||||||
// sb.append(jApiGenericTemplate.getName()).append(":");
|
|
||||||
// JApiChangeStatus changeStatus = jApiGenericTemplate.getChangeStatus();
|
|
||||||
// if (changeStatus == JApiChangeStatus.NEW || changeStatus == JApiChangeStatus.UNCHANGED) {
|
|
||||||
// sb.append(jApiGenericTemplate.getNewType());
|
|
||||||
// if (jApiGenericTemplate instanceof JApiCompatibility) {
|
|
||||||
// appendGenericTypesForCompatibilityChanges(sb, jApiGenericTemplate, ((JApiCompatibility) jApiHasGenericTemplates).getCompatibilityChanges());
|
|
||||||
// }
|
|
||||||
// } else if (changeStatus == JApiChangeStatus.REMOVED) {
|
|
||||||
// sb.append(jApiGenericTemplate.getOldType());
|
|
||||||
// if (jApiGenericTemplate instanceof JApiCompatibility) {
|
|
||||||
// appendGenericTypesForCompatibilityChanges(sb, jApiGenericTemplate, ((JApiCompatibility) jApiHasGenericTemplates).getCompatibilityChanges());
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// sb.append(jApiGenericTemplate.getNewType());
|
|
||||||
// appendGenericTypes(sb, false, jApiGenericTemplate.getNewGenericTypes());
|
|
||||||
// sb.append(" (<-").append(jApiGenericTemplate.getOldType());
|
|
||||||
// appendGenericTypes(sb, false, jApiGenericTemplate.getOldGenericTypes());
|
|
||||||
// sb.append(")");
|
|
||||||
// }
|
|
||||||
// if (!jApiGenericTemplate.getOldInterfaceTypes().isEmpty() || !jApiGenericTemplate.getNewInterfaceTypes().isEmpty()) {
|
|
||||||
// if (haveGenericTemplateInterfacesChanges(jApiGenericTemplate.getOldInterfaceTypes(), jApiGenericTemplate.getNewInterfaceTypes())) {
|
|
||||||
// appendGenericTemplatesInterfaces(sb, jApiGenericTemplate, false, true);
|
|
||||||
// sb.append(" (<-");
|
|
||||||
// appendGenericTemplatesInterfaces(sb, jApiGenericTemplate, true, false);
|
|
||||||
// sb.append(")");
|
|
||||||
// } else {
|
|
||||||
// appendGenericTemplatesInterfaces(sb, jApiGenericTemplate, false, true);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// sb.append("\n");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
private void appendGenericTemplatesInterfaces(StringBuilder sb, JApiGenericTemplate jApiGenericTemplate, boolean printOld, boolean printNew) {
|
|
||||||
if (printOld) {
|
|
||||||
for (JApiGenericType jApiGenericType : jApiGenericTemplate.getOldInterfaceTypes()) {
|
|
||||||
sb.append(" & ");
|
|
||||||
sb.append(jApiGenericType.getType());
|
|
||||||
appendGenericTypes(sb, false, jApiGenericType.getGenericTypes());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (printNew) {
|
|
||||||
for (JApiGenericType jApiGenericType : jApiGenericTemplate.getNewInterfaceTypes()) {
|
|
||||||
sb.append(" & ");
|
|
||||||
sb.append(jApiGenericType.getType());
|
|
||||||
appendGenericTypes(sb, false, jApiGenericType.getGenericTypes());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private FieldChangeDTO getFieldChange(JApiField field) {
|
|
||||||
return new FieldChangeDTO(
|
|
||||||
field.getChangeStatus(),
|
|
||||||
Optional.ofNullable(getFieldString(field, true)),
|
|
||||||
Optional.ofNullable(getFieldString(field, false)));
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getFieldString(JApiField field, boolean oldField) {
|
|
||||||
String accessModifier = str(get(field.getAccessModifier(), oldField).orElse(null));
|
|
||||||
String staticModifier = str(get(field.getStaticModifier(), oldField).orElse(null));
|
|
||||||
String finalModifier = str(get(field.getFinalModifier(), oldField).orElse(null));
|
|
||||||
String syntheticModifier = str(get(field.getSyntheticModifier(), oldField).orElse(null));
|
|
||||||
String fieldType = strOpt(field.getType(), oldField).orElse(null);
|
|
||||||
String name = field.getName();
|
|
||||||
|
|
||||||
return Stream.of(accessModifier, staticModifier, finalModifier, syntheticModifier, fieldType, name)
|
|
||||||
.filter(StringUtils::isNotBlank)
|
|
||||||
.collect(Collectors.joining(" "));
|
|
||||||
}
|
|
||||||
|
|
||||||
private String str(AccessModifier modifier) {
|
|
||||||
if (modifier == null || modifier == AccessModifier.PACKAGE_PROTECTED) {
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
return modifier.name().toLowerCase();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String str(StaticModifier modifier) {
|
|
||||||
return (modifier == StaticModifier.STATIC)
|
|
||||||
? "static"
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String str(FinalModifier modifier) {
|
|
||||||
return (modifier == FinalModifier.FINAL)
|
|
||||||
? "final"
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String str(SyntheticModifier modifier) {
|
|
||||||
return (modifier == SyntheticModifier.SYNTHETIC)
|
|
||||||
? "synthetic"
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String str(AbstractModifier modifier) {
|
|
||||||
return (modifier == AbstractModifier.ABSTRACT)
|
|
||||||
? "abstract"
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Optional<String> strOpt(JApiType tp, boolean oldField) {
|
|
||||||
return oldField ? convert(tp.getOldTypeOptional()) : convert(tp.getNewTypeOptional());
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T> Optional<T> get(JApiModifier<T> modifier, boolean oldField) {
|
|
||||||
return oldField ? convert(modifier.getOldModifier()) : convert(modifier.getNewModifier());
|
|
||||||
}
|
|
||||||
|
|
||||||
// private Optional<SuperclassChangeDTO> getSuperClassChange(JApiSuperclass jApiSuperclass) {
|
|
||||||
// return jApiSuperclass.getChangeStatus() != JApiChangeStatus.UNCHANGED
|
|
||||||
// ? Optional.ofNullable(new SuperclassChangeDTO(
|
|
||||||
// convert(jApiSuperclass.getOldSuperclassName()),
|
|
||||||
// convert(jApiSuperclass.getNewSuperclassName())))
|
|
||||||
// : Optional.empty();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private List<InterfaceChangeDTO> getInterfaceChanges(JApiClass jApiClass) {
|
|
||||||
// return jApiClass.getInterfaces().stream()
|
|
||||||
// .filter(intfc -> intfc.getChangeStatus() != JApiChangeStatus.UNCHANGED)
|
|
||||||
// .map(intfc -> new InterfaceChangeDTO(intfc.getChangeStatus(), intfc.getFullyQualifiedName()))
|
|
||||||
// .collect(Collectors.toList());
|
|
||||||
// }
|
|
||||||
private <T> Optional<T> convert(japicmp.util.Optional<T> apiOpt) {
|
|
||||||
T val = apiOpt.or((T) null);
|
|
||||||
return java.util.Optional.ofNullable(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// private void processClassFileFormatVersionChanges(StringBuilder sb, JApiClass jApiClass) {
|
|
||||||
// JApiClassFileFormatVersion classFileFormatVersion = jApiClass.getClassFileFormatVersion();
|
|
||||||
// sb.append(tabs(1))
|
|
||||||
// .append(signs(classFileFormatVersion))
|
|
||||||
// .append(" CLASS FILE FORMAT VERSION: ");
|
|
||||||
// if (classFileFormatVersion.getMajorVersionNew() != -1 && classFileFormatVersion.getMinorVersionNew() != -1) {
|
|
||||||
// sb.append(classFileFormatVersion.getMajorVersionNew()).append(".").append(classFileFormatVersion.getMinorVersionNew());
|
|
||||||
// } else {
|
|
||||||
// sb.append("n.a.");
|
|
||||||
// }
|
|
||||||
// sb.append(" <- ");
|
|
||||||
// if (classFileFormatVersion.getMajorVersionOld() != -1 && classFileFormatVersion.getMinorVersionOld() != -1) {
|
|
||||||
// sb.append(classFileFormatVersion.getMajorVersionOld()).append(".").append(classFileFormatVersion.getMinorVersionOld());
|
|
||||||
// } else {
|
|
||||||
// sb.append("n.a.");
|
|
||||||
// }
|
|
||||||
// sb.append("\n");
|
|
||||||
// }
|
|
||||||
// private String processClassType(JApiClass jApiClass) {
|
|
||||||
// JApiClassType classType = jApiClass.getClassType();
|
|
||||||
// switch (classType.getChangeStatus()) {
|
|
||||||
// case NEW:
|
|
||||||
// return classType.getNewType();
|
|
||||||
// case REMOVED:
|
|
||||||
// return classType.getOldType();
|
|
||||||
// case MODIFIED:
|
|
||||||
// return classType.getNewType() + " (<- " + classType.getOldType() + ") ";
|
|
||||||
// case UNCHANGED:
|
|
||||||
// return classType.getOldType();
|
|
||||||
// }
|
|
||||||
// return "n.a.";
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // TODO do we need this
|
|
||||||
// private String getJavaObjectSerializationStatus(JApiClass jApiClass) {
|
|
||||||
// return jApiClass.getJavaObjectSerializationCompatible().getDescription();
|
|
||||||
// }
|
|
||||||
// private String elementValueList2String(List<JApiAnnotationElementValue> values) {
|
|
||||||
// StringBuilder sb = new StringBuilder();
|
|
||||||
// for (JApiAnnotationElementValue value : values) {
|
|
||||||
// if (sb.length() > 0) {
|
|
||||||
// sb.append(",");
|
|
||||||
// }
|
|
||||||
// if (value.getName().isPresent()) {
|
|
||||||
// sb.append(value.getName().get()).append("=");
|
|
||||||
// }
|
|
||||||
// if (value.getType() != Type.Array && value.getType() != Type.Annotation) {
|
|
||||||
// if (value.getType() == Type.Enum) {
|
|
||||||
// sb.append(value.getFullyQualifiedName()).append(".").append(value.getValueString());
|
|
||||||
// } else {
|
|
||||||
// sb.append(value.getValueString());
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// if (value.getType() == Type.Array) {
|
|
||||||
// sb.append("{").append(elementValueList2String(value.getValues())).append("}");
|
|
||||||
// } else if (value.getType() == Type.Annotation) {
|
|
||||||
// sb.append("@").append(value.getFullyQualifiedName()).append("(").append(elementValueList2String(value.getValues())).append(")");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return sb.toString();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private String tabs(int numberOfTabs) {
|
|
||||||
// if (numberOfTabs <= 0) {
|
|
||||||
// return "";
|
|
||||||
// } else if (numberOfTabs == 1) {
|
|
||||||
// return "\t";
|
|
||||||
// } else if (numberOfTabs == 2) {
|
|
||||||
// return "\t\t";
|
|
||||||
// } else {
|
|
||||||
// StringBuilder sb = new StringBuilder();
|
|
||||||
// for (int i = 0; i < numberOfTabs; i++) {
|
|
||||||
// sb.append("\t");
|
|
||||||
// }
|
|
||||||
// return sb.toString();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// private String signs(JApiHasChangeStatus hasChangeStatus) {
|
|
||||||
// JApiChangeStatus changeStatus = hasChangeStatus.getChangeStatus();
|
|
||||||
// String retVal = "???";
|
|
||||||
// switch (changeStatus) {
|
|
||||||
// case UNCHANGED:
|
|
||||||
// retVal = "===";
|
|
||||||
// break;
|
|
||||||
// case NEW:
|
|
||||||
// retVal = "+++";
|
|
||||||
// break;
|
|
||||||
// case REMOVED:
|
|
||||||
// retVal = "---";
|
|
||||||
// break;
|
|
||||||
// case MODIFIED:
|
|
||||||
// retVal = "***";
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// boolean binaryCompatible = true;
|
|
||||||
// boolean sourceCompatible = true;
|
|
||||||
// if (hasChangeStatus instanceof JApiCompatibility) {
|
|
||||||
// JApiCompatibility jApiCompatibility = (JApiCompatibility) hasChangeStatus;
|
|
||||||
// binaryCompatible = jApiCompatibility.isBinaryCompatible();
|
|
||||||
// sourceCompatible = jApiCompatibility.isSourceCompatible();
|
|
||||||
// }
|
|
||||||
// if (binaryCompatible) {
|
|
||||||
// if (sourceCompatible) {
|
|
||||||
// retVal += " ";
|
|
||||||
// } else {
|
|
||||||
// retVal += "*";
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// retVal += "!";
|
|
||||||
// }
|
|
||||||
// return retVal;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private String bridgeModifierAsString(JApiHasBridgeModifier modifier) {
|
|
||||||
// JApiModifier<BridgeModifier> bridgeModifier = modifier.getBridgeModifier();
|
|
||||||
// return modifierAsString(bridgeModifier, BridgeModifier.NON_BRIDGE);
|
|
||||||
// }
|
|
||||||
// private <T> String modifierAsString(JApiModifier<T> modifier, T notPrintValue) {
|
|
||||||
// if (modifier.getOldModifier().isPresent() && modifier.getNewModifier().isPresent()) {
|
|
||||||
// if (modifier.getChangeStatus() == JApiChangeStatus.MODIFIED) {
|
|
||||||
// return modifier.getNewModifier().get() + " (<- " + modifier.getOldModifier().get() + ") ";
|
|
||||||
// } else if (modifier.getChangeStatus() == JApiChangeStatus.NEW) {
|
|
||||||
// if (modifier.getNewModifier().get() != notPrintValue) {
|
|
||||||
// return modifier.getNewModifier().get() + "(+) ";
|
|
||||||
// }
|
|
||||||
// } else if (modifier.getChangeStatus() == JApiChangeStatus.REMOVED) {
|
|
||||||
// if (modifier.getOldModifier().get() != notPrintValue) {
|
|
||||||
// return modifier.getOldModifier().get() + "(-) ";
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// if (modifier.getNewModifier().get() != notPrintValue) {
|
|
||||||
// return modifier.getNewModifier().get() + " ";
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } else if (modifier.getOldModifier().isPresent()) {
|
|
||||||
// if (modifier.getOldModifier().get() != notPrintValue) {
|
|
||||||
// return modifier.getOldModifier().get() + "(-) ";
|
|
||||||
// }
|
|
||||||
// } else if (modifier.getNewModifier().isPresent()) {
|
|
||||||
// if (modifier.getNewModifier().get() != notPrintValue) {
|
|
||||||
// return modifier.getNewModifier().get() + "(+) ";
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return "";
|
|
||||||
// }
|
|
||||||
// private String fieldTypeChangeAsString(JApiField field) {
|
|
||||||
// JApiType type = field.getType();
|
|
||||||
// if (type.getOldTypeOptional().isPresent() && type.getNewTypeOptional().isPresent()) {
|
|
||||||
// if (type.getChangeStatus() == JApiChangeStatus.MODIFIED) {
|
|
||||||
// return type.getNewTypeOptional().get() + " (<- " + type.getOldTypeOptional().get() + ")";
|
|
||||||
// } else if (type.getChangeStatus() == JApiChangeStatus.NEW) {
|
|
||||||
// return type.getNewTypeOptional().get() + "(+)";
|
|
||||||
// } else if (type.getChangeStatus() == JApiChangeStatus.REMOVED) {
|
|
||||||
// return type.getOldTypeOptional().get() + "(-)";
|
|
||||||
// } else {
|
|
||||||
// return type.getNewTypeOptional().get();
|
|
||||||
// }
|
|
||||||
// } else if (type.getOldTypeOptional().isPresent() && !type.getNewTypeOptional().isPresent()) {
|
|
||||||
// return type.getOldTypeOptional().get();
|
|
||||||
// } else if (!type.getOldTypeOptional().isPresent() && type.getNewTypeOptional().isPresent()) {
|
|
||||||
// return type.getNewTypeOptional().get();
|
|
||||||
// }
|
|
||||||
// return "n.a.";
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
|
@ -4,10 +4,15 @@
|
|||||||
package org.sleuthkit.autopsy.apiupdate;
|
package org.sleuthkit.autopsy.apiupdate;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import org.apache.commons.cli.ParseException;
|
import org.apache.commons.cli.ParseException;
|
||||||
|
import org.sleuthkit.autopsy.apiupdate.APIDiff.ComparisonRecord;
|
||||||
import org.sleuthkit.autopsy.apiupdate.CLIProcessor.CLIArgs;
|
import org.sleuthkit.autopsy.apiupdate.CLIProcessor.CLIArgs;
|
||||||
|
import org.sleuthkit.autopsy.apiupdate.ModuleUpdates.ModuleVersionNumbers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -15,6 +20,8 @@ import org.sleuthkit.autopsy.apiupdate.CLIProcessor.CLIArgs;
|
|||||||
*/
|
*/
|
||||||
public class Main {
|
public class Main {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(Main.class.getName());
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
args = "-c C:\\Users\\gregd\\Desktop\\apidiff\\new -p C:\\Users\\gregd\\Desktop\\apidiff\\old -cv 4.21.0 -pv 4.20.0 -s C:\\Users\\gregd\\Documents\\Source\\autopsy".split(" ");
|
args = "-c C:\\Users\\gregd\\Desktop\\apidiff\\new -p C:\\Users\\gregd\\Desktop\\apidiff\\old -cv 4.21.0 -pv 4.20.0 -s C:\\Users\\gregd\\Documents\\Source\\autopsy".split(" ");
|
||||||
CLIArgs cliArgs;
|
CLIArgs cliArgs;
|
||||||
@ -29,67 +36,69 @@ public class Main {
|
|||||||
System.exit(-1);
|
System.exit(-1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map<String, ModuleVersionNumbers> versNums = Stream.of(
|
|
||||||
// new ModuleVersionNumbers(
|
|
||||||
// "org.sleuthkit.autopsy.core",
|
|
||||||
// new ModuleUpdates.SemVer(1,2,3),
|
|
||||||
// 4,
|
|
||||||
// new ReleaseVal("org.sleuthkit.autopsy.core", 5)),
|
|
||||||
// new ModuleVersionNumbers(
|
|
||||||
// "org.sleuthkit.autopsy.corelibs",
|
|
||||||
// new ModuleUpdates.SemVer(6,7,8),
|
|
||||||
// 9,
|
|
||||||
// new ReleaseVal("org.sleuthkit.autopsy.corelibs", 10)))
|
|
||||||
// .collect(Collectors.toMap(v -> v.getModuleName(), v -> v, (v1, v2) -> v1));
|
|
||||||
//
|
|
||||||
// ModuleUpdates.setVersions(cliArgs.getSrcPath(), versNums);
|
|
||||||
|
|
||||||
|
Map<String, ModuleVersionNumbers> newVersionNumMapping = new HashMap<>();
|
||||||
|
|
||||||
for (String commonJarFileName : APIDiff.getCommonJars(cliArgs.getPreviousVersPath(), cliArgs.getCurrentVersPath())) {
|
for (String commonJarFileName : APIDiff.getCommonJars(cliArgs.getPreviousVersPath(), cliArgs.getCurrentVersPath())) {
|
||||||
try {
|
try {
|
||||||
// ModuleVersionNumbers m = ModuleUpdates.getVersionsFromJar(cliArgs.getPreviousVersPath().toPath().resolve(commonJarFileName).toFile());
|
ModuleVersionNumbers prevVersionNums = ModuleUpdates.getVersionsFromJar(cliArgs.getPreviousVersPath().toPath().resolve(commonJarFileName).toFile());
|
||||||
// System.out.println(MessageFormat.format("release: {0}, spec: {1}, implementation: {2}", m.getRelease().getFullReleaseStr(), m.getSpec().getSemVerStr(), m.getImplementation()));
|
|
||||||
APIDiff.getComparison(
|
ComparisonRecord record = APIDiff.getComparison(
|
||||||
cliArgs.getPreviousVersion(),
|
cliArgs.getPreviousVersion(),
|
||||||
cliArgs.getCurrentVersion(),
|
cliArgs.getCurrentVersion(),
|
||||||
cliArgs.getPreviousVersPath().toPath().resolve(commonJarFileName).toFile(),
|
cliArgs.getPreviousVersPath().toPath().resolve(commonJarFileName).toFile(),
|
||||||
cliArgs.getCurrentVersPath().toPath().resolve(commonJarFileName).toFile());
|
cliArgs.getCurrentVersPath().toPath().resolve(commonJarFileName).toFile());
|
||||||
|
|
||||||
|
ModuleVersionNumbers projectedVersionNums = ModuleUpdates.getModuleVersionUpdate(prevVersionNums, record.getChangeType());
|
||||||
|
|
||||||
|
outputDiff(commonJarFileName, record, prevVersionNums, projectedVersionNums);
|
||||||
|
|
||||||
|
newVersionNumMapping.put(commonJarFileName, projectedVersionNums);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
|
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cliArgs.isMakeUpdate()) {
|
||||||
|
ModuleUpdates.setVersions(cliArgs.getSrcPath(), newVersionNumMapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// for (String commonJarFileName : getCommonJars(cliArgs.getPreviousVersPath(), cliArgs.getCurrentVersPath())) {
|
|
||||||
//// getComparison(
|
|
||||||
//// cliArgs.getPreviousVersion(),
|
|
||||||
//// cliArgs.getCurrentVersion(),
|
|
||||||
//// cliArgs.getPreviousVersPath().toPath().resolve(commonJarFileName).toFile(),
|
|
||||||
//// cliArgs.getCurrentVersPath().toPath().resolve(commonJarFileName).toFile());
|
|
||||||
// try {
|
|
||||||
// Set<String> pubPackages = getPublicPackages(cliArgs.getPreviousVersPath().toPath().resolve(commonJarFileName).toFile());
|
|
||||||
// System.out.println(pubPackages);
|
|
||||||
// } catch (IOException ex) {
|
|
||||||
// Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
|
|
||||||
// } catch (IllegalStateException ex) {
|
|
||||||
// Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void outputDiff(
|
||||||
|
String commonJarFileName,
|
||||||
|
ComparisonRecord record,
|
||||||
private static void mainRun() {
|
ModuleVersionNumbers prevVersionNums,
|
||||||
|
ModuleVersionNumbers projectedVersionNums
|
||||||
// get public API diff's, for each jar
|
) {
|
||||||
// limit to public packages
|
LOGGER.log(Level.INFO, MessageFormat.format("\n"
|
||||||
// one of the following:
|
+ "====================================\n"
|
||||||
// generate text output of difference
|
+ "DIFF FOR: {0}\n"
|
||||||
// update version numbers in manifest file/references accordingly
|
+ "Public API Change Type: {1}\n"
|
||||||
|
+ "Previous Version Numbers:\n"
|
||||||
|
+ " - release: {2}\n"
|
||||||
|
+ " - specification: {3}\n"
|
||||||
|
+ " - implementation: {4}\n"
|
||||||
|
+ "Current Version Numbers:\n"
|
||||||
|
+ " - release: {5}\n"
|
||||||
|
+ " - specification: {6}\n"
|
||||||
|
+ " - implementation: {7}\n"
|
||||||
|
+ "====================================\n"
|
||||||
|
+ "Public API packages only in previous: {8}\n"
|
||||||
|
+ "Public API packages only in current: {9}\n"
|
||||||
|
+ "{10}\n\n",
|
||||||
|
commonJarFileName,
|
||||||
|
record.getChangeType(),
|
||||||
|
prevVersionNums.getRelease().getFullReleaseStr(),
|
||||||
|
prevVersionNums.getSpec().getSemVerStr(),
|
||||||
|
prevVersionNums.getImplementation(),
|
||||||
|
projectedVersionNums.getRelease().getFullReleaseStr(),
|
||||||
|
projectedVersionNums.getSpec().getSemVerStr(),
|
||||||
|
projectedVersionNums.getImplementation(),
|
||||||
|
record.getOnlyPrevApiPackages(),
|
||||||
|
record.getOnlyCurrApiPackages(),
|
||||||
|
record.getHumanReadableApiChange()
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -155,7 +155,47 @@ public class ModuleUpdates {
|
|||||||
return new ModuleVersionNumbers(jarFile.getName(), specSemVer, implementation, release);
|
return new ModuleVersionNumbers(jarFile.getName(), specSemVer, implementation, release);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void updateVersions() {
|
static ModuleVersionNumbers getModuleVersionUpdate(ModuleVersionNumbers prev, PublicApiChangeType apiChangeType) {
|
||||||
|
switch (apiChangeType) {
|
||||||
|
case NONE:
|
||||||
|
return new ModuleVersionNumbers(
|
||||||
|
prev.getModuleName(),
|
||||||
|
prev.getSpec(),
|
||||||
|
prev.getImplementation() + 1,
|
||||||
|
prev.getRelease()
|
||||||
|
);
|
||||||
|
case COMPATIBLE_CHANGE:
|
||||||
|
return new ModuleVersionNumbers(
|
||||||
|
prev.getModuleName(),
|
||||||
|
new SemVer(
|
||||||
|
prev.getSpec().getMajor(),
|
||||||
|
prev.getSpec().getMinor() + 1,
|
||||||
|
prev.getSpec().getPatch()
|
||||||
|
),
|
||||||
|
prev.getImplementation() + 1,
|
||||||
|
new ReleaseVal(
|
||||||
|
prev.getRelease().getModuleName(),
|
||||||
|
prev.getRelease().getReleaseVersion()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
case INCOMPATIBLE_CHANGE:
|
||||||
|
return new ModuleVersionNumbers(
|
||||||
|
prev.getModuleName(),
|
||||||
|
new SemVer(
|
||||||
|
prev.getSpec().getMajor() + 1,
|
||||||
|
prev.getSpec().getMinor(),
|
||||||
|
prev.getSpec().getPatch()
|
||||||
|
),
|
||||||
|
prev.getImplementation() + 1,
|
||||||
|
new ReleaseVal(
|
||||||
|
prev.getRelease().getModuleName(),
|
||||||
|
prev.getRelease().getReleaseVersion() == null ? null : prev.getRelease().getReleaseVersion() + 1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unknown api change type: " + apiChangeType);
|
||||||
|
}
|
||||||
|
|
||||||
// [specification major/minor/patch, implementation, release]
|
// [specification major/minor/patch, implementation, release]
|
||||||
// assumed defaults???
|
// assumed defaults???
|
||||||
// NON_COMPATIBLE:
|
// NON_COMPATIBLE:
|
||||||
|
@ -4,10 +4,30 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.apiupdate;
|
package org.sleuthkit.autopsy.apiupdate;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author gregd
|
* @author gregd
|
||||||
*/
|
*/
|
||||||
public enum PublicApiChangeType {
|
public enum PublicApiChangeType implements Comparator<PublicApiChangeType> {
|
||||||
NONE, COMPATIBLE_CHANGE, INCOMPATIBLE_CHANGE;
|
NONE(0), COMPATIBLE_CHANGE(1), INCOMPATIBLE_CHANGE(2);
|
||||||
|
|
||||||
|
private int level;
|
||||||
|
|
||||||
|
PublicApiChangeType(int level) {
|
||||||
|
this.level = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLevel() {
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compare(PublicApiChangeType o1, PublicApiChangeType o2) {
|
||||||
|
o1 = ObjectUtils.defaultIfNull(o1, PublicApiChangeType.NONE);
|
||||||
|
o2 = ObjectUtils.defaultIfNull(o2, PublicApiChangeType.NONE);
|
||||||
|
return Integer.compare(o1.getLevel(), o2.getLevel());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user