Item.java revision d8b31a17aee6519c2086ccac3e11f7cd40cba9c1
1/*
2 * [The "BSD licence"]
3 * Copyright (c) 2009 Ben Gruver
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 *    derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29package org.jf.dexlib;
30
31import org.jf.dexlib.Util.AnnotatedOutput;
32import org.jf.dexlib.Util.Input;
33import org.jf.dexlib.Util.AlignmentUtils;
34
35public abstract class Item<T extends Item> implements Comparable<T> {
36    /**
37     * The offset of this item in the dex file, or -1 if not known
38     */
39    private int offset = -1;
40
41    /**
42     * The index of this item in the containing section, or -1 if not known
43     */
44    private int index = -1;
45
46    /**
47     * The DexFile that this item is associatedr with
48     */
49    protected final DexFile dexFile;
50
51    /**
52     * The constructor that is used when reading in a <code>DexFile</code>
53     * @param dexFile the <code>DexFile</code> that this item is associated with
54     */
55    protected Item(DexFile dexFile) {
56        this.dexFile = dexFile;
57    }
58
59    /**
60     * Read in the item from the given input stream, and initialize the index
61     * @param in the <code>Input</code> object to read from
62     * @param index the index within the containing section of the item being read in
63     * @param readContext a <code>ReadContext</code> object to hold information that is
64     * only needed while reading in a file
65     */
66    protected void readFrom(Input in, int index, ReadContext readContext) {
67        assert in.getCursor() % getItemType().ItemAlignment == 0:"The Input cursor is not aligned";
68
69        this.offset = in.getCursor();
70        this.index = index;
71        this.readItem(in, readContext);
72    }
73
74    /**
75     * Place the item at the given offset and index, and return the offset of the byte following this item
76     * @param offset The offset to place the item at
77     * @param index The index of the item within the containing section
78     * @return The offset of the byte following this item
79     */
80    protected int placeAt(int offset, int index) {
81        assert offset % getItemType().ItemAlignment == 0;
82        assert !dexFile.getInplace() || (offset == this.offset && this.index == index);
83
84        this.offset = offset;
85        this.index = index;
86        return this.placeItem(offset);
87    }
88
89    /**
90     * Write and annotate this item to the output stream
91     * @param out The output stream to write and annotate to
92     */
93    protected void writeTo(AnnotatedOutput out) {
94        assert out.getCursor() % getItemType().ItemAlignment == 0;
95        assert out.getCursor() == offset;
96
97        if (out.annotates()) {
98            out.annotate(0, "[0x" + Integer.toHexString(index) + "] " + this.getItemType().TypeName);
99        }
100
101        out.indent();
102        writeItem(out);
103        out.deindent();
104    }
105
106    /**
107     * Returns a human readable form of this item
108     * @return a human readable form of this item
109     */
110    public String toString() {
111        return getConciseIdentity();
112    }
113
114    /**
115     * The method in the concrete item subclass that actually reads in the data for the item
116     *
117     * The logic in this method can assume that the given Input object is valid and is
118     * aligned as neccessary.
119     *
120     * This method is for internal use only
121     * @param in the <code>Input</code> object to read from
122     * @param readContext a <code>ReadContext</code> object to hold information that is
123     * only needed while reading in a file
124     */
125    protected abstract void readItem(Input in, ReadContext readContext);
126
127    /**
128     * The method should finalize the layout of the item and return the offset of the byte
129     * immediately following the item.
130     *
131     * The implementation of this method can assume that the offset argument has already been
132     * aligned based on the item's alignment requirements
133     *
134     * This method is for internal use only
135     * @param offset the (pre-aligned) offset to place the item at
136     * @return the size of the item, in bytes
137     */
138    protected abstract int placeItem(int offset);
139
140    /**
141     * The method in the concrete item subclass that actually writes and annotates the data
142     * for the item.
143     *
144     * The logic in this method can assume that the given Output object is valid and is
145     * aligned as neccessary
146     *
147     * @param out The <code>AnnotatedOutput</code> object to write/annotate to
148     */
149    protected abstract void writeItem(AnnotatedOutput out);
150
151    /**
152     * @return An ItemType enum that represents the item type of this item
153     */
154    public abstract ItemType getItemType();
155
156    /**
157     * @return A concise (human-readable) string value that conveys the identity of this item
158     */
159    public abstract String getConciseIdentity();
160
161
162    /**
163     * @return the offset in the dex file where this item is located
164     */
165    public int getOffset() {
166        return offset;
167    }
168
169    /**
170     * @return the index of this item within the item's containing section
171     */
172    public int getIndex() {
173        return index;
174    }
175
176    /**
177     * @return the <code>DexFile</code> that contains this item
178     */
179    public DexFile getDexFile() {
180        return dexFile;
181    }
182}
183