1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.dx.dex.file; 18 19 import com.android.dx.rop.annotation.Annotations; 20 import com.android.dx.rop.annotation.Annotation; 21 import com.android.dx.util.AnnotatedOutput; 22 import com.android.dx.util.Hex; 23 24 /** 25 * Set of annotations, where no annotation type appears more than once. 26 */ 27 public final class AnnotationSetItem extends OffsettedItem { 28 /** the required alignment for instances of this class */ 29 private static final int ALIGNMENT = 4; 30 31 /** the size of an entry int the set: one {@code uint} */ 32 private static final int ENTRY_WRITE_SIZE = 4; 33 34 /** {@code non-null;} the set of annotations */ 35 private final Annotations annotations; 36 37 /** 38 * {@code non-null;} set of annotations as individual items in an array. 39 * <b>Note:</b> The contents have to get sorted by type id before 40 * writing. 41 */ 42 private final AnnotationItem[] items; 43 44 /** 45 * Constructs an instance. 46 * 47 * @param annotations {@code non-null;} set of annotations 48 */ AnnotationSetItem(Annotations annotations)49 public AnnotationSetItem(Annotations annotations) { 50 super(ALIGNMENT, writeSize(annotations)); 51 52 this.annotations = annotations; 53 this.items = new AnnotationItem[annotations.size()]; 54 55 int at = 0; 56 for (Annotation a : annotations.getAnnotations()) { 57 items[at] = new AnnotationItem(a); 58 at++; 59 } 60 } 61 62 /** 63 * Gets the write size for the given set. 64 * 65 * @param annotations {@code non-null;} the set 66 * @return {@code > 0;} the write size 67 */ writeSize(Annotations annotations)68 private static int writeSize(Annotations annotations) { 69 // This includes an int size at the start of the list. 70 71 try { 72 return (annotations.size() * ENTRY_WRITE_SIZE) + 4; 73 } catch (NullPointerException ex) { 74 // Elucidate the exception. 75 throw new NullPointerException("list == null"); 76 } 77 } 78 79 /** 80 * Gets the underlying annotations of this instance 81 * 82 * @return {@code non-null;} the annotations 83 */ getAnnotations()84 public Annotations getAnnotations() { 85 return annotations; 86 } 87 88 /** {@inheritDoc} */ 89 @Override hashCode()90 public int hashCode() { 91 return annotations.hashCode(); 92 } 93 94 /** {@inheritDoc} */ 95 @Override compareTo0(OffsettedItem other)96 protected int compareTo0(OffsettedItem other) { 97 AnnotationSetItem otherSet = (AnnotationSetItem) other; 98 99 return annotations.compareTo(otherSet.annotations); 100 } 101 102 /** {@inheritDoc} */ 103 @Override itemType()104 public ItemType itemType() { 105 return ItemType.TYPE_ANNOTATION_SET_ITEM; 106 } 107 108 /** {@inheritDoc} */ 109 @Override toHuman()110 public String toHuman() { 111 return annotations.toString(); 112 } 113 114 /** {@inheritDoc} */ addContents(DexFile file)115 public void addContents(DexFile file) { 116 MixedItemSection byteData = file.getByteData(); 117 int size = items.length; 118 119 for (int i = 0; i < size; i++) { 120 items[i] = byteData.intern(items[i]); 121 } 122 } 123 124 /** {@inheritDoc} */ 125 @Override place0(Section addedTo, int offset)126 protected void place0(Section addedTo, int offset) { 127 // Sort the array to be in type id index order. 128 AnnotationItem.sortByTypeIdIndex(items); 129 } 130 131 /** {@inheritDoc} */ 132 @Override writeTo0(DexFile file, AnnotatedOutput out)133 protected void writeTo0(DexFile file, AnnotatedOutput out) { 134 boolean annotates = out.annotates(); 135 int size = items.length; 136 137 if (annotates) { 138 out.annotate(0, offsetString() + " annotation set"); 139 out.annotate(4, " size: " + Hex.u4(size)); 140 } 141 142 out.writeInt(size); 143 144 for (int i = 0; i < size; i++) { 145 AnnotationItem item = items[i]; 146 int offset = item.getAbsoluteOffset(); 147 148 if (annotates) { 149 out.annotate(4, " entries[" + Integer.toHexString(i) + "]: " + 150 Hex.u4(offset)); 151 items[i].annotateTo(out, " "); 152 } 153 154 out.writeInt(offset); 155 } 156 } 157 } 158