DexPool.java revision edd961477ec83d9f320bc65c5ca97572fceaccc5
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.writer.DexWriter; 42import org.jf.dexlib2.writer.io.FileDataStore; 43import org.jf.dexlib2.writer.pool.ProtoPool.Key; 44import org.jf.util.ExceptionWithContext; 45 46import javax.annotation.Nonnull; 47import java.io.File; 48import java.io.IOException; 49import java.util.Collection; 50import java.util.Set; 51 52public class DexPool extends DexWriter<CharSequence, StringReference, CharSequence, TypeReference, Key, 53 FieldReference, MethodReference, PoolClassDef, 54 Annotation, Set<? extends Annotation>, 55 TypeListPool.Key<? extends Collection<? extends CharSequence>>, Field, PoolMethod, 56 EncodedValue, AnnotationElement> { 57 58 public static DexPool makeDexPool() { 59 return makeDexPool(15); 60 } 61 62 public static DexPool makeDexPool(int api) { 63 StringPool stringPool = new StringPool(); 64 TypePool typePool = new TypePool(stringPool); 65 FieldPool fieldPool = new FieldPool(stringPool, typePool); 66 TypeListPool typeListPool = new TypeListPool(typePool); 67 ProtoPool protoPool = new ProtoPool(stringPool, typePool, typeListPool); 68 MethodPool methodPool = new MethodPool(stringPool, typePool, protoPool); 69 AnnotationPool annotationPool = new AnnotationPool(stringPool, typePool, fieldPool, methodPool); 70 AnnotationSetPool annotationSetPool = new AnnotationSetPool(annotationPool); 71 ClassPool classPool = new ClassPool(stringPool, typePool, fieldPool, methodPool, annotationSetPool, 72 typeListPool); 73 74 return new DexPool(api, stringPool, typePool, protoPool, fieldPool, methodPool, classPool, typeListPool, 75 annotationPool, annotationSetPool); 76 } 77 78 private DexPool(int api, StringPool stringPool, TypePool typePool, ProtoPool protoPool, FieldPool fieldPool, 79 MethodPool methodPool, ClassPool classPool, TypeListPool typeListPool, 80 AnnotationPool annotationPool, AnnotationSetPool annotationSetPool) { 81 super(api, stringPool, typePool, protoPool, fieldPool, methodPool, 82 classPool, typeListPool, annotationPool, annotationSetPool); 83 } 84 85 public static void writeTo(@Nonnull String path, @Nonnull org.jf.dexlib2.iface.DexFile input) throws IOException { 86 DexPool dexPool = makeDexPool(); 87 for (ClassDef classDef: input.getClasses()) { 88 ((ClassPool)dexPool.classSection).intern(classDef); 89 } 90 dexPool.writeTo(new FileDataStore(new File(path))); 91 } 92 93 @Override protected void writeEncodedValue(@Nonnull InternalEncodedValueWriter writer, 94 @Nonnull EncodedValue encodedValue) throws IOException { 95 switch (encodedValue.getValueType()) { 96 case ValueType.ANNOTATION: 97 AnnotationEncodedValue annotationEncodedValue = (AnnotationEncodedValue)encodedValue; 98 writer.writeAnnotation(annotationEncodedValue.getType(), annotationEncodedValue.getElements()); 99 break; 100 case ValueType.ARRAY: 101 ArrayEncodedValue arrayEncodedValue = (ArrayEncodedValue)encodedValue; 102 writer.writeArray(arrayEncodedValue.getValue()); 103 break; 104 case ValueType.BOOLEAN: 105 writer.writeBoolean(((BooleanEncodedValue)encodedValue).getValue()); 106 break; 107 case ValueType.BYTE: 108 writer.writeByte(((ByteEncodedValue)encodedValue).getValue()); 109 break; 110 case ValueType.CHAR: 111 writer.writeChar(((CharEncodedValue)encodedValue).getValue()); 112 break; 113 case ValueType.DOUBLE: 114 writer.writeDouble(((DoubleEncodedValue)encodedValue).getValue()); 115 break; 116 case ValueType.ENUM: 117 writer.writeEnum(((EnumEncodedValue)encodedValue).getValue()); 118 break; 119 case ValueType.FIELD: 120 writer.writeField(((FieldEncodedValue)encodedValue).getValue()); 121 break; 122 case ValueType.FLOAT: 123 writer.writeFloat(((FloatEncodedValue)encodedValue).getValue()); 124 break; 125 case ValueType.INT: 126 writer.writeInt(((IntEncodedValue)encodedValue).getValue()); 127 break; 128 case ValueType.LONG: 129 writer.writeLong(((LongEncodedValue)encodedValue).getValue()); 130 break; 131 case ValueType.METHOD: 132 writer.writeMethod(((MethodEncodedValue)encodedValue).getValue()); 133 break; 134 case ValueType.NULL: 135 writer.writeNull(); 136 break; 137 case ValueType.SHORT: 138 writer.writeShort(((ShortEncodedValue)encodedValue).getValue()); 139 break; 140 case ValueType.STRING: 141 writer.writeString(((StringEncodedValue)encodedValue).getValue()); 142 break; 143 case ValueType.TYPE: 144 writer.writeType(((TypeEncodedValue)encodedValue).getValue()); 145 break; 146 default: 147 throw new ExceptionWithContext("Unrecognized value type: %d", encodedValue.getValueType()); 148 } 149 } 150 151 public static void internEncodedValue(@Nonnull EncodedValue encodedValue, 152 @Nonnull StringPool stringPool, 153 @Nonnull TypePool typePool, 154 @Nonnull FieldPool fieldPool, 155 @Nonnull MethodPool methodPool) { 156 switch (encodedValue.getValueType()) { 157 case ValueType.ANNOTATION: 158 AnnotationEncodedValue annotationEncodedValue = (AnnotationEncodedValue)encodedValue; 159 typePool.intern(annotationEncodedValue.getType()); 160 for (AnnotationElement element: annotationEncodedValue.getElements()) { 161 stringPool.intern(element.getName()); 162 internEncodedValue(element.getValue(), stringPool, typePool, fieldPool, methodPool); 163 } 164 break; 165 case ValueType.ARRAY: 166 for (EncodedValue element: ((ArrayEncodedValue)encodedValue).getValue()) { 167 internEncodedValue(element, stringPool, typePool, fieldPool, methodPool); 168 } 169 break; 170 case ValueType.STRING: 171 stringPool.intern(((StringEncodedValue)encodedValue).getValue()); 172 break; 173 case ValueType.TYPE: 174 typePool.intern(((TypeEncodedValue)encodedValue).getValue()); 175 break; 176 case ValueType.ENUM: 177 fieldPool.intern(((EnumEncodedValue)encodedValue).getValue()); 178 break; 179 case ValueType.FIELD: 180 fieldPool.intern(((FieldEncodedValue)encodedValue).getValue()); 181 break; 182 case ValueType.METHOD: 183 methodPool.intern(((MethodEncodedValue)encodedValue).getValue()); 184 break; 185 } 186 } 187} 188