All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.googlecode.d2j.tools.jar.BaseWeaver Maven / Gradle / Ivy

package com.googlecode.d2j.tools.jar;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.objectweb.asm.Type;


public class BaseWeaver {

    protected String invocationInterfaceDesc = "Lcom/googlecode/d2j/tools/jar/MethodInvocation;";

    protected String invocationTypePrefix = "d2j/gen/MI_";

    protected static final String DEFAULT_RET_TYPE = "L888;";

    protected static final String DEFAULT_DESC = "(L;)" + DEFAULT_RET_TYPE;

    protected List callbacks = new ArrayList<>();

    protected int currentInvocationIdx = 0;

    protected int seqIndex = 1;

    protected MtdInfo key = new MtdInfo();

    protected Set ignores = new HashSet<>();

    protected Map clzDescMap = new HashMap<>();

    protected Map mtdMap = new HashMap<>();

    protected Map defMap = new HashMap<>();

    protected String buildMethodAName(String oldName) {
        return String.format("%s_A%03d", oldName, seqIndex++);
    }

    protected String buildCallbackMethodName(String oldName) {
        return String.format("%s_CB%03d", oldName, seqIndex++);
    }

    protected MtdInfo findDefinedTargetMethod(String owner, String name, String desc) {
        return findTargetMethod0(defMap, owner, name, desc);
    }

    protected MtdInfo findTargetMethod(String owner, String name, String desc) {
        return findTargetMethod0(mtdMap, owner, name, desc);
    }

    protected MtdInfo findTargetMethod0(Map map, String owner, String name, String desc) {
        MtdInfo v = map.get(buildKey(owner, name, desc));
        if (v != null) {
            return v;
        }

        // try with default ret
        key.desc = Type.getMethodDescriptor(Type.getType(DEFAULT_RET_TYPE), Type.getArgumentTypes(desc));
        v = map.get(key);
        if (v != null) {
            return v;
        }
        // try with default desc
        key.desc = DEFAULT_DESC;
        v = map.get(key);
        if (v != null) {
            return v;
        }
        if (!name.equals("*")) {
            return findTargetMethod0(map, owner, "*", desc);
        }
        return v;
    }

    protected MtdInfo buildKey(String owner, String name, String desc) {
        key.name = name;
        key.owner = owner;
        key.desc = desc;
        return key;
    }

    public BaseWeaver withConfig(Path is) throws IOException {
        return withConfig(Files.readAllLines(is, StandardCharsets.UTF_8));
    }

    public BaseWeaver withConfig(InputStream is) throws IOException {
        try (BufferedReader r = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
            List list = new ArrayList<>();
            for (String ln = r.readLine(); ln != null; ln = r.readLine()) {
                list.add(ln);
            }
            return withConfig(list);
        }
    }

    public BaseWeaver withConfig(List lines) {
        for (String ln : lines) {
            withConfig(ln);
        }
        return this;
    }

    public void withConfig(String ln) {
        if ("".equals(ln) || ln.startsWith("#")) {
            return;
        }
        switch (Character.toLowerCase(ln.charAt(0))) {
        case 'i':
            ignores.add(ln.substring(2));
            break;
        case 'c':
            int index = ln.lastIndexOf('=');
            if (index > 0) {
                String key = toInternal(ln.substring(2, index));
                String value = toInternal(ln.substring(index + 1));
                clzDescMap.put(key, value);
                ignores.add(value);
            }
            break;
        case 'r':
            index = ln.lastIndexOf('=');
            if (index > 0) {
                String key = ln.substring(2, index);
                String value = ln.substring(index + 1);
                MtdInfo mi = buildMethodInfo(key);

                index = value.indexOf('.');
                MtdInfo mtdValue = new MtdInfo();
                mtdValue.owner = value.substring(0, index);

                int index2 = value.indexOf('(', index);
                mtdValue.name = value.substring(index + 1, index2);
                mtdValue.desc = value.substring(index2);

                mtdMap.put(mi, mtdValue);

            }
            break;
        case 'd':
            index = ln.lastIndexOf('=');
            if (index > 0) {
                String key = ln.substring(2, index);
                String value = ln.substring(index + 1);
                MtdInfo mi = buildMethodInfo(key);

                index = value.indexOf('.');
                MtdInfo mtdValue = new MtdInfo();
                mtdValue.owner = value.substring(0, index);

                int index2 = value.indexOf('(', index);
                mtdValue.name = value.substring(index + 1, index2);
                mtdValue.desc = value.substring(index2);

                defMap.put(mi, mtdValue);
            }
            break;

        case 'o':
            setInvocationInterfaceDesc(ln.substring(2));
            break;
        case 'p':
            invocationTypePrefix = ln.substring(2);
            break;
        default:
            break;
        }
    }

    public void setInvocationInterfaceDesc(String invocationInterfaceDesc) {
        this.invocationInterfaceDesc = invocationInterfaceDesc;
    }

    protected static String toInternal(String key) {
        if (key.endsWith(";")) {
            key = key.substring(1, key.length() - 1);
        }
        return key;
    }

    protected MtdInfo buildMethodInfo(String value) {
        int index = value.indexOf('.');
        MtdInfo mtdValue = new MtdInfo();
        mtdValue.owner = value.substring(0, index);
        int index2 = value.indexOf('(', index);
        if (index2 >= 0) {
            mtdValue.name = value.substring(index + 1, index2);
            int index3 = value.indexOf(')');
            if (index3 == value.length() - 1) {
                mtdValue.desc = value.substring(index2) + DEFAULT_RET_TYPE;
            } else {
                mtdValue.desc = value.substring(index2);
            }
        } else {
            mtdValue.name = value.substring(index + 1);
            mtdValue.desc = DEFAULT_DESC;
        }
        return mtdValue;
    }

    // internal name
    public String getCurrentInvocationName() {
        return String.format("%s_%03d", invocationTypePrefix, currentInvocationIdx);
    }

    protected void nextInvocationName() {
        currentInvocationIdx++;
        callbacks.clear();
    }

    public static class Callback {

        int idx;

        Object callback;

        Object target;

        boolean isSpecial;

        boolean isStatic;

    }

    public static class MtdInfo {

        public String desc;

        public String name;

        public String owner;

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }

            MtdInfo mtdInfo = (MtdInfo) o;

            if (!desc.equals(mtdInfo.desc)) {
                return false;
            }
            if (!name.equals(mtdInfo.name)) {
                return false;
            }
            return owner.equals(mtdInfo.owner);
        }

        @Override
        public int hashCode() {
            int result = desc.hashCode();
            result = 31 * result + name.hashCode();
            result = 31 * result + owner.hashCode();
            return result;
        }

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy