com.android.dx.dex.file.AnnotationsDirectoryItem Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of builder Show documentation
Show all versions of builder Show documentation
Library to build Android applications.
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.dx.dex.file;
import com.android.dx.rop.annotation.Annotations;
import com.android.dx.rop.annotation.AnnotationsList;
import com.android.dx.rop.cst.CstFieldRef;
import com.android.dx.rop.cst.CstMethodRef;
import com.android.dx.util.AnnotatedOutput;
import com.android.dx.util.Hex;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
/**
* Per-class directory of annotations.
*/
public final class AnnotationsDirectoryItem extends OffsettedItem {
/** the required alignment for instances of this class */
private static final int ALIGNMENT = 4;
/** write size of this class's header, in bytes */
private static final int HEADER_SIZE = 16;
/** write size of a list element, in bytes */
private static final int ELEMENT_SIZE = 8;
/** {@code null-ok;} the class-level annotations, if any */
private AnnotationSetItem classAnnotations;
/** {@code null-ok;} the annotated fields, if any */
private ArrayList fieldAnnotations;
/** {@code null-ok;} the annotated methods, if any */
private ArrayList methodAnnotations;
/** {@code null-ok;} the annotated parameters, if any */
private ArrayList parameterAnnotations;
/**
* Constructs an empty instance.
*/
public AnnotationsDirectoryItem() {
super(ALIGNMENT, -1);
classAnnotations = null;
fieldAnnotations = null;
methodAnnotations = null;
parameterAnnotations = null;
}
/** {@inheritDoc} */
@Override
public ItemType itemType() {
return ItemType.TYPE_ANNOTATIONS_DIRECTORY_ITEM;
}
/**
* Returns whether this item is empty (has no contents).
*
* @return {@code true} if this item is empty, or {@code false}
* if not
*/
public boolean isEmpty() {
return (classAnnotations == null) &&
(fieldAnnotations == null) &&
(methodAnnotations == null) &&
(parameterAnnotations == null);
}
/**
* Returns whether this item is a candidate for interning. The only
* interning candidates are ones that only have a non-null
* set of class annotations, with no other lists.
*
* @return {@code true} if this is an interning candidate, or
* {@code false} if not
*/
public boolean isInternable() {
return (classAnnotations != null) &&
(fieldAnnotations == null) &&
(methodAnnotations == null) &&
(parameterAnnotations == null);
}
/** {@inheritDoc} */
@Override
public int hashCode() {
if (classAnnotations == null) {
return 0;
}
return classAnnotations.hashCode();
}
/**
* {@inheritDoc}
*
* Note:: This throws an exception if this item is not
* internable.
*
* @see #isInternable
*/
@Override
public int compareTo0(OffsettedItem other) {
if (! isInternable()) {
throw new UnsupportedOperationException("uninternable instance");
}
AnnotationsDirectoryItem otherDirectory =
(AnnotationsDirectoryItem) other;
return classAnnotations.compareTo(otherDirectory.classAnnotations);
}
/**
* Sets the direct annotations on this instance. These are annotations
* made on the class, per se, as opposed to on one of its members.
* It is only valid to call this method at most once per instance.
*
* @param annotations {@code non-null;} annotations to set for this class
* @param dexFile {@code non-null;} dex output
*/
public void setClassAnnotations(Annotations annotations, DexFile dexFile) {
if (annotations == null) {
throw new NullPointerException("annotations == null");
}
if (classAnnotations != null) {
throw new UnsupportedOperationException(
"class annotations already set");
}
classAnnotations = new AnnotationSetItem(annotations, dexFile);
}
/**
* Adds a field annotations item to this instance.
*
* @param field {@code non-null;} field in question
* @param annotations {@code non-null;} associated annotations to add
* @param dexFile {@code non-null;} dex output
*/
public void addFieldAnnotations(CstFieldRef field,
Annotations annotations, DexFile dexFile) {
if (fieldAnnotations == null) {
fieldAnnotations = new ArrayList();
}
fieldAnnotations.add(new FieldAnnotationStruct(field,
new AnnotationSetItem(annotations, dexFile)));
}
/**
* Adds a method annotations item to this instance.
*
* @param method {@code non-null;} method in question
* @param annotations {@code non-null;} associated annotations to add
* @param dexFile {@code non-null;} dex output
*/
public void addMethodAnnotations(CstMethodRef method,
Annotations annotations, DexFile dexFile) {
if (methodAnnotations == null) {
methodAnnotations = new ArrayList();
}
methodAnnotations.add(new MethodAnnotationStruct(method,
new AnnotationSetItem(annotations, dexFile)));
}
/**
* Adds a parameter annotations item to this instance.
*
* @param method {@code non-null;} method in question
* @param list {@code non-null;} associated list of annotation sets to add
* @param dexFile {@code non-null;} dex output
*/
public void addParameterAnnotations(CstMethodRef method,
AnnotationsList list, DexFile dexFile) {
if (parameterAnnotations == null) {
parameterAnnotations = new ArrayList();
}
parameterAnnotations.add(new ParameterAnnotationStruct(method, list, dexFile));
}
/**
* Gets the method annotations for a given method, if any. This is
* meant for use by debugging / dumping code.
*
* @param method {@code non-null;} the method
* @return {@code null-ok;} the method annotations, if any
*/
public Annotations getMethodAnnotations(CstMethodRef method) {
if (methodAnnotations == null) {
return null;
}
for (MethodAnnotationStruct item : methodAnnotations) {
if (item.getMethod().equals(method)) {
return item.getAnnotations();
}
}
return null;
}
/**
* Gets the parameter annotations for a given method, if any. This is
* meant for use by debugging / dumping code.
*
* @param method {@code non-null;} the method
* @return {@code null-ok;} the parameter annotations, if any
*/
public AnnotationsList getParameterAnnotations(CstMethodRef method) {
if (parameterAnnotations == null) {
return null;
}
for (ParameterAnnotationStruct item : parameterAnnotations) {
if (item.getMethod().equals(method)) {
return item.getAnnotationsList();
}
}
return null;
}
/** {@inheritDoc} */
public void addContents(DexFile file) {
MixedItemSection wordData = file.getWordData();
if (classAnnotations != null) {
classAnnotations = wordData.intern(classAnnotations);
}
if (fieldAnnotations != null) {
for (FieldAnnotationStruct item : fieldAnnotations) {
item.addContents(file);
}
}
if (methodAnnotations != null) {
for (MethodAnnotationStruct item : methodAnnotations) {
item.addContents(file);
}
}
if (parameterAnnotations != null) {
for (ParameterAnnotationStruct item : parameterAnnotations) {
item.addContents(file);
}
}
}
/** {@inheritDoc} */
@Override
public String toHuman() {
throw new RuntimeException("unsupported");
}
/** {@inheritDoc} */
@Override
protected void place0(Section addedTo, int offset) {
// We just need to set the write size here.
int elementCount = listSize(fieldAnnotations)
+ listSize(methodAnnotations) + listSize(parameterAnnotations);
setWriteSize(HEADER_SIZE + (elementCount * ELEMENT_SIZE));
}
/** {@inheritDoc} */
@Override
protected void writeTo0(DexFile file, AnnotatedOutput out) {
boolean annotates = out.annotates();
int classOff = OffsettedItem.getAbsoluteOffsetOr0(classAnnotations);
int fieldsSize = listSize(fieldAnnotations);
int methodsSize = listSize(methodAnnotations);
int parametersSize = listSize(parameterAnnotations);
if (annotates) {
out.annotate(0, offsetString() + " annotations directory");
out.annotate(4, " class_annotations_off: " + Hex.u4(classOff));
out.annotate(4, " fields_size: " +
Hex.u4(fieldsSize));
out.annotate(4, " methods_size: " +
Hex.u4(methodsSize));
out.annotate(4, " parameters_size: " +
Hex.u4(parametersSize));
}
out.writeInt(classOff);
out.writeInt(fieldsSize);
out.writeInt(methodsSize);
out.writeInt(parametersSize);
if (fieldsSize != 0) {
Collections.sort(fieldAnnotations);
if (annotates) {
out.annotate(0, " fields:");
}
for (FieldAnnotationStruct item : fieldAnnotations) {
item.writeTo(file, out);
}
}
if (methodsSize != 0) {
Collections.sort(methodAnnotations);
if (annotates) {
out.annotate(0, " methods:");
}
for (MethodAnnotationStruct item : methodAnnotations) {
item.writeTo(file, out);
}
}
if (parametersSize != 0) {
Collections.sort(parameterAnnotations);
if (annotates) {
out.annotate(0, " parameters:");
}
for (ParameterAnnotationStruct item : parameterAnnotations) {
item.writeTo(file, out);
}
}
}
/**
* Gets the list size of the given list, or {@code 0} if given
* {@code null}.
*
* @param list {@code null-ok;} the list in question
* @return {@code >= 0;} its size
*/
private static int listSize(ArrayList> list) {
if (list == null) {
return 0;
}
return list.size();
}
/**
* Prints out the contents of this instance, in a debugging-friendly
* way. This is meant to be called from {@link ClassDefItem#debugPrint}.
*
* @param out {@code non-null;} where to output to
*/
/*package*/ void debugPrint(PrintWriter out) {
if (classAnnotations != null) {
out.println(" class annotations: " + classAnnotations);
}
if (fieldAnnotations != null) {
out.println(" field annotations:");
for (FieldAnnotationStruct item : fieldAnnotations) {
out.println(" " + item.toHuman());
}
}
if (methodAnnotations != null) {
out.println(" method annotations:");
for (MethodAnnotationStruct item : methodAnnotations) {
out.println(" " + item.toHuman());
}
}
if (parameterAnnotations != null) {
out.println(" parameter annotations:");
for (ParameterAnnotationStruct item : parameterAnnotations) {
out.println(" " + item.toHuman());
}
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy