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

pro.fessional.meepo.poof.impl.java.JavaEngine Maven / Gradle / Ivy

Go to download

meepo, first, is a dota2 hero, and then a template engine that using the single/multi-comment of target file's syntax as directive in order to keep the template and the target file in the same syntax highlight, preview and IDE editing features.

The newest version!
package pro.fessional.meepo.poof.impl.java;

import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pro.fessional.meepo.Meepo;
import pro.fessional.meepo.eval.JavaEval;
import pro.fessional.meepo.poof.RnaEngine;
import pro.fessional.meepo.poof.RnaWarmed;
import pro.fessional.meepo.util.Java;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static pro.fessional.meepo.bind.Const.ENGINE$FUN;
import static pro.fessional.meepo.bind.Const.ENGINE$JAVA;
import static pro.fessional.meepo.bind.Const.TXT$EMPTY;
import static pro.fessional.meepo.poof.RnaWarmed.EMPTY;

/**
 * Compile java code and execute
 *
 * @author trydofor
 * @since 2020-10-15
 */
public class JavaEngine implements RnaEngine {

    public static final int KIND_JAVA = 1;
    public static final int KIND_FUN = 2;

    private static final Logger logger = LoggerFactory.getLogger(JavaEngine.class);
    private static final String[] TYPE = {ENGINE$JAVA, ENGINE$FUN};
    private static final ConcurrentHashMap ExprEval = new ConcurrentHashMap<>();

    @Override
    public @NotNull String[] type() {
        return TYPE;
    }

    @Override
    public Object eval(@NotNull Map ctx, @NotNull RnaWarmed expr, boolean mute) {
        if (expr == EMPTY) return null;

        Object obj = null;
        try {
            JavaEval java = expr.getTypedWork();
            if (expr.kind == KIND_JAVA) {
                obj = java.eval(ctx, null);
            }
            else {
                obj = java;
            }
        }
        catch (Throwable t) {
            if (mute) {
                logger.warn("mute failed-eval " + expr, t);
            }
            else {
                throw new IllegalStateException(expr.toString(), t);
            }
        }
        return obj;
    }

    @Override
    public @NotNull RnaEngine fork() {
        return this;
    }

    @Override
    public @NotNull RnaWarmed warm(@NotNull String type, @NotNull String expr) {
        JavaEval eval = ExprEval.computeIfAbsent(expr, this::compile);
        int kind = type.equalsIgnoreCase(ENGINE$JAVA) ? KIND_JAVA : KIND_FUN;
        return new RnaWarmed(type, expr, eval, kind);
    }

    private static final Pattern PtnImps = Pattern.compile("\\s*import\\s+[^;]+;\\s*", Pattern.MULTILINE);
    private static final AtomicInteger Counter = new AtomicInteger(0);

    private JavaEval compile(String expr) {
        final long s = System.currentTimeMillis();
        Matcher m = PtnImps.matcher(expr);
        String imps, body, colon;
        if (m.find()) {
            StringBuilder buf = new StringBuilder();
            int end;
            do {
                end = m.end();
                for (int i = m.start(); i < end; i++) {
                    char c = expr.charAt(i);
                    if (c == ',') {
                        buf.append(";\nimport ");
                    }
                    else {
                        buf.append(c);
                    }
                }
            } while (m.find());
            imps = buf.toString();
            body = expr.substring(end);
        }
        else {
            imps = TXT$EMPTY;
            body = expr;
        }
        colon = TXT$EMPTY;
        for (int i = body.length() - 1; i >= 0; i--) {
            char c = body.charAt(i);
            if (!Character.isWhitespace(c)) {
                if (c != ';') colon = ";";
                break;
            }
        }

        final String name = "Java" + Counter.incrementAndGet();
        HashMap ctx = new HashMap<>();
        ctx.put("import", imps);
        ctx.put("class", name);
        ctx.put("method", body);
        ctx.put("colon", colon);
        String tmpl = "classpath:/pro/fessional/meepo/poof/impl/java/JavaName.java";
        String code = Meepo.merge(ctx, tmpl, Meepo.CACHE_ALWAYS);
        try {
            Class clz = Java.compile("pro.fessional.meepo.poof.impl.java." + name, code);
            JavaEval java = Java.create(clz);
            logger.info("cost {}ms to compile {}", System.currentTimeMillis() - s, expr);
            return java;
        }
        catch (RuntimeException e) {
            logger.error("failed to create java-code=\n" + code + "\n", e);
            throw e;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy