diff --git a/build.gradle b/build.gradle index 9e5914a..a592342 100644 --- a/build.gradle +++ b/build.gradle @@ -80,7 +80,7 @@ jar { } } -tasks.withType(JavaCompile) { +tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' options.compilerArgs << '-Xlint:unchecked' } diff --git a/settings.gradle b/settings.gradle index 65e9965..f031072 100644 --- a/settings.gradle +++ b/settings.gradle @@ -6,13 +6,13 @@ pluginManagement { } plugins { - id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0' + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0' } dependencyResolutionManagement { versionCatalogs { libs { - version('asm', '9.6') + version('asm', '9.7.1') library('asm', 'org.ow2.asm', 'asm' ).versionRef('asm') library('asm-tree', 'org.ow2.asm', 'asm-tree' ).versionRef('asm') library('asm-commons', 'org.ow2.asm', 'asm-commons').versionRef('asm') diff --git a/src/main/java/cpw/mods/modlauncher/ArgumentHandler.java b/src/main/java/cpw/mods/modlauncher/ArgumentHandler.java index 2a5789e..ca23431 100644 --- a/src/main/java/cpw/mods/modlauncher/ArgumentHandler.java +++ b/src/main/java/cpw/mods/modlauncher/ArgumentHandler.java @@ -55,7 +55,7 @@ void processArguments(Environment env, Consumer parserConsumer, Bi env.computePropertyIfAbsent(IEnvironment.Keys.ASSETSDIR.get(), f -> this.optionSet.valueOf(assetsDirOption)); env.computePropertyIfAbsent(IEnvironment.Keys.LAUNCHTARGET.get(), f -> this.optionSet.valueOf(launchTarget)); env.computePropertyIfAbsent(IEnvironment.Keys.UUID.get(), f -> this.optionSet.valueOf(uuidOption)); - resultConsumer.accept(this.optionSet, this::optionResults); + resultConsumer.accept(this.optionSet, ArgumentHandler::optionResults); } Path[] getSpecialJars() { @@ -66,7 +66,7 @@ String getLaunchTarget() { return this.optionSet.valueOf(launchTarget); } - private ITransformationService.OptionResult optionResults(String serviceName, OptionSet set) { + private static ITransformationService.OptionResult optionResults(String serviceName, OptionSet set) { return new ITransformationService.OptionResult() { @Override public V value(OptionSpec option) { @@ -95,11 +95,11 @@ public String[] buildArgumentList() { addOptionToString(assetsDirOption, optionSet, args); addOptionToString(uuidOption, optionSet, args); List nonOptionList = this.optionSet.nonOptionArguments(); - nonOptionList.stream().map(Object::toString).forEach(args::add); + args.addAll(nonOptionList.stream().map(Object::toString).toList()); return args.toArray(new String[0]); } - private void addOptionToString(OptionSpec option, OptionSet optionSet, List appendTo) { + private static void addOptionToString(OptionSpec option, OptionSet optionSet, List appendTo) { if (optionSet.has(option)) { appendTo.add("--"+option.options().get(0)); appendTo.add(option.value(optionSet).toString()); diff --git a/src/main/java/cpw/mods/modlauncher/ClassTransformer.java b/src/main/java/cpw/mods/modlauncher/ClassTransformer.java index cc89601..977e02d 100644 --- a/src/main/java/cpw/mods/modlauncher/ClassTransformer.java +++ b/src/main/java/cpw/mods/modlauncher/ClassTransformer.java @@ -27,7 +27,7 @@ public class ClassTransformer { private static final byte[] EMPTY = new byte[0]; private static final Logger LOGGER = LogManager.getLogger(); - private final Marker CLASSDUMP = MarkerManager.getMarker("CLASSDUMP"); + private static final Marker CLASSDUMP = MarkerManager.getMarker("CLASSDUMP"); private final TransformStore transformers; private final LaunchPluginHandler pluginHandler; private final TransformingClassLoader transformingClassLoader; @@ -125,7 +125,7 @@ byte[] transform(byte[] inputClass, String className, final String reason) { } private static Path tempDir; - private void dumpClass(final byte[] clazz, String className) { + private static void dumpClass(final byte[] clazz, String className) { if (tempDir == null) { synchronized (ClassTransformer.class) { if (tempDir == null) { @@ -150,24 +150,27 @@ private void dumpClass(final byte[] clazz, String className) { private T performVote(List> transformers, T node, VotingContext context) { context.setNode(node); do { - final Stream> voteResultStream = transformers.stream().map(t -> gatherVote(t, context)); - final Map>> results = voteResultStream.collect(Collectors.groupingBy(TransformerVote::getResult)); + EnumMap>> results = gatherVotes(transformers, context); + // Someone rejected the current state. We're done here, and cannot proceed. - if (results.containsKey(TransformerVoteResult.REJECT)) { + if (results.containsKey(TransformerVoteResult.REJECT)) throw new VoteRejectedException(results.get(TransformerVoteResult.REJECT), node.getClass()); - } + // Remove all the "NO" voters - they don't wish to participate in further voting rounds - if (results.containsKey(TransformerVoteResult.NO)) { - transformers.removeAll(results.get(TransformerVoteResult.NO).stream().map(TransformerVote::getTransformer).collect(Collectors.toList())); - } + var noVotes = results.get(TransformerVoteResult.NO); + if (noVotes != null) + transformers.removeAll(noVotes.stream().map(TransformerVote::transformer).toList()); + // If there's at least one YES voter, let's apply the first one we find, remove them, and continue. - if (results.containsKey(TransformerVoteResult.YES)) { - final ITransformer transformer = results.get(TransformerVoteResult.YES).get(0).getTransformer(); + var yesVotes = results.get(TransformerVoteResult.YES); + if (yesVotes != null) { + final ITransformer transformer = yesVotes.get(0).transformer(); node = transformer.transform(node, context); - auditTrail.addTransformerAuditTrail(context.getClassName(), ((TransformerHolder)transformer).owner(), transformer); + auditTrail.addTransformerAuditTrail(context.getClassName(), ((TransformerHolder) transformer).owner(), transformer); transformers.remove(transformer); continue; } + // If we get here and find a DEFER, it means everyone just voted to DEFER. That's an untenable state and we cannot proceed. if (results.containsKey(TransformerVoteResult.DEFER)) { throw new VoteDeadlockException(results.get(TransformerVoteResult.DEFER), node.getClass()); @@ -177,17 +180,32 @@ private T performVote(List> transformers, T node, VotingCont return node; } - private TransformerVote gatherVote(ITransformer transformer, VotingContext context) { - TransformerVoteResult vr = transformer.castVote(context); - return new TransformerVote<>(vr, transformer); + private static EnumMap>> gatherVotes(List> transformers, VotingContext context) { + var results = new EnumMap>>(TransformerVoteResult.class); + for (ITransformer transformer : transformers) { + var voteResult = transformer.castVote(context); + results.computeIfAbsent(voteResult, k -> new ArrayList<>()) + .add(new TransformerVote<>(voteResult, transformer)); + } + return results; } - private MessageDigest getSha256() { - try { - return MessageDigest.getInstance("SHA-256"); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException("HUH"); + private static MessageDigest getSha256() { + final class LazyInit { + private static final MessageDigest SHA256; + + static { + try { + SHA256 = MessageDigest.getInstance("SHA-256"); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("HUH"); + } + } + + private LazyInit() {} } + + return LazyInit.SHA256; } TransformingClassLoader getTransformingClassLoader() { diff --git a/src/main/java/cpw/mods/modlauncher/EnumerationHelper.java b/src/main/java/cpw/mods/modlauncher/EnumerationHelper.java index 441248e..d88b05d 100644 --- a/src/main/java/cpw/mods/modlauncher/EnumerationHelper.java +++ b/src/main/java/cpw/mods/modlauncher/EnumerationHelper.java @@ -36,6 +36,6 @@ public static T firstElementOrNull(final Enumeration enumeration) { } public static Function> fromOptional(final Function> additionalClassBytesLocator) { - return input -> Collections.enumeration(additionalClassBytesLocator.apply(input).map(Stream::of).orElseGet(Stream::empty).collect(Collectors.toList())); + return input -> Collections.enumeration(additionalClassBytesLocator.apply(input).stream().toList()); } } diff --git a/src/main/java/cpw/mods/modlauncher/Environment.java b/src/main/java/cpw/mods/modlauncher/Environment.java index 47e39d8..12be742 100644 --- a/src/main/java/cpw/mods/modlauncher/Environment.java +++ b/src/main/java/cpw/mods/modlauncher/Environment.java @@ -11,6 +11,7 @@ import java.util.*; import java.util.function.BiFunction; import java.util.function.Function; +import java.util.function.Supplier; /** * Environment implementation class @@ -53,4 +54,9 @@ public Optional> findName public T computePropertyIfAbsent(final TypesafeMap.Key key, final Function, ? extends T> valueFunction) { return environment.computeIfAbsent(key, valueFunction); } + + @Override + public T putPropertyIfAbsent(final TypesafeMap.Key key, final T value) { + return environment.putIfAbsent(key, value); + } } diff --git a/src/main/java/cpw/mods/modlauncher/LaunchPluginHandler.java b/src/main/java/cpw/mods/modlauncher/LaunchPluginHandler.java index d6e9f58..4a0a5e6 100644 --- a/src/main/java/cpw/mods/modlauncher/LaunchPluginHandler.java +++ b/src/main/java/cpw/mods/modlauncher/LaunchPluginHandler.java @@ -81,7 +81,9 @@ public EnumMap> computeLaunchPluginTransformer } void offerScanResultsToPlugins(List scanResults) { - plugins.values().forEach(p -> p.addResources(scanResults)); + for (ILaunchPluginService p : plugins.values()) { + p.addResources(scanResults); + } } int offerClassNodeToPlugins(Phase phase, List plugins, @Nullable ClassNode node, Type className, TransformerAuditTrail auditTrail, String reason) { diff --git a/src/main/java/cpw/mods/modlauncher/LaunchServiceHandler.java b/src/main/java/cpw/mods/modlauncher/LaunchServiceHandler.java index d70b4b1..3429d2a 100644 --- a/src/main/java/cpw/mods/modlauncher/LaunchServiceHandler.java +++ b/src/main/java/cpw/mods/modlauncher/LaunchServiceHandler.java @@ -29,7 +29,7 @@ /** * Identifies the launch target and dispatches to it */ -class LaunchServiceHandler { +final class LaunchServiceHandler { private static final Logger LOGGER = LogManager.getLogger(); private final Map handlers = new HashMap<>(); @@ -66,7 +66,7 @@ private void launch(String target, String[] arguments, ModuleLayer gameLayer, Tr try { var virtual = lookup.findVirtual(service.getClass(), "launchService", type); Callable callable = (Callable)virtual.invokeExact(arguments, gameLayer); - runner = () -> callable.call(); + runner = callable::call; } catch (Throwable t) { sneak(t); } @@ -83,7 +83,7 @@ private void launch(String target, String[] arguments, ModuleLayer gameLayer, Tr static List hideAccessToken(String[] arguments) { var output = new ArrayList(); for (int i = 0; i < arguments.length; i++) { - if (i > 0 && Objects.equals(arguments[i-1], "--accessToken")) + if (i > 0 && "--accessToken".equals(arguments[i - 1])) output.add("**********"); else output.add(arguments[i]); diff --git a/src/main/java/cpw/mods/modlauncher/Launcher.java b/src/main/java/cpw/mods/modlauncher/Launcher.java index 0b8109f..036260b 100644 --- a/src/main/java/cpw/mods/modlauncher/Launcher.java +++ b/src/main/java/cpw/mods/modlauncher/Launcher.java @@ -45,15 +45,15 @@ public class Launcher { private Launcher() { INSTANCE = this; - LOGGER.info(MODLAUNCHER,"ModLauncher {} starting: java version {} by {}; OS {} arch {} version {}", ()->IEnvironment.class.getPackage().getImplementationVersion(), () -> System.getProperty("java.version"), ()->System.getProperty("java.vendor"), ()->System.getProperty("os.name"), ()->System.getProperty("os.arch"), ()->System.getProperty("os.version")); + LOGGER.info(MODLAUNCHER,"ModLauncher {} starting: java version {} by {}; OS {} arch {} version {}", IEnvironment.class.getPackage().getImplementationVersion(), System.getProperty("java.version"), System.getProperty("java.vendor"), System.getProperty("os.name"), System.getProperty("os.arch"), System.getProperty("os.version")); this.moduleLayerHandler = new ModuleLayerHandler(); this.launchService = new LaunchServiceHandler(this.moduleLayerHandler); this.blackboard = new TypesafeMap(); this.environment = new Environment(this); - environment.computePropertyIfAbsent(IEnvironment.Keys.MLSPEC_VERSION.get(), s->IEnvironment.class.getPackage().getSpecificationVersion()); - environment.computePropertyIfAbsent(IEnvironment.Keys.MLIMPL_VERSION.get(), s->IEnvironment.class.getPackage().getImplementationVersion()); - environment.computePropertyIfAbsent(IEnvironment.Keys.MODLIST.get(), s->new ArrayList<>()); - environment.computePropertyIfAbsent(IEnvironment.Keys.SECURED_JARS_ENABLED.get(), k-> ProtectionDomainHelper.canHandleSecuredJars()); + environment.putPropertyIfAbsent(IEnvironment.Keys.MLSPEC_VERSION.get(), IEnvironment.class.getPackage().getSpecificationVersion()); + environment.putPropertyIfAbsent(IEnvironment.Keys.MLIMPL_VERSION.get(), IEnvironment.class.getPackage().getImplementationVersion()); + environment.computePropertyIfAbsent(IEnvironment.Keys.MODLIST.get(), k -> new ArrayList<>()); + environment.putPropertyIfAbsent(IEnvironment.Keys.SECURED_JARS_ENABLED.get(), ProtectionDomainHelper.canHandleSecuredJars()); this.transformStore = new TransformStore(); this.transformationServicesHandler = new TransformationServicesHandler(this.transformStore, this.moduleLayerHandler); this.argumentHandler = new ArgumentHandler(); @@ -70,7 +70,7 @@ public static void main(String... args) { JVM information: %s %s %s """, props.getProperty("java.vm.vendor"), props.getProperty("java.vm.name"), props.getProperty("java.vm.version")); } - LOGGER.info(MODLAUNCHER,"ModLauncher running: args {}", () -> LaunchServiceHandler.hideAccessToken(args)); + LOGGER.info(MODLAUNCHER,"ModLauncher running: args {}", LaunchServiceHandler.hideAccessToken(args)); LOGGER.info(MODLAUNCHER, "JVM identified as {} {} {}", props.getProperty("java.vm.vendor"), props.getProperty("java.vm.name"), props.getProperty("java.vm.version")); new Launcher().run(args); } diff --git a/src/main/java/cpw/mods/modlauncher/LogMarkers.java b/src/main/java/cpw/mods/modlauncher/LogMarkers.java index d3c4401..3dac0db 100644 --- a/src/main/java/cpw/mods/modlauncher/LogMarkers.java +++ b/src/main/java/cpw/mods/modlauncher/LogMarkers.java @@ -7,8 +7,10 @@ import org.apache.logging.log4j.*; -class LogMarkers { +final class LogMarkers { static final Marker MODLAUNCHER = MarkerManager.getMarker("MODLAUNCHER"); - static final Marker CLASSLOADING = MarkerManager.getMarker("CLASSLOADING").addParents(MODLAUNCHER); +// static final Marker CLASSLOADING = MarkerManager.getMarker("CLASSLOADING").addParents(MODLAUNCHER); static final Marker LAUNCHPLUGIN = MarkerManager.getMarker("LAUNCHPLUGIN").addParents(MODLAUNCHER); + + private LogMarkers() {} } diff --git a/src/main/java/cpw/mods/modlauncher/ModuleLayerHandler.java b/src/main/java/cpw/mods/modlauncher/ModuleLayerHandler.java index 525c845..a1ef466 100644 --- a/src/main/java/cpw/mods/modlauncher/ModuleLayerHandler.java +++ b/src/main/java/cpw/mods/modlauncher/ModuleLayerHandler.java @@ -58,7 +58,7 @@ LayerInfo build(Layer layer) { } LayerInfo build(Layer layer, ClassLoaderFactory classLoaderSupplier) { - var jars = layers.getOrDefault(layer, List.of()).stream().toArray(SecureJar[]::new); + var jars = layers.getOrDefault(layer, List.of()).toArray(SecureJar[]::new); var targets = Arrays.stream(jars).map(SecureJar::name).toList(); var parentLayers = new ArrayList(); var parentConfigs = new ArrayList(); diff --git a/src/main/java/cpw/mods/modlauncher/NameMappingServiceHandler.java b/src/main/java/cpw/mods/modlauncher/NameMappingServiceHandler.java index 6defb7b..3b33920 100644 --- a/src/main/java/cpw/mods/modlauncher/NameMappingServiceHandler.java +++ b/src/main/java/cpw/mods/modlauncher/NameMappingServiceHandler.java @@ -21,7 +21,7 @@ /** * Allow names to be transformed between naming domains. */ -class NameMappingServiceHandler { +final class NameMappingServiceHandler { private static final Logger LOGGER = LogManager.getLogger(); private final Map allKnown = new HashMap<>(); private final Map active = new HashMap<>(); diff --git a/src/main/java/cpw/mods/modlauncher/PredicateVisitor.java b/src/main/java/cpw/mods/modlauncher/PredicateVisitor.java index 7aac790..f4dcc82 100644 --- a/src/main/java/cpw/mods/modlauncher/PredicateVisitor.java +++ b/src/main/java/cpw/mods/modlauncher/PredicateVisitor.java @@ -14,23 +14,29 @@ public class PredicateVisitor extends ClassVisitor { private static final int ASM_API = Opcodes.ASM9; - private ITransformerVotingContext.MethodPredicate methodPredicate; - private ITransformerVotingContext.FieldPredicate fieldPredicate; - private ITransformerVotingContext.ClassPredicate classPredicate; + private final ITransformerVotingContext.MethodPredicate methodPredicate; + private final ITransformerVotingContext.FieldPredicate fieldPredicate; + private final ITransformerVotingContext.ClassPredicate classPredicate; private boolean result; PredicateVisitor(final ITransformerVotingContext.FieldPredicate fieldPredicate) { super(ASM_API); + this.methodPredicate = null; this.fieldPredicate = fieldPredicate; + this.classPredicate = null; } PredicateVisitor(final ITransformerVotingContext.MethodPredicate methodPredicate) { super(ASM_API); this.methodPredicate = methodPredicate; + this.fieldPredicate = null; + this.classPredicate = null; } PredicateVisitor(final ITransformerVotingContext.ClassPredicate classPredicate) { super(ASM_API); + this.methodPredicate = null; + this.fieldPredicate = null; this.classPredicate = classPredicate; } diff --git a/src/main/java/cpw/mods/modlauncher/TransformTargetLabel.java b/src/main/java/cpw/mods/modlauncher/TransformTargetLabel.java index 6403da0..051bb55 100644 --- a/src/main/java/cpw/mods/modlauncher/TransformTargetLabel.java +++ b/src/main/java/cpw/mods/modlauncher/TransformTargetLabel.java @@ -5,7 +5,6 @@ package cpw.mods.modlauncher; - import org.objectweb.asm.Type; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.FieldNode; @@ -25,20 +24,22 @@ * Detailed targetting information */ public final class TransformTargetLabel { - private final Type className; private final String elementName; private final Type elementDescriptor; private final LabelType labelType; + TransformTargetLabel(ITransformer.Target target) { - this(target.getClassName(), target.getElementName(), target.getElementDescriptor(), LabelType.valueOf(target.getTargetType().name())); + this(target.className(), target.elementName(), target.elementDescriptor(), LabelType.valueOf(target.targetType().name())); } + private TransformTargetLabel(String className, String elementName, String elementDescriptor, LabelType labelType) { this.className = Type.getObjectType(className.replace('.', '/')); this.elementName = elementName; - this.elementDescriptor = elementDescriptor.length() > 0 ? Type.getMethodType(elementDescriptor) : Type.VOID_TYPE; + this.elementDescriptor = !elementDescriptor.isEmpty() ? Type.getMethodType(elementDescriptor) : Type.VOID_TYPE; this.labelType = labelType; } + public TransformTargetLabel(String className, String fieldName) { this(className, fieldName, "", FIELD); } @@ -58,19 +59,19 @@ public TransformTargetLabel(String className, LabelType type) { throw new IllegalArgumentException("Invalid type " + type + ", must be for class!"); } - final Type getClassName() { + Type getClassName() { return this.className; } - public final String getElementName() { + public String getElementName() { return this.elementName; } - public final Type getElementDescriptor() { + public Type getElementDescriptor() { return this.elementDescriptor; } - final LabelType getLabelType() { + LabelType getLabelType() { return this.labelType; } @@ -80,14 +81,11 @@ public int hashCode() { @Override public boolean equals(Object obj) { - try { - TransformTargetLabel tl = (TransformTargetLabel) obj; - return Objects.equals(this.className, tl.className) - && Objects.equals(this.elementName, tl.elementName) - && Objects.equals(this.elementDescriptor, tl.elementDescriptor); - } catch (ClassCastException cce) { - return false; - } + if (obj == this) return true; + return obj instanceof TransformTargetLabel tl + && Objects.equals(this.className, tl.className) + && Objects.equals(this.elementName, tl.elementName) + && Objects.equals(this.elementDescriptor, tl.elementDescriptor); } @Override diff --git a/src/main/java/cpw/mods/modlauncher/TransformationServicesHandler.java b/src/main/java/cpw/mods/modlauncher/TransformationServicesHandler.java index 0bbefbb..59a986a 100644 --- a/src/main/java/cpw/mods/modlauncher/TransformationServicesHandler.java +++ b/src/main/java/cpw/mods/modlauncher/TransformationServicesHandler.java @@ -27,7 +27,7 @@ import static cpw.mods.modlauncher.LogMarkers.*; -class TransformationServicesHandler { +final class TransformationServicesHandler { private static final Logger LOGGER = LogManager.getLogger(); private Map serviceLookup; private final TransformStore transformStore; @@ -44,7 +44,7 @@ List initializeTransformationServices(ArgumentH processArguments(argumentHandler, environment); initialiseTransformationServices(environment); // force the naming to "mojang" if nothing has been populated during transformer setup - environment.computePropertyIfAbsent(IEnvironment.Keys.NAMING.get(), a-> "mojang"); + environment.putPropertyIfAbsent(IEnvironment.Keys.NAMING.get(), "mojang"); nameMappingServiceHandler.bindNamingServices(environment.getProperty(Environment.Keys.NAMING.get()).orElse("mojang")); return runScanningTransformationServices(environment); } @@ -79,13 +79,17 @@ private void offerArgumentResultsToServices(OptionSet optionSet, BiFunction s.gatherTransformers(transformStore)); + for (TransformationServiceDecorator s : serviceLookup.values()) { + s.gatherTransformers(transformStore); + } } private void initialiseTransformationServices(Environment environment) { LOGGER.debug(MODLAUNCHER,"Transformation services initializing"); - serviceLookup.values().forEach(s -> s.onInitialize(environment)); + for (TransformationServiceDecorator s : serviceLookup.values()) { + s.onInitialize(environment); + } } private List runScanningTransformationServices(Environment environment) { @@ -94,7 +98,7 @@ private List runScanningTransformationServices( return serviceLookup.values() .stream() .map(s -> s.runScan(environment)) - .mapMulti(Iterable::forEach) + .flatMap(List::stream) .toList(); } @@ -113,7 +117,9 @@ private void validateTransformationServices() { private void loadTransformationServices(Environment environment) { LOGGER.debug(MODLAUNCHER,"Transformation services loading"); - serviceLookup.values().forEach(s -> s.onLoad(environment, serviceLookup.keySet())); + for (TransformationServiceDecorator s : serviceLookup.values()) { + s.onLoad(environment, serviceLookup.keySet()); + } } void discoverServices(final ArgumentHandler.DiscoveryData discoveryData) { @@ -168,8 +174,8 @@ void discoverServices(final ArgumentHandler.DiscoveryData discoveryData) { public List triggerScanCompletion(IModuleLayerManager moduleLayerManager) { return serviceLookup.values().stream() - .map(tsd->tsd.onCompleteScan(moduleLayerManager)) - .mapMulti(Iterable::forEach) + .map(tsd -> tsd.onCompleteScan(moduleLayerManager)) + .flatMap(List::stream) .toList(); } diff --git a/src/main/java/cpw/mods/modlauncher/TransformerAuditTrail.java b/src/main/java/cpw/mods/modlauncher/TransformerAuditTrail.java index 00ee2b5..835fe47 100644 --- a/src/main/java/cpw/mods/modlauncher/TransformerAuditTrail.java +++ b/src/main/java/cpw/mods/modlauncher/TransformerAuditTrail.java @@ -16,20 +16,16 @@ import java.util.stream.Collectors; public class TransformerAuditTrail implements ITransformerAuditTrail { - private Map> audit = new ConcurrentHashMap<>(); + private final Map> audit = new ConcurrentHashMap<>(); @Override public List getActivityFor(final String className) { return Collections.unmodifiableList(getTransformerActivities(className)); } - private static class TransformerActivity implements ITransformerActivity { - private final Type type; - private final String[] context; - - private TransformerActivity(Type type, String... context) { - this.type = type; - this.context = context; + private record TransformerActivity(String[] context, Type type) implements ITransformerActivity { + public TransformerActivity(Type type, String... context) { + this(context, type); } @Override @@ -43,7 +39,7 @@ public Type getType() { } public String getActivityString() { - return this.type.getLabel() + ":"+ String.join(":",this.context); + return this.type.getLabel() + ":" + String.join(":", this.context); } } @@ -63,12 +59,13 @@ public void addTransformerAuditTrail(String clazz, ITransformationService transf getTransformerActivities(clazz).add(new TransformerActivity(ITransformerActivity.Type.TRANSFORMER, concat(transformService.name(), transformer.labels()))); } - private String[] concat(String first, String[] rest) { + private static String[] concat(String first, String[] rest) { final String[] res = new String[rest.length + 1]; res[0] = first; System.arraycopy(rest, 0, res, 1, rest.length); return res; } + private List getTransformerActivities(final String clazz) { return audit.computeIfAbsent(clazz, k->new ArrayList<>()); } diff --git a/src/main/java/cpw/mods/modlauncher/TransformerClassWriter.java b/src/main/java/cpw/mods/modlauncher/TransformerClassWriter.java index 1e3a194..67fe56c 100644 --- a/src/main/java/cpw/mods/modlauncher/TransformerClassWriter.java +++ b/src/main/java/cpw/mods/modlauncher/TransformerClassWriter.java @@ -18,7 +18,7 @@ import java.util.*; import java.util.concurrent.ConcurrentHashMap; -class TransformerClassWriter extends ClassWriter { +final class TransformerClassWriter extends ClassWriter { private static final Logger LOGGER = LogManager.getLogger(); private static final Map CLASS_PARENTS = new ConcurrentHashMap<>(); private static final Map> CLASS_HIERARCHIES = new ConcurrentHashMap<>(); @@ -71,7 +71,7 @@ private Set getSupers(final String typeName) { return CLASS_HIERARCHIES.get(typeName); } - private boolean isIntf(final String typeName) { + private static boolean isIntf(final String typeName) { //We don't need computeHierarchy as it has been called already from a different method every time this method is called return IS_INTERFACE.get(typeName); } @@ -104,7 +104,7 @@ private void computeHierarchy(final String className) { * Computes the hierarchy for a specific class using the already loaded class object * Must be kept in sync with the file counterpart {@link SuperCollectingVisitor#visit(int, int, String, String, String, String[])} */ - private void computeHierarchyFromClass(final String name, final Class clazz) { + private static void computeHierarchyFromClass(final String name, final Class clazz) { Class superClass = clazz.getSuperclass(); Set hierarchies = new HashSet<>(); if (superClass != null) { @@ -118,13 +118,13 @@ private void computeHierarchyFromClass(final String name, final Class clazz) hierarchies.add("java/lang/Object"); } IS_INTERFACE.put(name, clazz.isInterface()); - Arrays.stream(clazz.getInterfaces()).forEach(c->{ + for (Class c : clazz.getInterfaces()) { String n = c.getName().replace('.', '/'); if (!CLASS_HIERARCHIES.containsKey(n)) computeHierarchyFromClass(n, c); hierarchies.add(n); hierarchies.addAll(CLASS_HIERARCHIES.get(n)); - }); + } CLASS_HIERARCHIES.put(name, hierarchies); //Only put the set in the map once it is fully populated, to prevent another thread from using incomplete data } @@ -150,7 +150,7 @@ private void computeHierarchyFromFile(final String className) { } } - private class SuperCollectingVisitor extends ClassVisitor { + private final class SuperCollectingVisitor extends ClassVisitor { public SuperCollectingVisitor() { super(Opcodes.ASM9); @@ -168,11 +168,11 @@ public void visit(final int version, final int access, final String name, final hierarchies.add("java/lang/Object"); } IS_INTERFACE.put(name, (access & Opcodes.ACC_INTERFACE) != 0); - Arrays.stream(interfaces).forEach(n->{ + for (String n : interfaces) { computeHierarchy(n); hierarchies.add(n); hierarchies.addAll(CLASS_HIERARCHIES.get(n)); - }); + } CLASS_HIERARCHIES.put(name, hierarchies); //Only put the set in the map once it is fully populated, to prevent another thread from using incomplete data } } diff --git a/src/main/java/cpw/mods/modlauncher/TransformerVote.java b/src/main/java/cpw/mods/modlauncher/TransformerVote.java index 25d522f..e8ea9fc 100644 --- a/src/main/java/cpw/mods/modlauncher/TransformerVote.java +++ b/src/main/java/cpw/mods/modlauncher/TransformerVote.java @@ -7,20 +7,4 @@ import cpw.mods.modlauncher.api.*; -class TransformerVote { - private final ITransformer transformer; - private final TransformerVoteResult result; - - TransformerVote(TransformerVoteResult vr, ITransformer transformer) { - this.transformer = transformer; - this.result = vr; - } - - TransformerVoteResult getResult() { - return result; - } - - ITransformer getTransformer() { - return transformer; - } -} +record TransformerVote(TransformerVoteResult result, ITransformer transformer) {} diff --git a/src/main/java/cpw/mods/modlauncher/TransformingClassLoader.java b/src/main/java/cpw/mods/modlauncher/TransformingClassLoader.java index 3463f5a..90be8d9 100644 --- a/src/main/java/cpw/mods/modlauncher/TransformingClassLoader.java +++ b/src/main/java/cpw/mods/modlauncher/TransformingClassLoader.java @@ -23,7 +23,11 @@ public class TransformingClassLoader extends ModuleClassLoader { private final ClassTransformer classTransformer; private static ModuleLayer get(ModuleLayerHandler layers, Layer layer) { - return layers.getLayer(layer).orElseThrow(() -> new NullPointerException("Failed to find " + layer.name() + " layer")); + var moduleLayer = layers.getLayer(layer).orElse(null); + if (moduleLayer == null) + throw new NullPointerException("Failed to find " + layer.name() + " layer"); + + return moduleLayer; } public TransformingClassLoader(TransformStore transformStore, LaunchPluginHandler pluginHandler, ModuleLayerHandler layers) { @@ -35,7 +39,7 @@ public TransformingClassLoader(TransformStore transformStore, LaunchPluginHandle TransformStore transformStore, LaunchPluginHandler pluginHandler, Environment environment) { super(name, parent, config, parentLayers, parentLoaders, true); TransformerAuditTrail tat = new TransformerAuditTrail(); - environment.computePropertyIfAbsent(IEnvironment.Keys.AUDITTRAIL.get(), v->tat); + environment.putPropertyIfAbsent(IEnvironment.Keys.AUDITTRAIL.get(), tat); this.classTransformer = new ClassTransformer(transformStore, pluginHandler, this, tat); } diff --git a/src/main/java/cpw/mods/modlauncher/TransformingClassLoaderBuilder.java b/src/main/java/cpw/mods/modlauncher/TransformingClassLoaderBuilder.java index 3dba4c9..44cddf2 100644 --- a/src/main/java/cpw/mods/modlauncher/TransformingClassLoaderBuilder.java +++ b/src/main/java/cpw/mods/modlauncher/TransformingClassLoaderBuilder.java @@ -8,15 +8,13 @@ import cpw.mods.modlauncher.api.ITransformingClassLoaderBuilder; import java.net.URL; -import java.net.URLConnection; import java.nio.file.Path; import java.util.*; import java.util.function.Function; -import java.util.jar.Manifest; import static cpw.mods.modlauncher.api.LamdbaExceptionUtils.rethrowFunction; -class TransformingClassLoaderBuilder implements ITransformingClassLoaderBuilder { +final class TransformingClassLoaderBuilder implements ITransformingClassLoaderBuilder { private final List transformationPaths = new ArrayList<>(); private Function> resourcesLocator; diff --git a/src/main/java/cpw/mods/modlauncher/VotingContext.java b/src/main/java/cpw/mods/modlauncher/VotingContext.java index 0ab80b7..5124892 100644 --- a/src/main/java/cpw/mods/modlauncher/VotingContext.java +++ b/src/main/java/cpw/mods/modlauncher/VotingContext.java @@ -14,31 +14,18 @@ /** * The internal vote context structure. */ -class VotingContext implements ITransformerVotingContext { +record VotingContext( + String getClassName, + boolean doesClassExist, + Supplier sha256, + List getAuditActivities, + String reason, + NodeHolder node +) implements ITransformerVotingContext { private static final Object[] EMPTY = new Object[0]; - private final String className; - private final boolean classExists; - private final Supplier sha256; - private final List auditActivities; - private final String reason; - private Object node; - VotingContext(String className, boolean classExists, Supplier sha256sum, final List activities, final String reason) { - this.className = className; - this.classExists = classExists; - this.sha256 = sha256sum; - this.auditActivities = activities; - this.reason = reason; - } - - @Override - public String getClassName() { - return className; - } - - @Override - public boolean doesClassExist() { - return classExists; + VotingContext(String className, boolean classExists, Supplier sha256sum, List activities, String reason) { + this(className, classExists, sha256sum, activities, reason, new NodeHolder()); } @Override @@ -46,23 +33,18 @@ public byte[] getInitialClassSha256() { return sha256.get(); } - @Override - public List getAuditActivities() { - return auditActivities; - } - @Override public String getReason() { return reason; } void setNode(final T node) { - this.node = node; + this.node.value = node; } @Override public boolean applyFieldPredicate(FieldPredicate fieldPredicate) { - FieldNode fn = (FieldNode) this.node; + FieldNode fn = (FieldNode) this.node.value; final PredicateVisitor predicateVisitor = new PredicateVisitor(fieldPredicate); fn.accept(predicateVisitor); return predicateVisitor.getResult(); @@ -70,7 +52,7 @@ public boolean applyFieldPredicate(FieldPredicate fieldPredicate) { @Override public boolean applyMethodPredicate(MethodPredicate methodPredicate) { - MethodNode mn = (MethodNode) this.node; + MethodNode mn = (MethodNode) this.node.value; final PredicateVisitor predicateVisitor = new PredicateVisitor(methodPredicate); mn.accept(predicateVisitor); return predicateVisitor.getResult(); @@ -78,7 +60,7 @@ public boolean applyMethodPredicate(MethodPredicate methodPredicate) { @Override public boolean applyClassPredicate(ClassPredicate classPredicate) { - ClassNode cn = (ClassNode) this.node; + ClassNode cn = (ClassNode) this.node.value; final PredicateVisitor predicateVisitor = new PredicateVisitor(classPredicate); cn.accept(predicateVisitor); return predicateVisitor.getResult(); @@ -86,7 +68,7 @@ public boolean applyClassPredicate(ClassPredicate classPredicate) { @Override public boolean applyInstructionPredicate(InsnPredicate insnPredicate) { - MethodNode mn = (MethodNode) this.node; + MethodNode mn = (MethodNode) this.node.value; boolean result = false; final AbstractInsnNode[] insnNodes = mn.instructions.toArray(); for (int i = 0; i < insnNodes.length; i++) { @@ -95,15 +77,17 @@ public boolean applyInstructionPredicate(InsnPredicate insnPredicate) { return result; } - private Object[] toObjectArray(final AbstractInsnNode insnNode) { - if (insnNode instanceof MethodInsnNode) { - final MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode; + private static Object[] toObjectArray(final AbstractInsnNode insnNode) { + if (insnNode instanceof MethodInsnNode methodInsnNode) { return new Object[] {methodInsnNode.name, methodInsnNode.desc, methodInsnNode.owner, methodInsnNode.itf}; } - if (insnNode instanceof FieldInsnNode) { - final FieldInsnNode fieldInsnNode = (FieldInsnNode) insnNode; + if (insnNode instanceof FieldInsnNode fieldInsnNode) { return new Object[] {fieldInsnNode.name, fieldInsnNode.desc, fieldInsnNode.owner}; } return EMPTY; } + + private static final class NodeHolder { + private Object value; + } } diff --git a/src/main/java/cpw/mods/modlauncher/api/IEnvironment.java b/src/main/java/cpw/mods/modlauncher/api/IEnvironment.java index d3a2765..1935b9e 100644 --- a/src/main/java/cpw/mods/modlauncher/api/IEnvironment.java +++ b/src/main/java/cpw/mods/modlauncher/api/IEnvironment.java @@ -28,11 +28,35 @@ public interface IEnvironment { * Compute a new value for insertion into the environment, if not already present. * * @param key to insert - * @param valueFunction the supplier of a value + * @param valueFunction the function to compute a value * @param Type of key * @return The value of the key */ T computePropertyIfAbsent(TypesafeMap.Key key, final Function, ? extends T> valueFunction); + + /** + * Compute a new value for insertion into the environment, if not already present. + * + * @param key to insert + * @param valueSupplier the supplier of a value + * @param Type of key + * @return The value of the key + */ + default T computePropertyIfAbsent(TypesafeMap.Key key, final Supplier valueSupplier) { + return computePropertyIfAbsent(key, k -> valueSupplier.get()); + } + + /** + * Insert a value into the environment if not already present. + * @param key to insert + * @param value the value to insert + * @return The value of the key + * @param Type of key + */ + default T putPropertyIfAbsent(TypesafeMap.Key key, T value) { + return computePropertyIfAbsent(key, k -> value); + } + /** * Find the named {@link ILaunchPluginService} * diff --git a/src/main/java/cpw/mods/modlauncher/api/IModuleLayerManager.java b/src/main/java/cpw/mods/modlauncher/api/IModuleLayerManager.java index 75c91d4..007361d 100644 --- a/src/main/java/cpw/mods/modlauncher/api/IModuleLayerManager.java +++ b/src/main/java/cpw/mods/modlauncher/api/IModuleLayerManager.java @@ -19,6 +19,10 @@ enum Layer { private final List parents; + Layer(Layer parent) { + this.parents = List.of(parent); + } + Layer(Layer... parent) { this.parents = List.of(parent); } diff --git a/src/main/java/cpw/mods/modlauncher/api/ITransformer.java b/src/main/java/cpw/mods/modlauncher/api/ITransformer.java index 7444d73..355800f 100644 --- a/src/main/java/cpw/mods/modlauncher/api/ITransformer.java +++ b/src/main/java/cpw/mods/modlauncher/api/ITransformer.java @@ -58,7 +58,7 @@ public interface ITransformer { /** * Return a set of {@link Target} identifying which elements this transformer wishes to try - * and apply to. The {@link Target#getTargetType()} must match the T variable for the transformer + * and apply to. The {@link Target#targetType()} must match the T variable for the transformer * as documented in {@link TargetType}, other combinations will be rejected. * * @return The set of targets this transformer wishes to apply to @@ -98,37 +98,27 @@ enum TargetType { /** * Simple data holder indicating where the {@link ITransformer} can target. + * @param className The name of the class being targeted + * @param elementName The name of the element being targeted. This is the field name for a field, + * the method name for a method. Empty string for other types + * @param elementDescriptor The method's descriptor. Empty string for other types + * @param targetType The {@link TargetType} for this target - it should match the ITransformer + * type variable T */ @SuppressWarnings("SameParameterValue") - final class Target { - private final String className; - private final String elementName; - private final String elementDescriptor; - private final TargetType targetType; - + record Target(String className, String elementName, String elementDescriptor, TargetType targetType) { /** * Build a new target. Ensure that the targetType matches the T type for the ITransformer * supplying the target. *

* In an obfuscated environment, this will be the obfuscated "notch" naming, in a * deobfuscated environment this will be the searge naming. - * - * @param className The name of the class being targetted - * @param elementName The name of the element being targetted. This is the field name for a field, - * the method name for a method. Empty string for other types - * @param elementDescriptor The method's descriptor. Empty string for other types - * @param targetType The {@link TargetType} for this target - it should match the ITransformer - * type variable T */ - Target(String className, String elementName, String elementDescriptor, TargetType targetType) { + public Target { Objects.requireNonNull(className, "Class Name cannot be null"); Objects.requireNonNull(elementName, "Element Name cannot be null"); Objects.requireNonNull(elementDescriptor, "Element Descriptor cannot be null"); Objects.requireNonNull(targetType, "Target Type cannot be null"); - this.className = className; - this.elementName = elementName; - this.elementDescriptor = elementDescriptor; - this.targetType = targetType; } /** diff --git a/src/main/java/cpw/mods/modlauncher/api/TypesafeMap.java b/src/main/java/cpw/mods/modlauncher/api/TypesafeMap.java index c964af6..40fa341 100644 --- a/src/main/java/cpw/mods/modlauncher/api/TypesafeMap.java +++ b/src/main/java/cpw/mods/modlauncher/api/TypesafeMap.java @@ -34,11 +34,20 @@ public V computeIfAbsent(Key key, Function, ? extends V> v return computeIfAbsent(this.map, key, valueFunction); } + public V putIfAbsent(Key key, V value) { + return putIfAbsent(this.map, key, value); + } + @SuppressWarnings("unchecked") - private V computeIfAbsent(ConcurrentHashMap map, Key key, Function, ? extends V> valueFunction) { + private static V computeIfAbsent(ConcurrentHashMap map, Key key, Function, ? extends V> valueFunction) { return (V) map.computeIfAbsent((C1) key, (Function) valueFunction); } + @SuppressWarnings("unchecked") + private static V putIfAbsent(ConcurrentHashMap map, Key key, V value) { + return (V) map.putIfAbsent((C1) key, value); + } + private ConcurrentHashMap> getKeyIdentifiers() { return keys; } @@ -77,16 +86,12 @@ public final String name() { @Override public int hashCode() { - return (int) (this.uniqueId ^ (this.uniqueId >>> 32)); + return Long.hashCode(this.uniqueId); } @Override public boolean equals(Object obj) { - try { - return this.uniqueId == ((Key) obj).uniqueId; - } catch (ClassCastException cc) { - return false; - } + return obj instanceof Key key && this.uniqueId == key.uniqueId; } @Override diff --git a/src/main/java/cpw/mods/modlauncher/log/TransformingThrowablePatternConverter.java b/src/main/java/cpw/mods/modlauncher/log/TransformingThrowablePatternConverter.java index 10a0e2a..8302226 100644 --- a/src/main/java/cpw/mods/modlauncher/log/TransformingThrowablePatternConverter.java +++ b/src/main/java/cpw/mods/modlauncher/log/TransformingThrowablePatternConverter.java @@ -85,7 +85,6 @@ public void format(@SuppressWarnings("exports") final LogEvent event, final Stri for (var line : audit.get(cls)) line(buf, " ", line); } - System.currentTimeMillis(); } private void line(StringBuilder sb, String... parts) { diff --git a/src/main/java/cpw/mods/modlauncher/util/ServiceLoaderUtils.java b/src/main/java/cpw/mods/modlauncher/util/ServiceLoaderUtils.java index 1f984aa..5509a45 100644 --- a/src/main/java/cpw/mods/modlauncher/util/ServiceLoaderUtils.java +++ b/src/main/java/cpw/mods/modlauncher/util/ServiceLoaderUtils.java @@ -33,10 +33,10 @@ public static Stream streamWithErrorHandling(ServiceLoader sl, Consume public static String fileNameFor(Class clazz) { var module = clazz.getModule(); var ref = module.getLayer().configuration().findModule(module.getName()); - if (!ref.isPresent()) + if (ref.isEmpty()) return "MISSING FILE"; var location = ref.get().reference().location(); - if (!location.isPresent()) + if (location.isEmpty()) return "MISSING FILE"; var path = Path.of(location.get());