
org.opalj.bi.reader.AttributesReader.scala Maven / Gradle / Ivy
The newest version!
/* BSD 2-Clause License - see OPAL/LICENSE for details. */
package org.opalj
package bi
package reader
import java.io.DataInputStream
import org.opalj.collection.immutable.RefArray
import org.opalj.control.fillRefArray
/**
* Trait that implements a template method to read in the attributes of
* a class, method_info, field_info or code_attribute structure.
*/
trait AttributesReader
extends AttributesAbstractions
with Constant_PoolAbstractions
with Unknown_attributeAbstractions {
//
// TYPE DEFINITIONS AND FACTORY METHODS
//
/**
* This factory method is called if an attribute is encountered that is unknown.
* In general, such unknown attributes are represented by the
* Unknown_attribute
class.
* However, if no representation of the unknown attribute is needed this method
* can return `null` - after reading (skipping) all bytes belonging to this attribute.
* If `null` is returned all information regarding this attribute are thrown away.
*/
def Unknown_attribute(
cp: Constant_Pool,
ap: AttributeParent,
ap_name_index: Constant_Pool_Index,
ap_descriptor_index: Constant_Pool_Index,
attribute_name_index: Int,
in: DataInputStream
): Unknown_attribute
//
// IMPLEMENTATION
//
/**
* This map associates attribute names with functions to read the corresponding
* attribute
*
* ==Names of the Attributes==
* Java 1/2Attributes:
*
* - ConstantValue_attribute
* - Exceptions_attribute
* - InnerClasses_attribute
* - EnclosingMethod_attribute
* - Synthetic_attribute
* - SourceFile_attribute
* - LineNumberTable_attribute
* - LocalVariableTable_attribute
* - LocalVariableTypeTable_attribute
* - Deprecated_attribute
* - Code_attribute => (CodeReader)
*
* Java 5Attributes:
*
* - Signature_attribute
* - SourceDebugExtension_attribute
* - RuntimeVisibleAnnotations_attribute
* - RuntimeInvisibleAnnotations_attribute
* - RuntimeVisibleParameterAnnotations_attribute
* - RuntimeInvisibleParameterAnnotations_attribute
* - AnnotationDefault_attribute
*
* Java 6Attributes:
*
* - StackMapTable_attribute
*
* Java 7Attributes:
*
* - BootstrapMethods_attribute
*
* Java 8Attributes:
*
* - MethodParameters_attribute
* - RuntimeVisibleTypeAnnotations_attribute
* - RuntimeInvisibleTypeAnnotations_attribute
*
* Java 9Attributes:
*
* - Module_attribute
* - MainClass_attribute
* - ModulePackages_attribute
*
* Java 11Attributes:
*
* - NestHost_attribute
* - NestMembers_attribute
*
* Java 16Attributes:
*
* - Record_attribute
*
*
* The returned function is allowed to return null; in this case the attribute
* will be discarded.
*/
private[this] var attributeReaders: Map[String, (Constant_Pool, AttributeParent, Constant_Pool_Index, Constant_Pool_Index, Constant_Pool_Index, DataInputStream) ⇒ Attribute] = Map()
/**
* See `AttributeReader.registerAttributeReader` for details.
*/
def registerAttributeReader(
reader: (String, (Constant_Pool, AttributeParent, Constant_Pool_Index, Constant_Pool_Index, Constant_Pool_Index, DataInputStream) ⇒ Attribute)
): Unit = {
attributeReaders += reader
}
private[this] var attributesPostProcessors = RefArray.empty[Attributes ⇒ Attributes]
/**
* Registers a new processor for the list of all attributes of a given class file
* element (class, field, method, code). This can be used to post-process attributes.
* E.g., to merge multiple line number tables if they exist or to link
* attributes that have strong dependencies. E.g., (in Java 8) the
* `localvar_target` structure of the `Runtime(In)VisibleTypeAnnotations` attribute
* has a reference in the local variable table attribute.
*/
def registerAttributesPostProcessor(p: Attributes ⇒ Attributes): Unit = {
attributesPostProcessors :+= p
}
def Attributes(
cp: Constant_Pool,
ap: AttributeParent,
ap_name_index: Constant_Pool_Index,
ap_descriptor_index: Constant_Pool_Index,
in: DataInputStream
): Attributes = {
val attributes: Attributes =
fillRefArray(in.readUnsignedShort) {
Attribute(cp, ap, ap_name_index, ap_descriptor_index, in)
}.filterNonNull // lets remove the attributes we don't need or understand
attributesPostProcessors.foldLeft(attributes)((a, p) ⇒ p(a))
}
def Attribute(
cp: Constant_Pool,
ap: AttributeParent,
ap_name_index: Constant_Pool_Index,
ap_descriptor_index: Constant_Pool_Index,
in: DataInputStream
): Attribute = {
val attribute_name_index = in.readUnsignedShort()
val attribute_name = cp(attribute_name_index).asString
attributeReaders.getOrElse(
attribute_name,
Unknown_attribute _ // this is a factory method
)(cp, ap, ap_name_index, ap_descriptor_index, attribute_name_index, in)
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy