1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage com.android.dx.cf.direct;
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.attrib.RawAttribute;
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.iface.Attribute;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.iface.ParseException;
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.iface.ParseObserver;
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.ConstantPool;
24333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilsonimport com.android.dx.rop.cst.CstString;
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.ByteArray;
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.Hex;
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Factory capable of instantiating various {@link Attribute} subclasses
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * depending on the context and name.
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class AttributeFactory {
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** context for attributes on class files */
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static final int CTX_CLASS = 0;
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** context for attributes on fields */
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static final int CTX_FIELD = 1;
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** context for attributes on methods */
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static final int CTX_METHOD = 2;
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** context for attributes on code attributes */
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static final int CTX_CODE = 3;
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** number of contexts */
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static final int CTX_COUNT = 4;
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs an instance.
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public AttributeFactory() {
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // This space intentionally left blank.
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Parses and makes an attribute based on the bytes at the
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * indicated position in the given array. This method figures out
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the name, and then does all the setup to call on to {@link #parse0},
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * which does the actual construction.
60de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
6199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param cf {@code non-null;} class file to parse from
6299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param context context to parse in; one of the {@code CTX_*}
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * constants
6499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param offset offset into {@code dcf}'s {@code bytes}
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * to start parsing at
6699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param observer {@code null-ok;} parse observer to report to, if any
6799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} an appropriately-constructed {@link Attribute}
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final Attribute parse(DirectClassFile cf, int context, int offset,
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                 ParseObserver observer) {
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (cf == null) {
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("cf == null");
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((context < 0) || (context >= CTX_COUNT)) {
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("bad context");
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
79333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson        CstString name = null;
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ByteArray bytes = cf.getBytes();
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ConstantPool pool = cf.getConstantPool();
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int nameIdx = bytes.getUnsignedShort(offset);
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int length = bytes.getInt(offset + 2);
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
87333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson            name = (CstString) pool.get(nameIdx);
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (observer != null) {
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                observer.parsed(bytes, offset, 2,
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                "name: " + name.toHuman());
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                observer.parsed(bytes, offset + 2, 4,
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                "length: " + Hex.u4(length));
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return parse0(cf, context, name.getString(), offset + 6, length,
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                          observer);
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (ParseException ex) {
99de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro            ex.addContext("...while parsing " +
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    ((name != null) ? (name.toHuman() + " ") : "") +
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "attribute at offset " + Hex.u4(offset));
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw ex;
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Parses attribute content. The base class implements this by constructing
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * an instance of {@link RawAttribute}. Subclasses are expected to
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * override this to do something better in most cases.
110de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
11199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param cf {@code non-null;} class file to parse from
11299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param context context to parse in; one of the {@code CTX_*}
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * constants
11499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param name {@code non-null;} the attribute name
11599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param offset offset into {@code bytes} to start parsing at; this
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * is the offset to the start of attribute data, not to the header
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param length the length of the attribute data
11899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param observer {@code null-ok;} parse observer to report to, if any
11999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} an appropriately-constructed {@link Attribute}
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected Attribute parse0(DirectClassFile cf, int context, String name,
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                               int offset, int length,
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                               ParseObserver observer) {
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ByteArray bytes = cf.getBytes();
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ConstantPool pool = cf.getConstantPool();
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Attribute result = new RawAttribute(name, bytes, offset, length, pool);
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (observer != null) {
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            observer.parsed(bytes, offset, length, "attribute data");
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return result;
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
135