DexPool.java revision 99b46173c5294d186ccf2e647b86346a22b247c8
1/* 2 * Copyright 2013, Google Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following disclaimer 13 * in the documentation and/or other materials provided with the 14 * distribution. 15 * * Neither the name of Google Inc. nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32package org.jf.dexlib2.writer.pool; 33 34import org.jf.dexlib2.ValueType; 35import org.jf.dexlib2.iface.Annotation; 36import org.jf.dexlib2.iface.AnnotationElement; 37import org.jf.dexlib2.iface.ClassDef; 38import org.jf.dexlib2.iface.Field; 39import org.jf.dexlib2.iface.reference.*; 40import org.jf.dexlib2.iface.value.*; 41import org.jf.dexlib2.immutable.instruction.ImmutableInstructionFactory; 42import org.jf.dexlib2.writer.DexWriter; 43import org.jf.dexlib2.writer.io.FileDataStore; 44import org.jf.dexlib2.writer.pool.ProtoPool.Key; 45import org.jf.util.ExceptionWithContext; 46 47import javax.annotation.Nonnull; 48import java.io.File; 49import java.io.IOException; 50import java.util.Collection; 51import java.util.Set; 52 53public class DexPool extends DexWriter<CharSequence, StringReference, CharSequence, TypeReference, Key, 54 FieldReference, MethodReference, Reference, PoolClassDef, 55 Annotation, Set<? extends Annotation>, 56 TypeListPool.Key<? extends Collection<? extends CharSequence>>, Field, PoolMethod, 57 EncodedValue, AnnotationElement> { 58 59 public static DexPool makeDexPool() { 60 return makeDexPool(15); 61 } 62 63 public static DexPool makeDexPool(int api) { 64 StringPool stringPool = new StringPool(); 65 TypePool typePool = new TypePool(stringPool); 66 FieldPool fieldPool = new FieldPool(stringPool, typePool); 67 TypeListPool typeListPool = new TypeListPool(typePool); 68 ProtoPool protoPool = new ProtoPool(stringPool, typePool, typeListPool); 69 MethodPool methodPool = new MethodPool(stringPool, typePool, protoPool); 70 AnnotationPool annotationPool = new AnnotationPool(stringPool, typePool, fieldPool, methodPool); 71 AnnotationSetPool annotationSetPool = new AnnotationSetPool(annotationPool); 72 ClassPool classPool = new ClassPool(stringPool, typePool, fieldPool, methodPool, annotationSetPool, 73 typeListPool); 74 75 return new DexPool(api, stringPool, typePool, protoPool, fieldPool, methodPool, classPool, typeListPool, 76 annotationPool, annotationSetPool); 77 } 78 79 private DexPool(int api, StringPool stringPool, TypePool typePool, ProtoPool protoPool, FieldPool fieldPool, 80 MethodPool methodPool, ClassPool classPool, TypeListPool typeListPool, 81 AnnotationPool annotationPool, AnnotationSetPool annotationSetPool) { 82 super(api, ImmutableInstructionFactory.INSTANCE, stringPool, typePool, protoPool, fieldPool, methodPool, 83 classPool, typeListPool, annotationPool, annotationSetPool); 84 } 85 86 public static void writeTo(@Nonnull String path, @Nonnull org.jf.dexlib2.iface.DexFile input) throws IOException { 87 DexPool dexPool = makeDexPool(); 88 for (ClassDef classDef: input.getClasses()) { 89 ((ClassPool)dexPool.classSection).intern(classDef); 90 } 91 dexPool.writeTo(new FileDataStore(new File(path))); 92 } 93 94 @Override protected void writeEncodedValue(@Nonnull InternalEncodedValueWriter writer, 95 @Nonnull EncodedValue encodedValue) throws IOException { 96 switch (encodedValue.getValueType()) { 97 case ValueType.ANNOTATION: 98 AnnotationEncodedValue annotationEncodedValue = (AnnotationEncodedValue)encodedValue; 99 writer.writeAnnotation(annotationEncodedValue.getType(), annotationEncodedValue.getElements()); 100 break; 101 case ValueType.ARRAY: 102 ArrayEncodedValue arrayEncodedValue = (ArrayEncodedValue)encodedValue; 103 writer.writeArray(arrayEncodedValue.getValue()); 104 break; 105 case ValueType.BOOLEAN: 106 writer.writeBoolean(((BooleanEncodedValue)encodedValue).getValue()); 107 break; 108 case ValueType.BYTE: 109 writer.writeByte(((ByteEncodedValue)encodedValue).getValue()); 110 break; 111 case ValueType.CHAR: 112 writer.writeChar(((CharEncodedValue)encodedValue).getValue()); 113 break; 114 case ValueType.DOUBLE: 115 writer.writeDouble(((DoubleEncodedValue)encodedValue).getValue()); 116 break; 117 case ValueType.ENUM: 118 writer.writeEnum(((EnumEncodedValue)encodedValue).getValue()); 119 break; 120 case ValueType.FIELD: 121 writer.writeField(((FieldEncodedValue)encodedValue).getValue()); 122 break; 123 case ValueType.FLOAT: 124 writer.writeFloat(((FloatEncodedValue)encodedValue).getValue()); 125 break; 126 case ValueType.INT: 127 writer.writeInt(((IntEncodedValue)encodedValue).getValue()); 128 break; 129 case ValueType.LONG: 130 writer.writeLong(((LongEncodedValue)encodedValue).getValue()); 131 break; 132 case ValueType.METHOD: 133 writer.writeMethod(((MethodEncodedValue)encodedValue).getValue()); 134 break; 135 case ValueType.NULL: 136 writer.writeNull(); 137 break; 138 case ValueType.SHORT: 139 writer.writeShort(((ShortEncodedValue)encodedValue).getValue()); 140 break; 141 case ValueType.STRING: 142 writer.writeString(((StringEncodedValue)encodedValue).getValue()); 143 break; 144 case ValueType.TYPE: 145 writer.writeType(((TypeEncodedValue)encodedValue).getValue()); 146 break; 147 default: 148 throw new ExceptionWithContext("Unrecognized value type: %d", encodedValue.getValueType()); 149 } 150 } 151 152 public static void internEncodedValue(@Nonnull EncodedValue encodedValue, 153 @Nonnull StringPool stringPool, 154 @Nonnull TypePool typePool, 155 @Nonnull FieldPool fieldPool, 156 @Nonnull MethodPool methodPool) { 157 switch (encodedValue.getValueType()) { 158 case ValueType.ANNOTATION: 159 AnnotationEncodedValue annotationEncodedValue = (AnnotationEncodedValue)encodedValue; 160 typePool.intern(annotationEncodedValue.getType()); 161 for (AnnotationElement element: annotationEncodedValue.getElements()) { 162 stringPool.intern(element.getName()); 163 internEncodedValue(element.getValue(), stringPool, typePool, fieldPool, methodPool); 164 } 165 break; 166 case ValueType.ARRAY: 167 for (EncodedValue element: ((ArrayEncodedValue)encodedValue).getValue()) { 168 internEncodedValue(element, stringPool, typePool, fieldPool, methodPool); 169 } 170 break; 171 case ValueType.STRING: 172 stringPool.intern(((StringEncodedValue)encodedValue).getValue()); 173 break; 174 case ValueType.TYPE: 175 typePool.intern(((TypeEncodedValue)encodedValue).getValue()); 176 break; 177 case ValueType.ENUM: 178 fieldPool.intern(((EnumEncodedValue)encodedValue).getValue()); 179 break; 180 case ValueType.FIELD: 181 fieldPool.intern(((FieldEncodedValue)encodedValue).getValue()); 182 break; 183 case ValueType.METHOD: 184 methodPool.intern(((MethodEncodedValue)encodedValue).getValue()); 185 break; 186 } 187 } 188} 189