• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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