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

io.github.dmlloyd.classfile.impl.verifier.VerificationWrapper Maven / Gradle / Ivy

/*
 * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */
package io.github.dmlloyd.classfile.impl.verifier;

import java.lang.constant.ClassDesc;
import java.util.LinkedList;
import java.util.List;

import io.github.dmlloyd.classfile.constantpool.ClassEntry;
import io.github.dmlloyd.classfile.constantpool.DynamicConstantPoolEntry;
import io.github.dmlloyd.classfile.constantpool.MemberRefEntry;
import io.github.dmlloyd.classfile.constantpool.NameAndTypeEntry;
import io.github.dmlloyd.classfile.extras.reflect.AccessFlag;
import java.util.stream.Collectors;
import io.github.dmlloyd.classfile.ClassModel;
import io.github.dmlloyd.classfile.constantpool.ConstantPool;
import io.github.dmlloyd.classfile.MethodModel;
import io.github.dmlloyd.classfile.attribute.LocalVariableInfo;
import io.github.dmlloyd.classfile.Attributes;
import io.github.dmlloyd.classfile.impl.BoundAttribute;
import io.github.dmlloyd.classfile.impl.CodeImpl;
import io.github.dmlloyd.classfile.impl.Util;

public final class VerificationWrapper {
    private final ClassModel clm;
    private final ConstantPoolWrapper cp;

    public VerificationWrapper(ClassModel clm) {
        this.clm = clm;
        this.cp = new ConstantPoolWrapper(clm.constantPool());
     }

    String thisClassName() {
        return clm.thisClass().asInternalName();
    }

    int majorVersion() {
        return clm.majorVersion();
    }

    String superclassName() {
        return clm.superclass().map(ClassEntry::asInternalName).orElse(null);
    }

    Iterable interfaceNames() {
        return Util.mappedList(clm.interfaces(), ClassEntry::asInternalName);
    }

    Iterable methods() {
        return clm.methods().stream().map(m -> new MethodWrapper(m)).toList();
    }

    boolean findField(String name, String sig) {
        for (var f : clm.fields())
            if (f.fieldName().stringValue().equals(name) && f.fieldType().stringValue().equals(sig))
                return true;
        return false;
    }

    class MethodWrapper {

        final MethodModel m;
        private final CodeImpl c;
        private final List exc;

        MethodWrapper(MethodModel m) {
            this.m = m;
            this.c = (CodeImpl)m.code().orElse(null);
            exc = new LinkedList<>();
            if (c != null) c.iterateExceptionHandlers((start, end, handler, catchType) -> {
                exc.add(new int[] {start, end, handler, catchType});
            });
        }

        ConstantPoolWrapper constantPool() {
            return cp;
        }

        boolean isNative() {
            return m.flags().has(AccessFlag.NATIVE);
        }

        boolean isAbstract() {
            return m.flags().has(AccessFlag.ABSTRACT);
        }

        boolean isBridge() {
            return m.flags().has(AccessFlag.BRIDGE);
        }

        boolean isStatic() {
            return m.flags().has(AccessFlag.STATIC);
        }

        String name() {
            return m.methodName().stringValue();
        }

        int maxStack() {
            return c == null ? 0 : c.maxStack();
        }

        int maxLocals() {
            return c == null ? 0 : c.maxLocals();
        }

        String descriptor() {
            return m.methodType().stringValue();
        }

        String parameters() {
            return m.methodTypeSymbol().parameterList().stream().map(ClassDesc::displayName).collect(Collectors.joining(","));
        }

        int codeLength() {
            return c == null ? 0 : c.codeLength();
        }

        byte[] codeArray() {
            return c == null ? null : c.codeArray();
        }

        List exceptionTable() {
            return exc;
        }

        List localVariableTable() {
            var attro = c.findAttribute(Attributes.localVariableTable());
            return attro.map(lvta -> lvta.localVariables()).orElse(List.of());
        }

        byte[] stackMapTableRawData() {
            var attro = c.findAttribute(Attributes.stackMapTable());
            return attro.map(attr -> ((BoundAttribute) attr).contents()).orElse(null);
        }

    }

    static class ConstantPoolWrapper {

        private final ConstantPool cp;

        ConstantPoolWrapper(ConstantPool cp) {
            this.cp = cp;
        }

        int entryCount() {
            return cp.size();
        }

        String classNameAt(int index) {
            return cp.entryByIndex(index, ClassEntry.class).asInternalName();
        }

        String dynamicConstantSignatureAt(int index) {
            return cp.entryByIndex(index, DynamicConstantPoolEntry.class).type().stringValue();
        }

        int tagAt(int index) {
            return cp.entryByIndex(index).tag();
        }

        private NameAndTypeEntry _refNameType(int index) {
            var e = cp.entryByIndex(index);
            return (e instanceof DynamicConstantPoolEntry de) ? de.nameAndType() :
                    e != null ? ((MemberRefEntry)e).nameAndType() : null;
        }

        String refNameAt(int index) {
            return _refNameType(index).name().stringValue();
        }

        String refSignatureAt(int index) {
            return _refNameType(index).type().stringValue();
        }

        int refClassIndexAt(int index) {
            return cp.entryByIndex(index, MemberRefEntry.class).owner().index();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy