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