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

act.controller.bytecode.HandlerEnhancer Maven / Gradle / Ivy

There is a newer version: 1.9.2
Show newest version
package act.controller.bytecode;

/*-
 * #%L
 * ACT Framework
 * %%
 * Copyright (C) 2014 - 2017 ActFramework
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

import static act.asm.tree.AbstractInsnNode.*;

import act.app.ActionContext;
import act.asm.*;
import act.asm.tree.*;
import act.controller.meta.*;
import act.util.AsmTypes;
import org.osgl.logging.LogManager;
import org.osgl.logging.Logger;
import org.osgl.mvc.result.Result;
import org.osgl.util.*;

import java.util.*;

public class HandlerEnhancer extends MethodVisitor implements Opcodes {

    private static final Logger logger = LogManager.get(HandlerEnhancer.class);

    private static final String RESULT_CLASS = Result.class.getName();

    private HandlerMethodMetaInfo info;
    private MethodVisitor next;
    private int paramIdShift = 0;
    private Set skipNaming = new HashSet<>();
    private Map overriddenNames = new HashMap<>();
    private boolean notAction;

    public HandlerEnhancer(final MethodVisitor mv, HandlerMethodMetaInfo meta, final int access, final String name, final String desc, final String signature, final String[] exceptions) {
        super(ASM5, new MethodNode(access, name, desc, signature, exceptions));
        if (logger.isTraceEnabled()) {
            logger.trace("enhance handler: " + meta.fullName());
        }
        this.info = meta;
        this.next = mv;
    }

    @Override
    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
        if ("Lact/controller/NotAction;".equals(desc)) {
            notAction = true;
        }
        return super.visitAnnotation(desc, visible);
    }

    @Override
    public AnnotationVisitor visitParameterAnnotation(final int parameter, String desc, boolean visible) {
        if ("Ljavax/inject/Named;".equals(desc)) {
            skipNaming.add(parameter);
        } else if ("Lorg/osgl/mvc/annotation/Param;".equals(desc)) {
            return new AnnotationVisitor(ASM5, super.visitParameterAnnotation(parameter, desc, visible)) {
                @Override
                public void visit(String name, Object value) {
                    if ("value".equals(name)) {
                        overriddenNames.put(parameter, S.string(value));
                    }
                    super.visit(name, value);
                }
            };
        }
        return super.visitParameterAnnotation(parameter, desc, visible);
    }

    @Override
    public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
        if (!"this".equals(name)) {
            int paramId = index;
            if (!info.isStatic()) {
                paramId--;
            }
            paramId -= paramIdShift;
            if (paramId < info.paramCount()) {
                HandlerParamMetaInfo param = info.param(paramId);
                param.name(name);
                if (Type.getType(long.class).equals(param.type()) || Type.getType(double.class).equals(param.type())) {
                    paramIdShift++;
                }
            }
            LocalVariableMetaInfo local = new LocalVariableMetaInfo(index, name, desc, start, end);
            info.addLocal(local);
        }
        super.visitLocalVariable(name, desc, signature, start, end, index);
    }

    @Override
    public void visitLineNumber(int line, Label start) {
        super.visitLineNumber(line, start);
        AsmContext.line(line);
    }

    @Override
    public void visitEnd() {
        if (notAction) {
            super.visitEnd();
            return;
        }
        MethodNode mn = (MethodNode) mv;
        addParamAnnotations();
        transform(mn);
        mn.accept(next);
    }

    private void addParamAnnotations() {
        int sz = info.paramCount();
        for (int i = 0; i < sz; ++i) {
            if (!skipNaming.contains(i)) {
                String name = overriddenNames.get(i);
                if (null == name) name = info.param(i).name();
                AnnotationVisitor av = mv.visitParameterAnnotation(i, "Ljavax/inject/Named;", true);
                av.visit("value", name);
            }
        }
    }

    private void transform(MethodNode mn) {
        new Transformer(mn, info).doIt();
    }

    private static class Transformer {
        MethodNode mn;
        InsnList instructions;
        private HandlerMethodMetaInfo meta;
        List




© 2015 - 2024 Weber Informatics LLC | Privacy Policy