Package logisticspipes.asm.wrapper

Source Code of logisticspipes.asm.wrapper.LogisticsWrapperHandler

package logisticspipes.asm.wrapper;

import static org.objectweb.asm.Opcodes.ACC_FINAL;
import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
import static org.objectweb.asm.Opcodes.ACC_SUPER;
import static org.objectweb.asm.Opcodes.ALOAD;
import static org.objectweb.asm.Opcodes.ARETURN;
import static org.objectweb.asm.Opcodes.ASTORE;
import static org.objectweb.asm.Opcodes.CHECKCAST;
import static org.objectweb.asm.Opcodes.DLOAD;
import static org.objectweb.asm.Opcodes.DRETURN;
import static org.objectweb.asm.Opcodes.FLOAD;
import static org.objectweb.asm.Opcodes.FRETURN;
import static org.objectweb.asm.Opcodes.GETFIELD;
import static org.objectweb.asm.Opcodes.GOTO;
import static org.objectweb.asm.Opcodes.IFEQ;
import static org.objectweb.asm.Opcodes.ILOAD;
import static org.objectweb.asm.Opcodes.INVOKEINTERFACE;
import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
import static org.objectweb.asm.Opcodes.INVOKESTATIC;
import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
import static org.objectweb.asm.Opcodes.IRETURN;
import static org.objectweb.asm.Opcodes.LLOAD;
import static org.objectweb.asm.Opcodes.LRETURN;
import static org.objectweb.asm.Opcodes.PUTFIELD;
import static org.objectweb.asm.Opcodes.RETURN;
import static org.objectweb.asm.Opcodes.V1_6;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import logisticspipes.LPConstants;
import logisticspipes.LogisticsPipes;
import logisticspipes.asm.IgnoreDisabledProxy;
import logisticspipes.proxy.DontLoadProxy;
import logisticspipes.proxy.VersionNotSupportedException;
import logisticspipes.proxy.interfaces.ICraftingRecipeProvider;
import logisticspipes.proxy.interfaces.IGenericProgressProvider;
import logisticspipes.utils.ModStatusHelper;
import net.minecraft.launchwrapper.Launch;
import net.minecraft.launchwrapper.LogWrapper;

import org.apache.logging.log4j.Level;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

public class LogisticsWrapperHandler {
  private static final boolean DUMP = false;
 
  private static Map<String, Class<?>> lookupMap = new HashMap<String, Class<?>>();
  public static List<AbstractWrapper> wrapperController = new ArrayList<AbstractWrapper>();
 
  private static Method m_defineClass = null;
 
  private LogisticsWrapperHandler() {}
 
  public static IGenericProgressProvider getWrappedProgressProvider(String modId, String name, Class<? extends IGenericProgressProvider> providerClass) {
    IGenericProgressProvider provider = null;
    Throwable e = null;
    if(ModStatusHelper.isModLoaded(modId)) {
      try {
        provider = providerClass.newInstance();
      } catch(Exception e1) {
        if(e1 instanceof VersionNotSupportedException) {
          throw (VersionNotSupportedException) e1;
        }
        e1.printStackTrace();
        e = e1;
      } catch(NoClassDefFoundError e1) {
        e1.printStackTrace();
        e = e1;
      }
    }
    GenericProgressProviderWrapper instance = new GenericProgressProviderWrapper(provider, modId + ": " + name);
    if(provider != null) {
      LogisticsPipes.log.info("Loaded " + name + " ProgressProvider");
    } else {
      if(e != null) {
        ((AbstractWrapper)instance).setState(WrapperState.Exception);
        ((AbstractWrapper)instance).setReason(e);
        LogisticsPipes.log.info("Couldn't load " + name + " ProgressProvider");
      } else {
        LogisticsPipes.log.info("Didn't load " + name + " ProgressProvider");
        ((AbstractWrapper)instance).setState(WrapperState.ModMissing);
      }
    }
    instance.setModId(modId);
    wrapperController.add(instance);
    return instance;
  }
 
  public static ICraftingRecipeProvider getWrappedRecipeProvider(String modId, String name, Class<? extends ICraftingRecipeProvider> providerClass) {
    ICraftingRecipeProvider provider = null;
    Throwable e = null;
    if(ModStatusHelper.isModLoaded(modId)) {
      try {
        provider = providerClass.newInstance();
      } catch(Exception e1) {
        if(e1 instanceof VersionNotSupportedException) {
          throw (VersionNotSupportedException) e1;
        }
        e1.printStackTrace();
        e = e1;
      } catch(NoClassDefFoundError e1) {
        e1.printStackTrace();
        e = e1;
      }
    }
    CraftingRecipeProviderWrapper instance = new CraftingRecipeProviderWrapper(provider, name);
    if(provider != null) {
      LogisticsPipes.log.info("Loaded " + name + " RecipeProvider");
    } else {
      if(e != null) {
        ((AbstractWrapper)instance).setState(WrapperState.Exception);
        ((AbstractWrapper)instance).setReason(e);
        LogisticsPipes.log.info("Couldn't load " + name + " RecipeProvider");
      } else {
        LogisticsPipes.log.info("Didn't load " + name + " RecipeProvider");
        ((AbstractWrapper)instance).setState(WrapperState.ModMissing);
      }
    }
    instance.setModId(modId);
    wrapperController.add(instance);
    return instance;
  }
 
  @SuppressWarnings("unchecked")
  public static <T> T getWrappedProxy(String modId, Class<T> interfaze, Class<? extends T> proxyClazz, T dummyProxy, Class<?>... wrapperInterfaces) throws NoSuchFieldException, SecurityException, ClassNotFoundException, IllegalArgumentException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
    String proxyName = interfaze.getSimpleName().substring(1);
    if(!proxyName.endsWith("Proxy")) {
      throw new RuntimeException("UnuportedProxyName: " + proxyName);
    }
    proxyName = proxyName.substring(0, proxyName.length() - 5);
    String className = "logisticspipes/asm/wrapper/" + proxyName + "ProxyWrapper";
    boolean ignoreModLoaded = false;
    if(modId.startsWith("!")) {
      ignoreModLoaded = true;
      modId = modId.substring(1);
    }
    Class<?> clazz = lookupMap.get(className);
    if(clazz == null) {
      String fieldName = interfaze.getName().replace('.', '/');
      //String classFile = interfaze.getSimpleName().substring(1) + "Wrapper.java";
      ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
     
      cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, className, null, "logisticspipes/asm/wrapper/AbstractWrapper", new String[] { fieldName });
     
      cw.visitSource(".LP|ASM.dynamic", null);
     
      {
        FieldVisitor fv = cw.visitField(ACC_PRIVATE, "proxy", "L" + fieldName + ";", null, null);
        fv.visitEnd();
      }
      {
        FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL, "dummyProxy", "L" + fieldName + ";", null, null);
        fv.visitEnd();
      }
      {
        MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "(L" + fieldName + ";L" + fieldName + ";)V", null, null);
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitLineNumber(11, l0);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKESPECIAL, "logisticspipes/asm/wrapper/AbstractWrapper", "<init>", "()V");
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitLineNumber(12, l1);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitFieldInsn(PUTFIELD, className, "dummyProxy", "L" + fieldName + ";");
        Label l2 = new Label();
        mv.visitLabel(l2);
        mv.visitLineNumber(13, l2);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitFieldInsn(PUTFIELD, className, "proxy", "L" + fieldName + ";");
        Label l3 = new Label();
        mv.visitLabel(l3);
        mv.visitLineNumber(14, l3);
        mv.visitInsn(RETURN);
        Label l4 = new Label();
        mv.visitLabel(l4);
        mv.visitLocalVariable("this", "L" + className + ";", null, l0, l4, 0);
        mv.visitLocalVariable("dProxy", "L" + fieldName + ";", null, l0, l4, 1);
        mv.visitLocalVariable("iProxy", "L" + fieldName + ";", null, l0, l4, 2);
        mv.visitMaxs(2, 3);
        mv.visitEnd();
      }
      int lineAddition = 100;
      List<Class<?>> list = Arrays.asList(wrapperInterfaces);
      for(Method method: interfaze.getMethods()) {
        addProxyMethod(cw, method, fieldName, className, lineAddition, !list.contains(method.getReturnType()));
        lineAddition += 10;
      }
      addGetName(cw, className, proxyName);
      addGetTypeName(cw, className, "Proxy");
      cw.visitEnd();
     
      String lookfor = className.replace('/', '.');
     
      byte[] bytes = cw.toByteArray();
     
      if(LPConstants.DEBUG) {
        if(DUMP) {
          saveGeneratedClass(bytes, lookfor, "LP_WRAPPER_CLASSES");
        }
        ClassReader cr = new ClassReader(bytes);
        org.objectweb.asm.util.CheckClassAdapter.verify(cr, Launch.classLoader, false, new PrintWriter(System.err));
      }
     
      clazz = loadClass(bytes, lookfor);
      lookupMap.put(className, (Class<?>) clazz);
    }
   
    T proxy = null;
    Throwable e = null;
    if(ModStatusHelper.isModLoaded(modId) || ignoreModLoaded) {
      try {
        proxy = proxyClazz.newInstance();
      } catch(Exception e1) {
        if(e1 instanceof VersionNotSupportedException) {
          throw (VersionNotSupportedException) e1;
        }
        if(!(e1 instanceof DontLoadProxy)) {
          e1.printStackTrace();
          e = e1;
        }
      } catch(NoClassDefFoundError e1) {
        e1.printStackTrace();
        e = e1;
      }
    }
    T instance = (T) clazz.getConstructor(new Class<?>[]{interfaze, interfaze}).newInstance(dummyProxy, proxy);
    if(proxy != null) {
      LogisticsPipes.log.info("Loaded " + proxyName + "Proxy");
    } else {
      LogisticsPipes.log.info("Loaded " + proxyName + " DummyProxy");
      if(e != null) {
        ((AbstractWrapper)instance).setState(WrapperState.Exception);
        ((AbstractWrapper)instance).setReason(e);
      } else {
        ((AbstractWrapper)instance).setState(WrapperState.ModMissing);
      }
    }
    ((AbstractWrapper)instance).setModId(modId);
    wrapperController.add((AbstractWrapper) instance);
    return instance;
  }

  @SuppressWarnings("unchecked")
  public static <T> T getWrappedSubProxy(AbstractWrapper wrapper, Class<T> interfaze, T proxy, T dummyProxy) throws NoSuchFieldException, SecurityException, ClassNotFoundException, IllegalArgumentException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
    if(proxy == null) return null;
    String proxyName = interfaze.getSimpleName().substring(1);
    String className = "logisticspipes/asm/wrapper/" + proxyName + "ProxyWrapper";
   
    Class<?> clazz = lookupMap.get(className);
    if(clazz == null) {
      String fieldName = interfaze.getName().replace('.', '/');
      //String classFile = interfaze.getSimpleName().substring(1) + "Wrapper.java";
      ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
     
      cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, className, null, "logisticspipes/asm/wrapper/AbstractSubWrapper", new String[] { fieldName });
     
      cw.visitSource(".LP|ASM.dynamic", null);
     
      {
        FieldVisitor fv = cw.visitField(ACC_PRIVATE, "proxy", "L" + fieldName + ";", null, null);
        fv.visitEnd();
      }
      {
        FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL, "dummyProxy", "L" + fieldName + ";", null, null);
        fv.visitEnd();
      }
      {
        MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "(Llogisticspipes/asm/wrapper/AbstractWrapper;L" + fieldName + ";L" + fieldName + ";)V", null, null);
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitLineNumber(11, l0);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitMethodInsn(INVOKESPECIAL, "logisticspipes/asm/wrapper/AbstractSubWrapper", "<init>", "(Llogisticspipes/asm/wrapper/AbstractWrapper;)V");
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitLineNumber(12, l1);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitFieldInsn(PUTFIELD, className, "dummyProxy", "L" + fieldName + ";");
        Label l2 = new Label();
        mv.visitLabel(l2);
        mv.visitLineNumber(13, l2);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 3);
        mv.visitFieldInsn(PUTFIELD, className, "proxy", "L" + fieldName + ";");
        Label l3 = new Label();
        mv.visitLabel(l3);
        mv.visitLineNumber(14, l3);
        mv.visitInsn(RETURN);
        Label l4 = new Label();
        mv.visitLabel(l4);
        mv.visitLocalVariable("this", "L" + className + ";", null, l0, l4, 0);
        mv.visitLocalVariable("wrapper", "Llogisticspipes/asm/wrapper/AbstractWrapper;", null, l0, l4, 1);
        mv.visitLocalVariable("dProxy", "L" + fieldName + ";", null, l0, l4, 2);
        mv.visitLocalVariable("iProxy", "L" + fieldName + ";", null, l0, l4, 3);
        mv.visitMaxs(2, 3);
        mv.visitEnd();
      }
      int lineAddition = 100;
      for(Method method: interfaze.getMethods()) {
        addProxyMethod(cw, method, fieldName, className, lineAddition, true);
        lineAddition += 10;
      }
      cw.visitEnd();
     
      String lookfor = className.replace('/', '.');
     
      byte[] bytes = cw.toByteArray();
     
      if(LPConstants.DEBUG) {
        if(DUMP) {
          saveGeneratedClass(bytes, lookfor, "LP_WRAPPER_CLASSES");
        }
        ClassReader cr = new ClassReader(bytes);
        org.objectweb.asm.util.CheckClassAdapter.verify(cr, Launch.classLoader, false, new PrintWriter(System.err));
      }
     
      clazz = loadClass(bytes, lookfor);
      lookupMap.put(className, (Class<?>) clazz);
    }
   
    T instance = (T) clazz.getConstructor(new Class<?>[]{AbstractWrapper.class, interfaze, interfaze}).newInstance(wrapper, dummyProxy, proxy);
    return instance;
  }
 
  private static Class<?> loadClass(byte[] data, String lookfor) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    if(m_defineClass == null) {
      m_defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
      m_defineClass.setAccessible(true);
    }
    return (Class<?>) m_defineClass.invoke(Launch.classLoader, data, 0, data.length);
  }
 
  private static void addGetTypeName(ClassWriter cw, String className, String type) {
    MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "getTypeName", "()Ljava/lang/String;", null, null);
    mv.visitCode();
    Label l0 = new Label();
    mv.visitLabel(l0);
    mv.visitLineNumber(31, l0);
    mv.visitLdcInsn(type);
    mv.visitInsn(ARETURN);
    Label l1 = new Label();
    mv.visitLabel(l1);
    mv.visitLocalVariable("this", "L" + className + ";", null, l0, l1, 0);
    mv.visitMaxs(1, 1);
    mv.visitEnd();
  }

  private static void addGetName(ClassWriter cw, String className, String proxyName) {
    MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "getName", "()Ljava/lang/String;", null, null);
    mv.visitCode();
    Label l0 = new Label();
    mv.visitLabel(l0);
    mv.visitLineNumber(41, l0);
    mv.visitLdcInsn(proxyName);
    mv.visitInsn(ARETURN);
    Label l1 = new Label();
    mv.visitLabel(l1);
    mv.visitLocalVariable("this", "L" + className + ";", null, l0, l1, 0);
    mv.visitMaxs(1, 1);
    mv.visitEnd();
  }

  private static void addProxyMethod(ClassWriter cw, Method method, String fieldName, String className, int lineAddition, boolean normalResult) {
    Class<?> retclazz = method.getReturnType();
    int eIndex = 1;
    StringBuilder desc = new StringBuilder("(");
    for(Class<?> clazz:method.getParameterTypes()) {
      desc.append(getClassSignature(clazz));
      if(clazz == long.class || clazz == double.class) {
        eIndex += 2;
      } else {
        eIndex += 1;
      }
    }
    eIndex++;
    desc.append(")");
    String resultClassL = null;
    String resultClass = null;
    int returnType = 0;
    if(retclazz == null || retclazz == void.class) {
      desc.append("V");
      returnType = RETURN;
    } else if(retclazz.isPrimitive()) {
      desc.append(getPrimitiveMapping(retclazz));
      returnType = getPrimitiveReturnMapping(retclazz);
    } else if(retclazz.isArray()) {
      if(retclazz.getComponentType().isPrimitive()) {
        resultClassL = retclazz.getName().replace('.', '/');
        resultClass = retclazz.getName().replace('.', '/');
      } else {
        resultClassL = "L" + retclazz.getName().replace('.', '/') + ";";
        resultClass = retclazz.getName().replace('.', '/');
      }
      desc.append(resultClassL);
      returnType = ARETURN;
    } else {
      resultClassL = "L" + retclazz.getName().replace('.', '/') + ";";
      resultClass = retclazz.getName().replace('.', '/');
      desc.append(resultClassL);
      returnType = ARETURN;
    }
    MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, method.getName(), desc.toString(), null, null);
    mv.visitCode();
    Label l0 = new Label();
    Label l1 = new Label();
    Label l2 = new Label();
    mv.visitTryCatchBlock(l0, l1, l2, "java/lang/Exception");
    Label l3 = new Label();
    mv.visitTryCatchBlock(l0, l1, l3, "java/lang/NoClassDefFoundError");
    Label l4 = new Label();
    mv.visitLabel(l4);
    mv.visitLineNumber(lineAddition + 1, l4);
    mv.visitVarInsn(ALOAD, 0);
    if(method.isAnnotationPresent(IgnoreDisabledProxy.class) || !normalResult) {
      mv.visitMethodInsn(INVOKEVIRTUAL, className, "canTryAnyway", "()Z");
    } else {
      mv.visitMethodInsn(INVOKEVIRTUAL, className, "isEnabled", "()Z");
    }
    Label l5 = new Label();
    mv.visitJumpInsn(IFEQ, l5);
    mv.visitLabel(l0);
    mv.visitLineNumber(lineAddition + 2, l0);
    if(normalResult) {
      mv.visitVarInsn(ALOAD, 0);
      mv.visitFieldInsn(GETFIELD, className, "proxy", "L" + fieldName + ";");
      addMethodParameterLoad(mv, method);
      mv.visitMethodInsn(INVOKEINTERFACE, fieldName, method.getName(), desc.toString());
      mv.visitLabel(l1);
      mv.visitInsn(returnType);
    } else {
      mv.visitVarInsn(ALOAD, 0);
      mv.visitLdcInsn(Type.getType(resultClassL));
      mv.visitVarInsn(ALOAD, 0);
      mv.visitFieldInsn(GETFIELD, className, "proxy", "L" + fieldName + ";");
      addMethodParameterLoad(mv, method);
      mv.visitMethodInsn(INVOKEINTERFACE, fieldName, method.getName(), desc.toString());
      mv.visitVarInsn(ALOAD, 0);
      mv.visitFieldInsn(GETFIELD, className, "dummyProxy", "L" + fieldName + ";");
      addMethodParameterLoad(mv, method);
      mv.visitMethodInsn(INVOKEINTERFACE, fieldName, method.getName(), desc.toString());
      mv.visitMethodInsn(INVOKESTATIC, "logisticspipes/asm/wrapper/LogisticsWrapperHandler", "getWrappedSubProxy", "(Llogisticspipes/asm/wrapper/AbstractWrapper;Ljava/lang/Class;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
      mv.visitTypeInsn(CHECKCAST, resultClass);
      mv.visitLabel(l1);
      mv.visitInsn(ARETURN);
    }
    mv.visitLabel(l2);
    mv.visitLineNumber(lineAddition + 3, l2);
    mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/Exception" });
    mv.visitVarInsn(ASTORE, eIndex);
    Label l6 = new Label();
    mv.visitLabel(l6);
    mv.visitLineNumber(lineAddition + 4, l6);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitVarInsn(ALOAD, eIndex);
    mv.visitMethodInsn(INVOKEVIRTUAL, className, "handleException", "(Ljava/lang/Throwable;)V");
    Label l7 = new Label();
    mv.visitLabel(l7);
    mv.visitJumpInsn(GOTO, l5);
    mv.visitLabel(l3);
    mv.visitLineNumber(lineAddition + 5, l3);
    mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/NoClassDefFoundError" });
    mv.visitVarInsn(ASTORE, eIndex);
    Label l8 = new Label();
    mv.visitLabel(l8);
    mv.visitLineNumber(lineAddition + 6, l8);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitVarInsn(ALOAD, eIndex);
    mv.visitMethodInsn(INVOKEVIRTUAL, className, "handleException", "(Ljava/lang/Throwable;)V");
    mv.visitLabel(l5);
    mv.visitLineNumber(lineAddition + 7, l5);
    mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, className, "dummyProxy", "L" + fieldName + ";");
    addMethodParameterLoad(mv, method);
    mv.visitMethodInsn(INVOKEINTERFACE, fieldName, method.getName(), desc.toString());
    mv.visitInsn(returnType);
    Label l9 = new Label();
    mv.visitLabel(l9);
    mv.visitLocalVariable("this", "L" + className + ";", null, l4, l9, 0);
    addParameterVars(mv, method, l4, l9);
    mv.visitLocalVariable("e", "Ljava/lang/Exception;", null, l6, l7, eIndex);
    mv.visitLocalVariable("e", "Ljava/lang/NoClassDefFoundError;", null, l8, l5, eIndex);
    mv.visitMaxs(0, 0);
    mv.visitEnd();
  }
 
  private static void addMethodParameterLoad(MethodVisitor mv, Method method) {
    int i=1;
    for(Class<?> clazz:method.getParameterTypes()) {
      if(clazz.isPrimitive()) {
          if(clazz == int.class || clazz == boolean.class || clazz == short.class || clazz == byte.class) {
          mv.visitVarInsn(ILOAD, i);
          i++;
        } else if(clazz == long.class) {
          mv.visitVarInsn(LLOAD, i);
          i += 2;
        } else if(clazz == float.class) {
          mv.visitVarInsn(FLOAD, i);
          i++;
        } else if(clazz == double.class) {
          mv.visitVarInsn(DLOAD, i);
          i += 2;
        } else {
          throw new UnsupportedOperationException("Unmapped clazz: " + clazz.getName());
        }
      } else {
        mv.visitVarInsn(ALOAD, i);
        i++;
      }
    }
  }
 
  private static void addParameterVars(MethodVisitor mv, Method method, Label l3, Label l8) {
    int i=1;
    for(Class<?> clazz:method.getParameterTypes()) {
      mv.visitLocalVariable("par" + i, getClassSignature(clazz), null, l3, l8, i);
      if(clazz == long.class || clazz == double.class) {
        i++;
      }
      i++;
    }
  }

  private static String getPrimitiveMapping(Class<?> clazz) {
    if(clazz == int.class) {
      return "I";
    } else if(clazz == long.class) {
      return "J";
    } else if(clazz == float.class) {
      return "F";
    } else if(clazz == double.class) {
      return "D";
    } else if(clazz == boolean.class) {
      return "Z";
    } else if(clazz == short.class) {
      return "S";
    } else if(clazz == byte.class) {
      return "B";
    } else {
      throw new UnsupportedOperationException("Unmapped clazz: " + clazz.getName());
    }
  }
 
  private static int getPrimitiveReturnMapping(Class<?> clazz) {
    if(clazz == int.class || clazz == boolean.class || clazz == short.class || clazz == byte.class) {
      return IRETURN;
    } else if(clazz == long.class) {
      return LRETURN;
    } else if(clazz == float.class) {
      return FRETURN;
    } else if(clazz == double.class) {
      return DRETURN;
    } else {
      throw new UnsupportedOperationException("Unmapped clazz: " + clazz.getName());
    }
  }
 
  private static String getClassSignature(Class<?> clazz) {
    if(clazz.isPrimitive()) {
      return getPrimitiveMapping(clazz);
    } else {
      if(clazz.isArray()) {
        return clazz.getName().replace('.', '/');
      } else {
        return "L" + clazz.getName().replace('.', '/') + ";";
      }
    }
  }
 
  private static File  tempFolder  = null;
 
  public static void saveGeneratedClass(final byte[] data, final String transformedName, final String folder) {
    if(tempFolder == null) {
      tempFolder = new File(Launch.minecraftHome, folder);
    }
   
    final File outFile = new File(tempFolder, transformedName.replace('.', File.separatorChar) + ".class");
    final File outDir = outFile.getParentFile();
   
    if(!outDir.exists()) {
      outDir.mkdirs();
    }
   
    if(outFile.exists()) {
      outFile.delete();
    }
   
    try {
      LogWrapper.fine("Saving transformed class \"%s\" to \"%s\"", transformedName, outFile.getAbsolutePath().replace('\\', '/'));
     
      final OutputStream output = new FileOutputStream(outFile);
      output.write(data);
      output.close();
    } catch(IOException ex) {
      LogWrapper.log(Level.WARN, ex, "Could not save transformed class \"%s\"", transformedName);
    }
  }
}
TOP

Related Classes of logisticspipes.asm.wrapper.LogisticsWrapperHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.