FileDocCategorySizeDatePackage
StdAttributeFactory.javaAPI DocAndroid 5.1 API27069Thu Mar 12 22:18:30 GMT 2015com.android.dx.cf.direct

StdAttributeFactory

public class StdAttributeFactory extends AttributeFactory
Standard subclass of {@link AttributeFactory}, which knows how to parse all the standard attribute types.

Fields Summary
public static final StdAttributeFactory
THE_ONE
{@code non-null;} shared instance of this class
Constructors Summary
public StdAttributeFactory()
Constructs an instance.


            
      
        // This space intentionally left blank.
    
Methods Summary
private com.android.dx.cf.iface.AttributeannotationDefault(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)
Parses an {@code AnnotationDefault} attribute.

        if (length < 2) {
            throwSeverelyTruncated();
        }

        AnnotationParser ap =
            new AnnotationParser(cf, offset, length, observer);
        Constant cst = ap.parseValueAttribute();

        return new AttAnnotationDefault(cst, length);
    
private com.android.dx.cf.iface.Attributecode(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)
Parses a {@code Code} attribute.

        if (length < 12) {
            return throwSeverelyTruncated();
        }

        ByteArray bytes = cf.getBytes();
        ConstantPool pool = cf.getConstantPool();
        int maxStack = bytes.getUnsignedShort(offset); // u2 max_stack
        int maxLocals = bytes.getUnsignedShort(offset + 2); // u2 max_locals
        int codeLength = bytes.getInt(offset + 4); // u4 code_length
        int origOffset = offset;

        if (observer != null) {
            observer.parsed(bytes, offset, 2,
                            "max_stack: " + Hex.u2(maxStack));
            observer.parsed(bytes, offset + 2, 2,
                            "max_locals: " + Hex.u2(maxLocals));
            observer.parsed(bytes, offset + 4, 4,
                            "code_length: " + Hex.u4(codeLength));
        }

        offset += 8;
        length -= 8;

        if (length < (codeLength + 4)) {
            return throwTruncated();
        }

        int codeOffset = offset;
        offset += codeLength;
        length -= codeLength;
        BytecodeArray code =
            new BytecodeArray(bytes.slice(codeOffset, codeOffset + codeLength),
                              pool);
        if (observer != null) {
            code.forEach(new CodeObserver(code.getBytes(), observer));
        }

        // u2 exception_table_length
        int exceptionTableLength = bytes.getUnsignedShort(offset);
        ByteCatchList catches = (exceptionTableLength == 0) ?
            ByteCatchList.EMPTY :
            new ByteCatchList(exceptionTableLength);

        if (observer != null) {
            observer.parsed(bytes, offset, 2,
                            "exception_table_length: " +
                            Hex.u2(exceptionTableLength));
        }

        offset += 2;
        length -= 2;

        if (length < (exceptionTableLength * 8 + 2)) {
            return throwTruncated();
        }

        for (int i = 0; i < exceptionTableLength; i++) {
            if (observer != null) {
                observer.changeIndent(1);
            }

            int startPc = bytes.getUnsignedShort(offset);
            int endPc = bytes.getUnsignedShort(offset + 2);
            int handlerPc = bytes.getUnsignedShort(offset + 4);
            int catchTypeIdx = bytes.getUnsignedShort(offset + 6);
            CstType catchType = (CstType) pool.get0Ok(catchTypeIdx);
            catches.set(i, startPc, endPc, handlerPc, catchType);
            if (observer != null) {
                observer.parsed(bytes, offset, 8,
                                Hex.u2(startPc) + ".." + Hex.u2(endPc) +
                                " -> " + Hex.u2(handlerPc) + " " +
                                ((catchType == null) ? "<any>" :
                                 catchType.toHuman()));
            }
            offset += 8;
            length -= 8;

            if (observer != null) {
                observer.changeIndent(-1);
            }
        }

        catches.setImmutable();

        AttributeListParser parser =
            new AttributeListParser(cf, CTX_CODE, offset, this);
        parser.setObserver(observer);

        StdAttributeList attributes = parser.getList();
        attributes.setImmutable();

        int attributeByteCount = parser.getEndOffset() - offset;
        if (attributeByteCount != length) {
            return throwBadLength(attributeByteCount + (offset - origOffset));
        }

        return new AttCode(maxStack, maxLocals, code, catches, attributes);
    
private com.android.dx.cf.iface.AttributeconstantValue(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)
Parses a {@code ConstantValue} attribute.

        if (length != 2) {
            return throwBadLength(2);
        }

        ByteArray bytes = cf.getBytes();
        ConstantPool pool = cf.getConstantPool();
        int idx = bytes.getUnsignedShort(offset);
        TypedConstant cst = (TypedConstant) pool.get(idx);
        Attribute result = new AttConstantValue(cst);

        if (observer != null) {
            observer.parsed(bytes, offset, 2, "value: " + cst);
        }

        return result;
    
private com.android.dx.cf.iface.Attributedeprecated(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)
Parses a {@code Deprecated} attribute.

        if (length != 0) {
            return throwBadLength(0);
        }

        return new AttDeprecated();
    
private com.android.dx.cf.iface.AttributeenclosingMethod(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)
Parses an {@code EnclosingMethod} attribute.

        if (length != 4) {
            throwBadLength(4);
        }

        ByteArray bytes = cf.getBytes();
        ConstantPool pool = cf.getConstantPool();

        int idx = bytes.getUnsignedShort(offset);
        CstType type = (CstType) pool.get(idx);

        idx = bytes.getUnsignedShort(offset + 2);
        CstNat method = (CstNat) pool.get0Ok(idx);

        Attribute result = new AttEnclosingMethod(type, method);

        if (observer != null) {
            observer.parsed(bytes, offset, 2, "class: " + type);
            observer.parsed(bytes, offset + 2, 2, "method: " +
                            DirectClassFile.stringOrNone(method));
        }

        return result;
    
private com.android.dx.cf.iface.Attributeexceptions(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)
Parses an {@code Exceptions} attribute.

        if (length < 2) {
            return throwSeverelyTruncated();
        }

        ByteArray bytes = cf.getBytes();
        int count = bytes.getUnsignedShort(offset); // number_of_exceptions

        if (observer != null) {
            observer.parsed(bytes, offset, 2,
                            "number_of_exceptions: " + Hex.u2(count));
        }

        offset += 2;
        length -= 2;

        if (length != (count * 2)) {
            throwBadLength((count * 2) + 2);
        }

        TypeList list = cf.makeTypeList(offset, count);
        return new AttExceptions(list);
    
private com.android.dx.cf.iface.AttributeinnerClasses(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)
Parses an {@code InnerClasses} attribute.

        if (length < 2) {
            return throwSeverelyTruncated();
        }

        ByteArray bytes = cf.getBytes();
        ConstantPool pool = cf.getConstantPool();
        int count = bytes.getUnsignedShort(offset); // number_of_classes

        if (observer != null) {
            observer.parsed(bytes, offset, 2,
                            "number_of_classes: " + Hex.u2(count));
        }

        offset += 2;
        length -= 2;

        if (length != (count * 8)) {
            throwBadLength((count * 8) + 2);
        }

        InnerClassList list = new InnerClassList(count);

        for (int i = 0; i < count; i++) {
            int innerClassIdx = bytes.getUnsignedShort(offset);
            int outerClassIdx = bytes.getUnsignedShort(offset + 2);
            int nameIdx = bytes.getUnsignedShort(offset + 4);
            int accessFlags = bytes.getUnsignedShort(offset + 6);
            CstType innerClass = (CstType) pool.get(innerClassIdx);
            CstType outerClass = (CstType) pool.get0Ok(outerClassIdx);
            CstString name = (CstString) pool.get0Ok(nameIdx);
            list.set(i, innerClass, outerClass, name, accessFlags);
            if (observer != null) {
                observer.parsed(bytes, offset, 2,
                                "inner_class: " +
                                DirectClassFile.stringOrNone(innerClass));
                observer.parsed(bytes, offset + 2, 2,
                                "  outer_class: " +
                                DirectClassFile.stringOrNone(outerClass));
                observer.parsed(bytes, offset + 4, 2,
                                "  name: " +
                                DirectClassFile.stringOrNone(name));
                observer.parsed(bytes, offset + 6, 2,
                                "  access_flags: " +
                                AccessFlags.innerClassString(accessFlags));
            }
            offset += 8;
        }

        list.setImmutable();
        return new AttInnerClasses(list);
    
private com.android.dx.cf.iface.AttributelineNumberTable(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)
Parses a {@code LineNumberTable} attribute.

        if (length < 2) {
            return throwSeverelyTruncated();
        }

        ByteArray bytes = cf.getBytes();
        int count = bytes.getUnsignedShort(offset); // line_number_table_length

        if (observer != null) {
            observer.parsed(bytes, offset, 2,
                            "line_number_table_length: " + Hex.u2(count));
        }

        offset += 2;
        length -= 2;

        if (length != (count * 4)) {
            throwBadLength((count * 4) + 2);
        }

        LineNumberList list = new LineNumberList(count);

        for (int i = 0; i < count; i++) {
            int startPc = bytes.getUnsignedShort(offset);
            int lineNumber = bytes.getUnsignedShort(offset + 2);
            list.set(i, startPc, lineNumber);
            if (observer != null) {
                observer.parsed(bytes, offset, 4,
                                Hex.u2(startPc) + " " + lineNumber);
            }
            offset += 4;
        }

        list.setImmutable();
        return new AttLineNumberTable(list);
    
private com.android.dx.cf.iface.AttributelocalVariableTable(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)
Parses a {@code LocalVariableTable} attribute.

        if (length < 2) {
            return throwSeverelyTruncated();
        }

        ByteArray bytes = cf.getBytes();
        int count = bytes.getUnsignedShort(offset);

        if (observer != null) {
            observer.parsed(bytes, offset, 2,
                    "local_variable_table_length: " + Hex.u2(count));
        }

        LocalVariableList list = parseLocalVariables(
                bytes.slice(offset + 2, offset + length), cf.getConstantPool(),
                observer, count, false);
        return new AttLocalVariableTable(list);
    
private com.android.dx.cf.iface.AttributelocalVariableTypeTable(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)
Parses a {@code LocalVariableTypeTable} attribute.

        if (length < 2) {
            return throwSeverelyTruncated();
        }

        ByteArray bytes = cf.getBytes();
        int count = bytes.getUnsignedShort(offset);

        if (observer != null) {
            observer.parsed(bytes, offset, 2,
                    "local_variable_type_table_length: " + Hex.u2(count));
        }

        LocalVariableList list = parseLocalVariables(
                bytes.slice(offset + 2, offset + length), cf.getConstantPool(),
                observer, count, true);
        return new AttLocalVariableTypeTable(list);
    
protected com.android.dx.cf.iface.Attributeparse0(DirectClassFile cf, int context, java.lang.String name, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)
{@inheritDoc}

        switch (context) {
            case CTX_CLASS: {
                if (name == AttDeprecated.ATTRIBUTE_NAME) {
                    return deprecated(cf, offset, length, observer);
                }
                if (name == AttEnclosingMethod.ATTRIBUTE_NAME) {
                    return enclosingMethod(cf, offset, length, observer);
                }
                if (name == AttInnerClasses.ATTRIBUTE_NAME) {
                    return innerClasses(cf, offset, length, observer);
                }
                if (name == AttRuntimeInvisibleAnnotations.ATTRIBUTE_NAME) {
                    return runtimeInvisibleAnnotations(cf, offset, length,
                            observer);
                }
                if (name == AttRuntimeVisibleAnnotations.ATTRIBUTE_NAME) {
                    return runtimeVisibleAnnotations(cf, offset, length,
                            observer);
                }
                if (name == AttSynthetic.ATTRIBUTE_NAME) {
                    return synthetic(cf, offset, length, observer);
                }
                if (name == AttSignature.ATTRIBUTE_NAME) {
                    return signature(cf, offset, length, observer);
                }
                if (name == AttSourceFile.ATTRIBUTE_NAME) {
                    return sourceFile(cf, offset, length, observer);
                }
                break;
            }
            case CTX_FIELD: {
                if (name == AttConstantValue.ATTRIBUTE_NAME) {
                    return constantValue(cf, offset, length, observer);
                }
                if (name == AttDeprecated.ATTRIBUTE_NAME) {
                    return deprecated(cf, offset, length, observer);
                }
                if (name == AttRuntimeInvisibleAnnotations.ATTRIBUTE_NAME) {
                    return runtimeInvisibleAnnotations(cf, offset, length,
                            observer);
                }
                if (name == AttRuntimeVisibleAnnotations.ATTRIBUTE_NAME) {
                    return runtimeVisibleAnnotations(cf, offset, length,
                            observer);
                }
                if (name == AttSignature.ATTRIBUTE_NAME) {
                    return signature(cf, offset, length, observer);
                }
                if (name == AttSynthetic.ATTRIBUTE_NAME) {
                    return synthetic(cf, offset, length, observer);
                }
                break;
            }
            case CTX_METHOD: {
                if (name == AttAnnotationDefault.ATTRIBUTE_NAME) {
                    return annotationDefault(cf, offset, length, observer);
                }
                if (name == AttCode.ATTRIBUTE_NAME) {
                    return code(cf, offset, length, observer);
                }
                if (name == AttDeprecated.ATTRIBUTE_NAME) {
                    return deprecated(cf, offset, length, observer);
                }
                if (name == AttExceptions.ATTRIBUTE_NAME) {
                    return exceptions(cf, offset, length, observer);
                }
                if (name == AttRuntimeInvisibleAnnotations.ATTRIBUTE_NAME) {
                    return runtimeInvisibleAnnotations(cf, offset, length,
                            observer);
                }
                if (name == AttRuntimeVisibleAnnotations.ATTRIBUTE_NAME) {
                    return runtimeVisibleAnnotations(cf, offset, length,
                            observer);
                }
                if (name == AttRuntimeInvisibleParameterAnnotations.
                        ATTRIBUTE_NAME) {
                    return runtimeInvisibleParameterAnnotations(
                            cf, offset, length, observer);
                }
                if (name == AttRuntimeVisibleParameterAnnotations.
                        ATTRIBUTE_NAME) {
                    return runtimeVisibleParameterAnnotations(
                            cf, offset, length, observer);
                }
                if (name == AttSignature.ATTRIBUTE_NAME) {
                    return signature(cf, offset, length, observer);
                }
                if (name == AttSynthetic.ATTRIBUTE_NAME) {
                    return synthetic(cf, offset, length, observer);
                }
                break;
            }
            case CTX_CODE: {
                if (name == AttLineNumberTable.ATTRIBUTE_NAME) {
                    return lineNumberTable(cf, offset, length, observer);
                }
                if (name == AttLocalVariableTable.ATTRIBUTE_NAME) {
                    return localVariableTable(cf, offset, length, observer);
                }
                if (name == AttLocalVariableTypeTable.ATTRIBUTE_NAME) {
                    return localVariableTypeTable(cf, offset, length,
                            observer);
                }
                break;
            }
        }

        return super.parse0(cf, context, name, offset, length, observer);
    
private com.android.dx.cf.code.LocalVariableListparseLocalVariables(com.android.dx.util.ByteArray bytes, com.android.dx.rop.cst.ConstantPool pool, com.android.dx.cf.iface.ParseObserver observer, int count, boolean typeTable)
Parse the table part of either a {@code LocalVariableTable} or a {@code LocalVariableTypeTable}.

param
bytes {@code non-null;} bytes to parse, which should only contain the table data (no header)
param
pool {@code non-null;} constant pool to use
param
count {@code >= 0;} the number of entries
param
typeTable {@code true} iff this is for a type table
return
{@code non-null;} the constructed list

        if (bytes.size() != (count * 10)) {
            // "+ 2" is for the count.
            throwBadLength((count * 10) + 2);
        }

        ByteArray.MyDataInputStream in = bytes.makeDataInputStream();
        LocalVariableList list = new LocalVariableList(count);

        try {
            for (int i = 0; i < count; i++) {
                int startPc = in.readUnsignedShort();
                int length = in.readUnsignedShort();
                int nameIdx = in.readUnsignedShort();
                int typeIdx = in.readUnsignedShort();
                int index = in.readUnsignedShort();
                CstString name = (CstString) pool.get(nameIdx);
                CstString type = (CstString) pool.get(typeIdx);
                CstString descriptor = null;
                CstString signature = null;

                if (typeTable) {
                    signature = type;
                } else {
                    descriptor = type;
                }

                list.set(i, startPc, length, name,
                        descriptor, signature, index);

                if (observer != null) {
                    observer.parsed(bytes, i * 10, 10, Hex.u2(startPc) +
                            ".." + Hex.u2(startPc + length) + " " +
                            Hex.u2(index) + " " + name.toHuman() + " " +
                            type.toHuman());
                }
            }
        } catch (IOException ex) {
            throw new RuntimeException("shouldn't happen", ex);
        }

        list.setImmutable();
        return list;
    
private com.android.dx.cf.iface.AttributeruntimeInvisibleAnnotations(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)
Parses a {@code RuntimeInvisibleAnnotations} attribute.

        if (length < 2) {
            throwSeverelyTruncated();
        }

        AnnotationParser ap =
            new AnnotationParser(cf, offset, length, observer);
        Annotations annotations =
            ap.parseAnnotationAttribute(AnnotationVisibility.BUILD);

        return new AttRuntimeInvisibleAnnotations(annotations, length);
    
private com.android.dx.cf.iface.AttributeruntimeInvisibleParameterAnnotations(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)
Parses a {@code RuntimeInvisibleParameterAnnotations} attribute.

        if (length < 2) {
            throwSeverelyTruncated();
        }

        AnnotationParser ap =
            new AnnotationParser(cf, offset, length, observer);
        AnnotationsList list =
            ap.parseParameterAttribute(AnnotationVisibility.BUILD);

        return new AttRuntimeInvisibleParameterAnnotations(list, length);
    
private com.android.dx.cf.iface.AttributeruntimeVisibleAnnotations(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)
Parses a {@code RuntimeVisibleAnnotations} attribute.

        if (length < 2) {
            throwSeverelyTruncated();
        }

        AnnotationParser ap =
            new AnnotationParser(cf, offset, length, observer);
        Annotations annotations =
            ap.parseAnnotationAttribute(AnnotationVisibility.RUNTIME);

        return new AttRuntimeVisibleAnnotations(annotations, length);
    
private com.android.dx.cf.iface.AttributeruntimeVisibleParameterAnnotations(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)
Parses a {@code RuntimeVisibleParameterAnnotations} attribute.

        if (length < 2) {
            throwSeverelyTruncated();
        }

        AnnotationParser ap =
            new AnnotationParser(cf, offset, length, observer);
        AnnotationsList list =
            ap.parseParameterAttribute(AnnotationVisibility.RUNTIME);

        return new AttRuntimeVisibleParameterAnnotations(list, length);
    
private com.android.dx.cf.iface.Attributesignature(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)
Parses a {@code Signature} attribute.

        if (length != 2) {
            throwBadLength(2);
        }

        ByteArray bytes = cf.getBytes();
        ConstantPool pool = cf.getConstantPool();
        int idx = bytes.getUnsignedShort(offset);
        CstString cst = (CstString) pool.get(idx);
        Attribute result = new AttSignature(cst);

        if (observer != null) {
            observer.parsed(bytes, offset, 2, "signature: " + cst);
        }

        return result;
    
private com.android.dx.cf.iface.AttributesourceFile(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)
Parses a {@code SourceFile} attribute.

        if (length != 2) {
            throwBadLength(2);
        }

        ByteArray bytes = cf.getBytes();
        ConstantPool pool = cf.getConstantPool();
        int idx = bytes.getUnsignedShort(offset);
        CstString cst = (CstString) pool.get(idx);
        Attribute result = new AttSourceFile(cst);

        if (observer != null) {
            observer.parsed(bytes, offset, 2, "source: " + cst);
        }

        return result;
    
private com.android.dx.cf.iface.Attributesynthetic(DirectClassFile cf, int offset, int length, com.android.dx.cf.iface.ParseObserver observer)
Parses a {@code Synthetic} attribute.

        if (length != 0) {
            return throwBadLength(0);
        }

        return new AttSynthetic();
    
private static com.android.dx.cf.iface.AttributethrowBadLength(int expected)
Throws the right exception when an attribute has an unexpected length (given its contents).

param
expected expected length
return
never
throws
ParseException always thrown

        throw new ParseException("bad attribute length; expected length " +
                                 Hex.u4(expected));
    
private static com.android.dx.cf.iface.AttributethrowSeverelyTruncated()
Throws the right exception when a known attribute has a way too short length.

return
never
throws
ParseException always thrown

        throw new ParseException("severely truncated attribute");
    
private static com.android.dx.cf.iface.AttributethrowTruncated()
Throws the right exception when a known attribute has a too short length.

return
never
throws
ParseException always thrown

        throw new ParseException("truncated attribute");