org.decojer.cavaj.readers.asm.ReadFieldVisitor.java Source code

Java tutorial

Introduction

Here is the source code for org.decojer.cavaj.readers.asm.ReadFieldVisitor.java

Source

/*
 * $Id$
 *
 * This file is part of the DecoJer project.
 * Copyright (C) 2010-2011  Andr Pankraz
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
    
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
    
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * In accordance with Section 7(b) of the GNU Affero General Public License,
 * a covered work must retain the producer line in every Java Source Code
 * that is created using DecoJer.
 */
package org.decojer.cavaj.readers.asm;

import static org.decojer.cavaj.readers.asm.ReadUtils.annotateT;

import java.lang.annotation.RetentionPolicy;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import org.decojer.cavaj.model.A;
import org.decojer.cavaj.model.DU;
import org.decojer.cavaj.model.fields.F;
import org.decojer.cavaj.model.types.T;
import org.decojer.cavaj.readers.ReadVisitor;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.TypePath;
import org.objectweb.asm.TypeReference;

/**
 * ASM read field visitor.
 *
 * @author Andr Pankraz
 */
@Slf4j
public class ReadFieldVisitor extends FieldVisitor implements ReadVisitor {

    private A[] as;

    @Nullable
    private F f;

    @Getter
    @Nonnull
    private final ReadClassVisitor parentVisitor;

    private final ReadAnnotationMemberVisitor readAnnotationMemberVisitor;

    /**
     * Constructor.
     *
     * @param parentVisitor
     *            parent visitor
     */
    public ReadFieldVisitor(@Nonnull final ReadClassVisitor parentVisitor) {
        super(Opcodes.ASM5);
        this.parentVisitor = parentVisitor;
        this.readAnnotationMemberVisitor = new ReadAnnotationMemberVisitor(this);
    }

    @Override
    public DU getDu() {
        return getParentVisitor().getDu();
    }

    /**
     * Get field declaration.
     *
     * @return field declaration
     */
    @Nonnull
    protected F getF() {
        assert this.f != null;
        return this.f;
    }

    @Override
    public T getT() {
        return getParentVisitor().getT();
    }

    /**
     * Init and set field.
     *
     * @param f
     *            field
     */
    public void init(@Nonnull final F f) {
        this.f = f;
        this.as = null;
    }

    @Override
    public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {
        if (this.as == null) {
            this.as = new A[1];
        } else {
            final A[] newAs = new A[this.as.length + 1];
            System.arraycopy(this.as, 0, newAs, 0, this.as.length);
            this.as = newAs;
        }
        this.as[this.as.length - 1] = this.readAnnotationMemberVisitor.init(desc,
                visible ? RetentionPolicy.RUNTIME : RetentionPolicy.CLASS);
        return this.readAnnotationMemberVisitor;
    }

    @Override
    public void visitAttribute(final Attribute attr) {
        log.warn(getF() + ": Unknown field attribute tag '" + attr.type + "' for field info '" + getF().getT()
                + "'!");
    }

    @Override
    public void visitEnd() {
        if (this.as != null) {
            getF().setAs(this.as);
        }
    }

    @Override
    public AnnotationVisitor visitTypeAnnotation(final int typeRef, @Nullable final TypePath typePath,
            final String desc, final boolean visible) {
        final A a = this.readAnnotationMemberVisitor.init(desc,
                visible ? RetentionPolicy.RUNTIME : RetentionPolicy.CLASS);
        if (a == null) {
            log.warn(getF() + ": Cannot read annotation for descriptor '" + desc + "'!");
            return null;
        }
        final TypeReference typeReference = new TypeReference(typeRef);
        switch (typeReference.getSort()) {
        case TypeReference.FIELD:
            getF().setValueT(annotateT(getF().getValueT(), a, typePath));
            break;
        default:
            log.warn(
                    getF() + ": Unknown type annotation ref sort '0x" + Integer.toHexString(typeReference.getSort())
                            + "' : " + typeRef + " : " + typePath + " : " + desc + " : " + visible);
        }
        return this.readAnnotationMemberVisitor;
    }

}