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 32 package org.jf.dexlib2.writer; 33 34 import com.google.common.collect.Ordering; 35 import org.jf.dexlib2.ValueType; 36 import org.jf.dexlib2.base.BaseAnnotationElement; 37 import org.jf.dexlib2.iface.reference.FieldReference; 38 import org.jf.dexlib2.iface.reference.MethodHandleReference; 39 import org.jf.dexlib2.iface.reference.MethodReference; 40 41 import javax.annotation.Nonnull; 42 import java.io.IOException; 43 import java.util.Collection; 44 45 public abstract class EncodedValueWriter<StringKey, TypeKey, FieldRefKey extends FieldReference, 46 MethodRefKey extends MethodReference, AnnotationElement extends org.jf.dexlib2.iface.AnnotationElement, 47 ProtoRefKey, MethodHandleKey extends MethodHandleReference, EncodedValue> { 48 @Nonnull private final DexDataWriter writer; 49 @Nonnull private final StringSection<StringKey, ?> stringSection; 50 @Nonnull private final TypeSection<?, TypeKey, ?> typeSection; 51 @Nonnull private final FieldSection<?, ?, FieldRefKey, ?> fieldSection; 52 @Nonnull private final MethodSection<?, ?, ?, MethodRefKey, ?> methodSection; 53 @Nonnull private final ProtoSection<?, ?, ProtoRefKey, ?> protoSection; 54 @Nonnull private final MethodHandleSection<MethodHandleKey, ?, ?> methodHandleSection; 55 @Nonnull private final AnnotationSection<StringKey, TypeKey, ?, AnnotationElement, EncodedValue> annotationSection; 56 EncodedValueWriter( @onnull DexDataWriter writer, @Nonnull StringSection<StringKey, ?> stringSection, @Nonnull TypeSection<?, TypeKey, ?> typeSection, @Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection, @Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection, ProtoSection<?, ?, ProtoRefKey, ?> protoSection, MethodHandleSection<MethodHandleKey, ?, ?> methodHandleSection, @Nonnull AnnotationSection<StringKey, TypeKey, ?, AnnotationElement, EncodedValue> annotationSection)57 public EncodedValueWriter( 58 @Nonnull DexDataWriter writer, 59 @Nonnull StringSection<StringKey, ?> stringSection, 60 @Nonnull TypeSection<?, TypeKey, ?> typeSection, 61 @Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection, 62 @Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection, 63 ProtoSection<?, ?, ProtoRefKey, ?> protoSection, 64 MethodHandleSection<MethodHandleKey, ?, ?> methodHandleSection, 65 @Nonnull AnnotationSection<StringKey, TypeKey, ?, AnnotationElement, EncodedValue> annotationSection) { 66 this.writer = writer; 67 this.stringSection = stringSection; 68 this.typeSection = typeSection; 69 this.fieldSection = fieldSection; 70 this.methodSection = methodSection; 71 this.protoSection = protoSection; 72 this.methodHandleSection = methodHandleSection; 73 this.annotationSection = annotationSection; 74 } 75 writeEncodedValue(@onnull EncodedValue encodedValue)76 protected abstract void writeEncodedValue(@Nonnull EncodedValue encodedValue) throws IOException; 77 writeAnnotation(TypeKey annotationType, Collection<? extends AnnotationElement> elements)78 public void writeAnnotation(TypeKey annotationType, 79 Collection<? extends AnnotationElement> elements) throws IOException { 80 writer.writeEncodedValueHeader(ValueType.ANNOTATION, 0); 81 writer.writeUleb128(typeSection.getItemIndex(annotationType)); 82 writer.writeUleb128(elements.size()); 83 84 Collection<? extends AnnotationElement> sortedElements = Ordering.from(BaseAnnotationElement.BY_NAME) 85 .immutableSortedCopy(elements); 86 87 for (AnnotationElement element: sortedElements) { 88 writer.writeUleb128(stringSection.getItemIndex(annotationSection.getElementName(element))); 89 writeEncodedValue(annotationSection.getElementValue(element)); 90 } 91 } 92 writeArray(Collection<? extends EncodedValue> elements)93 public void writeArray(Collection<? extends EncodedValue> elements) throws IOException { 94 writer.writeEncodedValueHeader(ValueType.ARRAY, 0); 95 writer.writeUleb128(elements.size()); 96 for (EncodedValue element: elements) { 97 writeEncodedValue(element); 98 } 99 } 100 writeBoolean(boolean value)101 public void writeBoolean(boolean value) throws IOException { 102 writer.writeEncodedValueHeader(ValueType.BOOLEAN, value ? 1 : 0); 103 } 104 writeByte(byte value)105 public void writeByte(byte value) throws IOException { 106 writer.writeEncodedInt(ValueType.BYTE, value); 107 } 108 writeChar(char value)109 public void writeChar(char value) throws IOException { 110 writer.writeEncodedUint(ValueType.CHAR, value); 111 } 112 writeDouble(double value)113 public void writeDouble(double value) throws IOException { 114 writer.writeEncodedDouble(ValueType.DOUBLE, value); 115 } 116 writeEnum(@onnull FieldRefKey value)117 public void writeEnum(@Nonnull FieldRefKey value) throws IOException { 118 writer.writeEncodedUint(ValueType.ENUM, fieldSection.getItemIndex(value)); 119 } 120 writeField(@onnull FieldRefKey value)121 public void writeField(@Nonnull FieldRefKey value) throws IOException { 122 writer.writeEncodedUint(ValueType.FIELD, fieldSection.getItemIndex(value)); 123 } 124 writeFloat(float value)125 public void writeFloat(float value) throws IOException { 126 writer.writeEncodedFloat(ValueType.FLOAT, value); 127 } 128 writeInt(int value)129 public void writeInt(int value) throws IOException { 130 writer.writeEncodedInt(ValueType.INT, value); 131 } 132 writeLong(long value)133 public void writeLong(long value) throws IOException { 134 writer.writeEncodedLong(ValueType.LONG, value); 135 } 136 writeMethod(@onnull MethodRefKey value)137 public void writeMethod(@Nonnull MethodRefKey value) throws IOException { 138 writer.writeEncodedUint(ValueType.METHOD, methodSection.getItemIndex(value)); 139 } 140 writeNull()141 public void writeNull() throws IOException { 142 writer.write(ValueType.NULL); 143 } 144 writeShort(int value)145 public void writeShort(int value) throws IOException { 146 writer.writeEncodedInt(ValueType.SHORT, value); 147 } 148 writeString(@onnull StringKey value)149 public void writeString(@Nonnull StringKey value) throws IOException { 150 writer.writeEncodedUint(ValueType.STRING, stringSection.getItemIndex(value)); 151 } 152 writeType(@onnull TypeKey value)153 public void writeType(@Nonnull TypeKey value) throws IOException { 154 writer.writeEncodedUint(ValueType.TYPE, typeSection.getItemIndex(value)); 155 } 156 writeMethodType(@onnull ProtoRefKey value)157 public void writeMethodType(@Nonnull ProtoRefKey value) throws IOException { 158 writer.writeEncodedUint(ValueType.METHOD_TYPE, protoSection.getItemIndex(value)); 159 } 160 writeMethodHandle(@onnull MethodHandleKey value)161 public void writeMethodHandle(@Nonnull MethodHandleKey value) throws IOException { 162 writer.writeEncodedUint(ValueType.METHOD_HANDLE, methodHandleSection.getItemIndex(value)); 163 } 164 } 165