mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-06 21:00:22 +00:00
updates
This commit is contained in:
parent
10d27316a6
commit
0b7e8dd8ca
@ -4,20 +4,40 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.apiupdate;
|
||||
|
||||
import com.google.common.collect.Comparators;
|
||||
import japicmp.cmp.JApiCmpArchive;
|
||||
import japicmp.cmp.JarArchiveComparator;
|
||||
import japicmp.cmp.JarArchiveComparatorOptions;
|
||||
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.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.FileFilter;
|
||||
import java.io.IOException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Collectors;
|
||||
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();
|
||||
//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);
|
||||
|
||||
JarArchiveComparator jarArchiveComparator = new JarArchiveComparator(comparatorOptions);
|
||||
List<JApiClass> jApiClasses = jarArchiveComparator.compare(
|
||||
new JApiCmpArchive(prevJar, prevVersion),
|
||||
new JApiCmpArchive(curJar, curVersion)
|
||||
);
|
||||
|
||||
Set<String> prevPublicApiPackages = getPublicPackages(prevJar);
|
||||
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());
|
||||
|
||||
PublicApiChangeType changeType = getChangeType(jApiClasses);
|
||||
|
||||
Options options = Options.newDefault();
|
||||
options.setOutputOnlyModifications(true);
|
||||
|
||||
System.out.println("Comparing " + prevJar.getName());
|
||||
ChangeOutputGenerator stdoutOutputGenerator = new ChangeOutputGenerator(options, jApiClasses);
|
||||
String output = stdoutOutputGenerator.generate();
|
||||
System.out.println(output);
|
||||
StdoutOutputGenerator stdoutOutputGenerator = new StdoutOutputGenerator(options, jApiClasses);
|
||||
String humanReadableApiChange = stdoutOutputGenerator.generate();
|
||||
return new ComparisonRecord(prevVersion, curVersion, prevJar, curJar, humanReadableApiChange, changeType, onlyPrevApiPackages, onlyCurApiPackages, commonApiPackages);
|
||||
}
|
||||
|
||||
private static void generateOutput(Options options, List<JApiClass> jApiClasses, JarArchiveComparator jarArchiveComparator) {
|
||||
// for (JApiClass cls: jApiClasses) {
|
||||
// cls.is
|
||||
// }
|
||||
//
|
||||
private static void updateToMax(AtomicReference<PublicApiChangeType> apiChangeRef, JApiHasChangeStatus tp) {
|
||||
PublicApiChangeType apiChangeType;
|
||||
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;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@ -37,7 +38,7 @@ public class CLIProcessor {
|
||||
.hasArg(true)
|
||||
.longOpt("curr-path")
|
||||
.option("c")
|
||||
.required(true)
|
||||
.required(false)
|
||||
.build();
|
||||
|
||||
static Option PREV_VERS_OPT = Option.builder()
|
||||
@ -46,7 +47,7 @@ public class CLIProcessor {
|
||||
.hasArg(true)
|
||||
.longOpt("prev-version")
|
||||
.option("pv")
|
||||
.required(true)
|
||||
.required(false)
|
||||
.build();
|
||||
|
||||
static Option CUR_VERS_OPT = Option.builder()
|
||||
@ -55,7 +56,7 @@ public class CLIProcessor {
|
||||
.hasArg(true)
|
||||
.longOpt("curr-version")
|
||||
.option("cv")
|
||||
.required(true)
|
||||
.required(false)
|
||||
.build();
|
||||
|
||||
static Option SRC_LOC_OPT = Option.builder()
|
||||
@ -67,15 +68,27 @@ public class CLIProcessor {
|
||||
.required(true)
|
||||
.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(
|
||||
PREV_VERS_PATH_OPT,
|
||||
CUR_VERS_PATH_OPT,
|
||||
PREV_VERS_OPT,
|
||||
CUR_VERS_OPT,
|
||||
SRC_LOC_OPT
|
||||
SRC_LOC_OPT,
|
||||
UPDATE_OPT
|
||||
);
|
||||
|
||||
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) {
|
||||
Options toRet = new Options();
|
||||
@ -112,15 +125,19 @@ public class CLIProcessor {
|
||||
CommandLine helpCmd = parser.parse(HELP_OPTIONS, args, true);
|
||||
boolean isHelp = helpCmd.hasOption(HELP_OPT);
|
||||
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);
|
||||
String curVers = cmd.getOptionValue(CUR_VERS_OPT);
|
||||
String prevVers = cmd.getOptionValue(PREV_VERS_OPT);
|
||||
String curVersPath = cmd.getOptionValue(CUR_VERS_PATH_OPT);
|
||||
String curVers = cmd.hasOption(CUR_VERS_OPT) ? cmd.getOptionValue(CUR_VERS_OPT) : DEFAULT_CURR_VERSION;
|
||||
String prevVers = cmd.hasOption(PREV_VERS_OPT) ? cmd.getOptionValue(PREV_VERS_OPT) : DEFAULT_PREV_VERSION;
|
||||
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 srcPath = cmd.getOptionValue(SRC_LOC_OPT);
|
||||
boolean makeUpdate = cmd.hasOption(UPDATE_OPT);
|
||||
File curVersFile = new File(curVersPath);
|
||||
File prevVersFile = new File(prevVersPath);
|
||||
File srcPathFile = new File(srcPath);
|
||||
@ -137,7 +154,7 @@ public class CLIProcessor {
|
||||
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 {
|
||||
@ -148,14 +165,16 @@ public class CLIProcessor {
|
||||
private final File previousVersPath;
|
||||
private final boolean isHelp;
|
||||
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.previousVersion = previousVersion;
|
||||
this.currentVersPath = currentVersPath;
|
||||
this.previousVersPath = previousVersPath;
|
||||
this.srcPath = srcPath;
|
||||
this.isHelp = isHelp;
|
||||
this.makeUpdate = makeUpdate;
|
||||
}
|
||||
|
||||
public String getCurrentVersion() {
|
||||
@ -178,6 +197,10 @@ public class CLIProcessor {
|
||||
return isHelp;
|
||||
}
|
||||
|
||||
public boolean isMakeUpdate() {
|
||||
return makeUpdate;
|
||||
}
|
||||
|
||||
public File getSrcPath() {
|
||||
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;
|
||||
|
||||
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.Logger;
|
||||
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.ModuleUpdates.ModuleVersionNumbers;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -15,6 +20,8 @@ import org.sleuthkit.autopsy.apiupdate.CLIProcessor.CLIArgs;
|
||||
*/
|
||||
public class Main {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(Main.class.getName());
|
||||
|
||||
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(" ");
|
||||
CLIArgs cliArgs;
|
||||
@ -29,67 +36,69 @@ public class Main {
|
||||
System.exit(-1);
|
||||
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())) {
|
||||
try {
|
||||
// ModuleVersionNumbers m = 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(
|
||||
cliArgs.getPreviousVersion(),
|
||||
cliArgs.getCurrentVersion(),
|
||||
ModuleVersionNumbers prevVersionNums = ModuleUpdates.getVersionsFromJar(cliArgs.getPreviousVersPath().toPath().resolve(commonJarFileName).toFile());
|
||||
|
||||
ComparisonRecord record = APIDiff.getComparison(
|
||||
cliArgs.getPreviousVersion(),
|
||||
cliArgs.getCurrentVersion(),
|
||||
cliArgs.getPreviousVersPath().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) {
|
||||
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 mainRun() {
|
||||
|
||||
// get public API diff's, for each jar
|
||||
// limit to public packages
|
||||
// one of the following:
|
||||
// generate text output of difference
|
||||
// update version numbers in manifest file/references accordingly
|
||||
private static void outputDiff(
|
||||
String commonJarFileName,
|
||||
ComparisonRecord record,
|
||||
ModuleVersionNumbers prevVersionNums,
|
||||
ModuleVersionNumbers projectedVersionNums
|
||||
) {
|
||||
LOGGER.log(Level.INFO, MessageFormat.format("\n"
|
||||
+ "====================================\n"
|
||||
+ "DIFF FOR: {0}\n"
|
||||
+ "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);
|
||||
}
|
||||
|
||||
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]
|
||||
// assumed defaults???
|
||||
// NON_COMPATIBLE:
|
||||
|
@ -4,10 +4,30 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.apiupdate;
|
||||
|
||||
import java.util.Comparator;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author gregd
|
||||
*/
|
||||
public enum PublicApiChangeType {
|
||||
NONE, COMPATIBLE_CHANGE, INCOMPATIBLE_CHANGE;
|
||||
public enum PublicApiChangeType implements Comparator<PublicApiChangeType> {
|
||||
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