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.builder; 33 34import com.google.common.base.Function; 35import com.google.common.collect.ImmutableList; 36import com.google.common.collect.ImmutableSet; 37import com.google.common.collect.Iterators; 38import org.jf.dexlib2.ValueType; 39import org.jf.dexlib2.iface.AnnotationElement; 40import org.jf.dexlib2.iface.value.*; 41import org.jf.dexlib2.writer.builder.BuilderEncodedValues.*; 42import org.jf.util.ExceptionWithContext; 43 44import javax.annotation.Nonnull; 45import javax.annotation.Nullable; 46import java.util.Set; 47 48class BuilderContext { 49 // keep our own local references to the various pools, using the Builder specific pool type; 50 @Nonnull final BuilderStringPool stringPool; 51 @Nonnull final BuilderTypePool typePool; 52 @Nonnull final BuilderFieldPool fieldPool; 53 @Nonnull final BuilderMethodPool methodPool; 54 @Nonnull final BuilderProtoPool protoPool; 55 @Nonnull final BuilderClassPool classPool; 56 57 @Nonnull final BuilderTypeListPool typeListPool; 58 @Nonnull final BuilderAnnotationPool annotationPool; 59 @Nonnull final BuilderAnnotationSetPool annotationSetPool; 60 61 62 BuilderContext() { 63 this.stringPool = new BuilderStringPool(); 64 this.typePool = new BuilderTypePool(this); 65 this.fieldPool = new BuilderFieldPool(this); 66 this.methodPool = new BuilderMethodPool(this); 67 this.protoPool = new BuilderProtoPool(this); 68 this.classPool = new BuilderClassPool(); 69 70 this.typeListPool = new BuilderTypeListPool(this); 71 this.annotationPool = new BuilderAnnotationPool(this); 72 this.annotationSetPool = new BuilderAnnotationSetPool(this); 73 } 74 75 @Nonnull Set<? extends BuilderAnnotationElement> internAnnotationElements( 76 @Nonnull Set<? extends AnnotationElement> elements) { 77 return ImmutableSet.copyOf( 78 Iterators.transform(elements.iterator(), 79 new Function<AnnotationElement, BuilderAnnotationElement>() { 80 @Nullable @Override 81 public BuilderAnnotationElement apply(AnnotationElement input) { 82 return internAnnotationElement(input); 83 } 84 })); 85 } 86 87 @Nonnull private BuilderAnnotationElement internAnnotationElement(@Nonnull AnnotationElement annotationElement) { 88 return new BuilderAnnotationElement(stringPool.internString(annotationElement.getName()), 89 internEncodedValue(annotationElement.getValue())); 90 } 91 92 @Nullable BuilderEncodedValue internNullableEncodedValue(@Nullable EncodedValue encodedValue) { 93 if (encodedValue == null) { 94 return null; 95 } 96 return internEncodedValue(encodedValue); 97 } 98 99 @Nonnull private BuilderEncodedValue internEncodedValue(@Nonnull EncodedValue encodedValue) { 100 switch (encodedValue.getValueType()) { 101 case ValueType.ANNOTATION: 102 return internAnnotationEncodedValue((AnnotationEncodedValue)encodedValue); 103 case ValueType.ARRAY: 104 return internArrayEncodedValue((ArrayEncodedValue)encodedValue); 105 case ValueType.BOOLEAN: 106 boolean value = ((BooleanEncodedValue)encodedValue).getValue(); 107 return value?BuilderBooleanEncodedValue.TRUE_VALUE:BuilderBooleanEncodedValue.FALSE_VALUE; 108 case ValueType.BYTE: 109 return new BuilderByteEncodedValue(((ByteEncodedValue)encodedValue).getValue()); 110 case ValueType.CHAR: 111 return new BuilderCharEncodedValue(((CharEncodedValue)encodedValue).getValue()); 112 case ValueType.DOUBLE: 113 return new BuilderDoubleEncodedValue(((DoubleEncodedValue)encodedValue).getValue()); 114 case ValueType.ENUM: 115 return internEnumEncodedValue((EnumEncodedValue)encodedValue); 116 case ValueType.FIELD: 117 return internFieldEncodedValue((FieldEncodedValue)encodedValue); 118 case ValueType.FLOAT: 119 return new BuilderFloatEncodedValue(((FloatEncodedValue)encodedValue).getValue()); 120 case ValueType.INT: 121 return new BuilderIntEncodedValue(((IntEncodedValue)encodedValue).getValue()); 122 case ValueType.LONG: 123 return new BuilderLongEncodedValue(((LongEncodedValue)encodedValue).getValue()); 124 case ValueType.METHOD: 125 return internMethodEncodedValue((MethodEncodedValue)encodedValue); 126 case ValueType.NULL: 127 return BuilderNullEncodedValue.INSTANCE; 128 case ValueType.SHORT: 129 return new BuilderShortEncodedValue(((ShortEncodedValue)encodedValue).getValue()); 130 case ValueType.STRING: 131 return internStringEncodedValue((StringEncodedValue)encodedValue); 132 case ValueType.TYPE: 133 return internTypeEncodedValue((TypeEncodedValue)encodedValue); 134 default: 135 throw new ExceptionWithContext("Unexpected encoded value type: %d", encodedValue.getValueType()); 136 } 137 } 138 139 @Nonnull private BuilderAnnotationEncodedValue internAnnotationEncodedValue(@Nonnull AnnotationEncodedValue value) { 140 return new BuilderAnnotationEncodedValue( 141 typePool.internType(value.getType()), 142 internAnnotationElements(value.getElements())); 143 } 144 145 @Nonnull private BuilderArrayEncodedValue internArrayEncodedValue(@Nonnull ArrayEncodedValue value) { 146 return new BuilderArrayEncodedValue( 147 ImmutableList.copyOf( 148 Iterators.transform(value.getValue().iterator(), 149 new Function<EncodedValue, BuilderEncodedValue>() { 150 @Nullable @Override public BuilderEncodedValue apply(EncodedValue input) { 151 return internEncodedValue(input); 152 } 153 }))); 154 } 155 156 @Nonnull private BuilderEnumEncodedValue internEnumEncodedValue(@Nonnull EnumEncodedValue value) { 157 return new BuilderEnumEncodedValue(fieldPool.internField(value.getValue())); 158 } 159 160 @Nonnull private BuilderFieldEncodedValue internFieldEncodedValue(@Nonnull FieldEncodedValue value) { 161 return new BuilderFieldEncodedValue(fieldPool.internField(value.getValue())); 162 } 163 164 @Nonnull private BuilderMethodEncodedValue internMethodEncodedValue(@Nonnull MethodEncodedValue value) { 165 return new BuilderMethodEncodedValue(methodPool.internMethod(value.getValue())); 166 } 167 168 @Nonnull private BuilderStringEncodedValue internStringEncodedValue(@Nonnull StringEncodedValue string) { 169 return new BuilderStringEncodedValue(stringPool.internString(string.getValue())); 170 } 171 172 @Nonnull private BuilderTypeEncodedValue internTypeEncodedValue(@Nonnull TypeEncodedValue type) { 173 return new BuilderTypeEncodedValue(typePool.internType(type.getValue())); 174 } 175} 176