Skip to content

Commit

Permalink
Hard fail if a required mixin target was already transformed, bump 0.5.9
Browse files Browse the repository at this point in the history
  • Loading branch information
Mumfrey committed Jun 15, 2016
1 parent 19ca129 commit a000477
Show file tree
Hide file tree
Showing 6 changed files with 271 additions and 31 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ packaging=jar
description=Mixin
url=https://www.spongepowered.org
organization=SpongePowered
buildVersion=0.5.8
buildVersion=0.5.9
buildType=SNAPSHOT
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,7 @@ public abstract class MixinBootstrap {
/**
* Subsystem version
*/
public static final String VERSION = "0.5.8";

/**
* Blackboard key where the subsystem version will be stored to indicate
* successful bootstrap
*/
// public static final String INIT_KEY = Blackboard.Keys.INIT;
public static final String VERSION = "0.5.9";

// Consts
private static final String LAUNCH_PACKAGE = "org.spongepowered.asm.launch.";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
package org.spongepowered.asm.mixin.transformer;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
Expand Down Expand Up @@ -58,14 +57,15 @@
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
import org.spongepowered.asm.mixin.transformer.throwables.InvalidMixinException;
import org.spongepowered.asm.mixin.transformer.throwables.MixinReloadException;
import org.spongepowered.asm.mixin.transformer.throwables.MixinTargetAlreadyLoadedException;
import org.spongepowered.asm.util.ASMHelper;
import org.spongepowered.asm.util.launchwrapper.LaunchClassLoaderUtil;

import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.collect.Lists;

import net.minecraft.launchwrapper.Launch;
import net.minecraft.launchwrapper.LaunchClassLoader;

/**
* Runtime information bundle about a mixin
Expand Down Expand Up @@ -531,14 +531,17 @@ MixinPreProcessorStandard createPreProcessor(ClassNode classNode) {
}
}

/**
* Class loader utility
*/
private static final LaunchClassLoaderUtil classLoaderUtil = LaunchClassLoaderUtil.forClassLoader(Launch.classLoader);

/**
* Global order of mixin infos, used to determine ordering between mixins
* with equivalent priority
*/
static int mixinOrder = 0;

static final Set<String> invalidClasses = MixinInfo.$getInvalidClassesSet();

/**
* Logger
*/
Expand Down Expand Up @@ -637,6 +640,8 @@ MixinPreProcessorStandard createPreProcessor(ClassNode classNode) {
this.pendingState = new State(mixinBytes);
this.info = this.pendingState.getClassInfo();
this.type = this.initType();
} catch (InvalidMixinException ex) {
throw ex;
} catch (Exception ex) {
throw new InvalidMixinException(this, ex);
}
Expand All @@ -646,6 +651,8 @@ MixinPreProcessorStandard createPreProcessor(ClassNode classNode) {
this.priority = this.readPriority(this.pendingState.getClassNode());
this.targetClasses = this.readTargetClasses(this.pendingState.getClassNode(), suppressPlugin);
this.targetClassNames = Collections.unmodifiableList(Lists.transform(this.targetClasses, Functions.toStringFunction()));
} catch (InvalidMixinException ex) {
throw ex;
} catch (Exception ex) {
throw new InvalidMixinException(this, ex);
}
Expand Down Expand Up @@ -725,8 +732,16 @@ public String apply(String input) {
* Reads a target list into the outTargets list
*/
private void readTargets(Collection<ClassInfo> outTargets, Collection<String> inTargets, boolean suppressPlugin, boolean checkPublic) {
for (String targetName : inTargets) {
targetName = targetName.replace('/', '.');
for (String targetRef : inTargets) {
String targetName = targetRef.replace('/', '.');
if (MixinInfo.classLoaderUtil.isClassLoaded(targetName)) {
String message = String.format("Critical problem: %s target %s was already transformed.", this, targetName);
if (this.parent.isRequired()) {
throw new MixinTargetAlreadyLoadedException(this, message);
}
this.logger.error(message);
}

if (this.plugin == null || suppressPlugin || this.plugin.shouldApplyMixin(targetName, this.className)) {
ClassInfo targetInfo = this.getTarget(targetName, checkPublic);
if (targetInfo != null && !outTargets.contains(targetInfo)) {
Expand All @@ -740,12 +755,12 @@ private void readTargets(Collection<ClassInfo> outTargets, Collection<String> in
private ClassInfo getTarget(String targetName, boolean checkPublic) throws InvalidMixinException {
ClassInfo targetInfo = ClassInfo.forName(targetName);
if (targetInfo == null) {
this.handleTargetError("@Mixin target " + targetName + " was not found " + this);
this.handleTargetError(String.format("@Mixin target %s was not found %s", targetName, this));
return null;
}
this.type.validateTarget(targetName, targetInfo);
if (checkPublic && targetInfo.isPublic()) {
this.handleTargetError("@Mixin target " + targetName + " is public in " + this + " and should be specified in value");
this.handleTargetError(String.format("@Mixin target %s is public in %s and should be specified in value", targetName, this));
}
return targetInfo;
}
Expand Down Expand Up @@ -957,9 +972,7 @@ private byte[] loadMixinClass(String mixinClassName, boolean runTransformers) th
// Inject the mixin class name into the LaunchClassLoader's invalid
// classes set so that any classes referencing the mixin directly will
// cause the game to crash
if (MixinInfo.invalidClasses != null) {
MixinInfo.invalidClasses.add(mixinClassName);
}
MixinInfo.classLoaderUtil.registerInvalidClass(mixinClassName);

return mixinBytes;
}
Expand Down Expand Up @@ -1018,17 +1031,5 @@ public void postApply(String transformedName, ClassNode targetClass) {
public String toString() {
return String.format("%s:%s", this.parent.getName(), this.name);
}

@SuppressWarnings("unchecked")
private static Set<String> $getInvalidClassesSet() {
try {
Field invalidClasses = LaunchClassLoader.class.getDeclaredField("invalidClasses");
invalidClasses.setAccessible(true);
return (Set<String>)invalidClasses.get(Launch.classLoader);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.spongepowered.asm.lib.tree.ClassNode;
import org.spongepowered.asm.mixin.MixinEnvironment;
import org.spongepowered.asm.mixin.transformer.MixinTransformer.ReEntranceState;
import org.spongepowered.asm.util.launchwrapper.LaunchClassLoaderUtil;

import net.minecraft.launchwrapper.IClassTransformer;
import net.minecraft.launchwrapper.Launch;
Expand Down Expand Up @@ -136,6 +137,10 @@ private static byte[] getClassBytes(String name, String transformedName) throws
* except the excluded transformers
*/
private static byte[] applyTransformers(String name, String transformedName, byte[] basicClass) {
if (LaunchClassLoaderUtil.forClassLoader(Launch.classLoader).isClassExcluded(name, transformedName)) {
return basicClass;
}

MixinEnvironment environment = MixinEnvironment.getCurrentEnvironment();

for (IClassTransformer transformer : environment.getTransformers()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* This file is part of Mixin, licensed under the MIT License (MIT).
*
* Copyright (c) SpongePowered <https://www.spongepowered.org>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.spongepowered.asm.mixin.transformer.throwables;

import org.spongepowered.asm.mixin.extensibility.IMixinInfo;

/**
* Exception thrown when a specified mixin target was already classloaded.
*/
public class MixinTargetAlreadyLoadedException extends InvalidMixinException {

private static final long serialVersionUID = 1L;

public MixinTargetAlreadyLoadedException(IMixinInfo mixin, String message) {
super(mixin, message);
}

public MixinTargetAlreadyLoadedException(IMixinInfo mixin, Throwable cause) {
super(mixin, cause);
}

public MixinTargetAlreadyLoadedException(IMixinInfo mixin, String message, Throwable cause) {
super(mixin, message, cause);
}

}
Loading

0 comments on commit a000477

Please sign in to comment.