1917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/*
2917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Copyright (C) 2008 The Android Open Source Project
3917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
4917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Licensed under the Apache License, Version 2.0 (the "License");
5917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * you may not use this file except in compliance with the License.
6917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * You may obtain a copy of the License at
7917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
8917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *      http://www.apache.org/licenses/LICENSE-2.0
9917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
10917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Unless required by applicable law or agreed to in writing, software
11917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * distributed under the License is distributed on an "AS IS" BASIS,
12917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * See the License for the specific language governing permissions and
14917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * limitations under the License.
15917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */
16917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
17917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpackage com.android.dexgen.dex.file;
18917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
19917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.annotation.Annotation;
20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.annotation.Annotations;
21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.AnnotatedOutput;
22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.Hex;
23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/**
25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Set of annotations, where no annotation type appears more than once.
26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */
27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class AnnotationSetItem extends OffsettedItem {
28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** the required alignment for instances of this class */
29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static final int ALIGNMENT = 4;
30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** the size of an entry int the set: one {@code uint} */
32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static final int ENTRY_WRITE_SIZE = 4;
33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code non-null;} the set of annotations */
35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final Annotations annotations;
36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@code non-null;} set of annotations as individual items in an array.
39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * <b>Note:</b> The contents have to get sorted by type id before
40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * writing.
41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final AnnotationItem[] items;
43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Constructs an instance.
46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param annotations {@code non-null;} set of annotations
48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public AnnotationSetItem(Annotations annotations) {
50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        super(ALIGNMENT, writeSize(annotations));
51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.annotations = annotations;
53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.items = new AnnotationItem[annotations.size()];
54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int at = 0;
56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (Annotation a : annotations.getAnnotations()) {
57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            items[at] = new AnnotationItem(a);
58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            at++;
59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the write size for the given set.
64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param annotations {@code non-null;} the set
66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code > 0;} the write size
67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static int writeSize(Annotations annotations) {
69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        // This includes an int size at the start of the list.
70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        try {
72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return (annotations.size() * ENTRY_WRITE_SIZE) + 4;
73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } catch (NullPointerException ex) {
74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            // Elucidate the exception.
75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new NullPointerException("list == null");
76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the underlying annotations of this instance
81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} the annotations
83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public Annotations getAnnotations() {
85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return annotations;
86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public int hashCode() {
91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return annotations.hashCode();
92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    protected int compareTo0(OffsettedItem other) {
97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        AnnotationSetItem otherSet = (AnnotationSetItem) other;
98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return annotations.compareTo(otherSet.annotations);
100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public ItemType itemType() {
105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return ItemType.TYPE_ANNOTATION_SET_ITEM;
106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public String toHuman() {
111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return annotations.toString();
112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public void addContents(DexFile file) {
116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        MixedItemSection byteData = file.getByteData();
117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int size = items.length;
118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < size; i++) {
120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            items[i] = byteData.intern(items[i]);
121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    protected void place0(Section addedTo, int offset) {
127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        // Sort the array to be in type id index order.
128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        AnnotationItem.sortByTypeIdIndex(items);
129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    protected void writeTo0(DexFile file, AnnotatedOutput out) {
134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        boolean annotates = out.annotates();
135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int size = items.length;
136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (annotates) {
138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.annotate(0, offsetString() + " annotation set");
139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.annotate(4, "  size: " + Hex.u4(size));
140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        out.writeInt(size);
143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < size; i++) {
145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            AnnotationItem item = items[i];
146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            int offset = item.getAbsoluteOffset();
147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (annotates) {
149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                out.annotate(4, "  entries[" + Integer.toHexString(i) + "]: " +
150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                        Hex.u4(offset));
151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                items[i].annotateTo(out, "    ");
152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.writeInt(offset);
155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul}
158