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

com.feilong.lib.javassist.bytecode.InnerClassesAttribute Maven / Gradle / Ivy

Go to download

feilong is a suite of core and expanded libraries that include utility classes, http, excel,cvs, io classes, and much much more.

There is a newer version: 4.0.8
Show newest version
/*
 * Javassist, a Java-bytecode translator toolkit.
 * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License.  Alternatively, the contents of this file may be used under
 * the terms of the GNU Lesser General Public License Version 2.1 or later,
 * or the Apache License Version 2.0.
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 */

package com.feilong.lib.javassist.bytecode;

import java.io.DataInputStream;
import java.io.IOException;
import java.util.Map;

/**
 * InnerClasses_attribute.
 */
public class InnerClassesAttribute extends AttributeInfo{

    /**
     * The name of this attribute "InnerClasses".
     */
    public static final String tag = "InnerClasses";

    InnerClassesAttribute(ConstPool cp, int n, DataInputStream in) throws IOException{
        super(cp, n, in);
    }

    private InnerClassesAttribute(ConstPool cp, byte[] info){
        super(cp, tag, info);
    }

    /**
     * Constructs an empty InnerClasses attribute.
     *
     * @see #append(String, String, String, int)
     */
    public InnerClassesAttribute(ConstPool cp){
        super(cp, tag, new byte[2]);
        ByteArray.write16bit(0, get(), 0);
    }

    /**
     * Returns number_of_classes.
     */
    public int tableLength(){
        return ByteArray.readU16bit(get(), 0);
    }

    /**
     * Returns classes[nth].inner_class_info_index.
     */
    public int innerClassIndex(int nth){
        return ByteArray.readU16bit(get(), nth * 8 + 2);
    }

    /**
     * Returns the class name indicated
     * by classes[nth].inner_class_info_index.
     * The class name is fully-qualified and separated by dot.
     *
     * @return null or the class name.
     * @see ConstPool#getClassInfo(int)
     */
    public String innerClass(int nth){
        int i = innerClassIndex(nth);
        if (i == 0){
            return null;
        }
        return constPool.getClassInfo(i);
    }

    /**
     * Sets classes[nth].inner_class_info_index to
     * the given index.
     */
    public void setInnerClassIndex(int nth,int index){
        ByteArray.write16bit(index, get(), nth * 8 + 2);
    }

    /**
     * Returns classes[nth].outer_class_info_index.
     */
    public int outerClassIndex(int nth){
        return ByteArray.readU16bit(get(), nth * 8 + 4);
    }

    /**
     * Returns the class name indicated
     * by classes[nth].outer_class_info_index.
     *
     * @return null or the class name.
     */
    public String outerClass(int nth){
        int i = outerClassIndex(nth);
        if (i == 0){
            return null;
        }
        return constPool.getClassInfo(i);
    }

    /**
     * Sets classes[nth].outer_class_info_index to
     * the given index.
     */
    public void setOuterClassIndex(int nth,int index){
        ByteArray.write16bit(index, get(), nth * 8 + 4);
    }

    /**
     * Returns classes[nth].inner_name_index.
     */
    public int innerNameIndex(int nth){
        return ByteArray.readU16bit(get(), nth * 8 + 6);
    }

    /**
     * Returns the simple class name indicated
     * by classes[nth].inner_name_index.
     *
     * @return null or the class name.
     */
    public String innerName(int nth){
        int i = innerNameIndex(nth);
        if (i == 0){
            return null;
        }
        return constPool.getUtf8Info(i);
    }

    /**
     * Sets classes[nth].inner_name_index to
     * the given index.
     */
    public void setInnerNameIndex(int nth,int index){
        ByteArray.write16bit(index, get(), nth * 8 + 6);
    }

    /**
     * Returns classes[nth].inner_class_access_flags.
     */
    public int accessFlags(int nth){
        return ByteArray.readU16bit(get(), nth * 8 + 8);
    }

    /**
     * Sets classes[nth].inner_class_access_flags to
     * the given index.
     */
    public void setAccessFlags(int nth,int flags){
        ByteArray.write16bit(flags, get(), nth * 8 + 8);
    }

    /**
     * Finds the entry for the given inner class.
     *
     * @param name
     *            the fully-qualified class name separated by dot and $.
     * @return the index or -1 if not found.
     * @since 3.22
     */
    public int find(String name){
        int n = tableLength();
        for (int i = 0; i < n; i++){
            if (name.equals(innerClass(i))){
                return i;
            }
        }

        return -1;
    }

    /**
     * Appends a new entry.
     *
     * @param inner
     *            inner_class_info_index
     * @param outer
     *            outer_class_info_index
     * @param name
     *            inner_name_index
     * @param flags
     *            inner_class_access_flags
     */
    public void append(String inner,String outer,String name,int flags){
        int i = constPool.addClassInfo(inner);
        int o = constPool.addClassInfo(outer);
        int n = constPool.addUtf8Info(name);
        append(i, o, n, flags);
    }

    /**
     * Appends a new entry.
     *
     * @param inner
     *            inner_class_info_index
     * @param outer
     *            outer_class_info_index
     * @param name
     *            inner_name_index
     * @param flags
     *            inner_class_access_flags
     */
    public void append(int inner,int outer,int name,int flags){
        byte[] data = get();
        int len = data.length;
        byte[] newData = new byte[len + 8];
        for (int i = 2; i < len; ++i){
            newData[i] = data[i];
        }

        int n = ByteArray.readU16bit(data, 0);
        ByteArray.write16bit(n + 1, newData, 0);

        ByteArray.write16bit(inner, newData, len);
        ByteArray.write16bit(outer, newData, len + 2);
        ByteArray.write16bit(name, newData, len + 4);
        ByteArray.write16bit(flags, newData, len + 6);

        set(newData);
    }

    /**
     * Removes the {@code nth} entry. It does not eliminate
     * constant pool items that the removed entry refers to.
     * {@link ClassFile#compact()} should be executed to remove
     * these unnecessary items.
     *
     * @param nth
     *            0, 1, 2, ...
     * @return the number of items after the removal.
     * @see ClassFile#compact()
     */
    public int remove(int nth){
        byte[] data = get();
        int len = data.length;
        if (len < 10){
            return 0;
        }

        int n = ByteArray.readU16bit(data, 0);
        int nthPos = 2 + nth * 8;
        if (n <= nth){
            return n;
        }

        byte[] newData = new byte[len - 8];
        ByteArray.write16bit(n - 1, newData, 0);
        int i = 2, j = 2;
        while (i < len){
            if (i == nthPos){
                i += 8;
            }else{
                newData[j++] = data[i++];
            }
        }

        set(newData);
        return n - 1;
    }

    /**
     * Makes a copy. Class names are replaced according to the
     * given Map object.
     *
     * @param newCp
     *            the constant pool table used by the new copy.
     * @param classnames
     *            pairs of replaced and substituted
     *            class names.
     */
    @Override
    public AttributeInfo copy(ConstPool newCp,Map classnames){
        byte[] src = get();
        byte[] dest = new byte[src.length];
        ConstPool cp = getConstPool();
        InnerClassesAttribute attr = new InnerClassesAttribute(newCp, dest);
        int n = ByteArray.readU16bit(src, 0);
        ByteArray.write16bit(n, dest, 0);
        int j = 2;
        for (int i = 0; i < n; ++i){
            int innerClass = ByteArray.readU16bit(src, j);
            int outerClass = ByteArray.readU16bit(src, j + 2);
            int innerName = ByteArray.readU16bit(src, j + 4);
            int innerAccess = ByteArray.readU16bit(src, j + 6);

            if (innerClass != 0){
                innerClass = cp.copy(innerClass, newCp, classnames);
            }

            ByteArray.write16bit(innerClass, dest, j);

            if (outerClass != 0){
                outerClass = cp.copy(outerClass, newCp, classnames);
            }

            ByteArray.write16bit(outerClass, dest, j + 2);

            if (innerName != 0){
                innerName = cp.copy(innerName, newCp, classnames);
            }

            ByteArray.write16bit(innerName, dest, j + 4);
            ByteArray.write16bit(innerAccess, dest, j + 6);
            j += 8;
        }

        return attr;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy