1 /* 2 * Copyright 2016 Google Inc. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.turbine.bytecode; 18 19 import com.google.common.io.ByteArrayDataOutput; 20 import com.google.common.io.ByteStreams; 21 import com.google.turbine.bytecode.Attribute.Annotations; 22 import com.google.turbine.bytecode.Attribute.ConstantValue; 23 import com.google.turbine.bytecode.Attribute.ExceptionsAttribute; 24 import com.google.turbine.bytecode.Attribute.InnerClasses; 25 import com.google.turbine.bytecode.Attribute.MethodParameters; 26 import com.google.turbine.bytecode.Attribute.Signature; 27 import com.google.turbine.bytecode.Attribute.TypeAnnotations; 28 import com.google.turbine.bytecode.ClassFile.AnnotationInfo; 29 import com.google.turbine.bytecode.ClassFile.MethodInfo.ParameterInfo; 30 import com.google.turbine.bytecode.ClassFile.TypeAnnotationInfo; 31 import com.google.turbine.model.Const; 32 import java.util.List; 33 34 /** Writer {@link Attribute}s to bytecode. */ 35 public class AttributeWriter { 36 37 private final ConstantPool pool; 38 private final ByteArrayDataOutput output; 39 AttributeWriter(ConstantPool pool, ByteArrayDataOutput output)40 public AttributeWriter(ConstantPool pool, ByteArrayDataOutput output) { 41 this.pool = pool; 42 this.output = output; 43 } 44 45 /** Writes a single attribute. */ write(Attribute attribute)46 public void write(Attribute attribute) { 47 switch (attribute.kind()) { 48 case SIGNATURE: 49 writeSignatureAttribute((Signature) attribute); 50 break; 51 case EXCEPTIONS: 52 writeExceptionsAttribute((ExceptionsAttribute) attribute); 53 break; 54 case INNER_CLASSES: 55 writeInnerClasses((InnerClasses) attribute); 56 break; 57 case CONSTANT_VALUE: 58 writeConstantValue((ConstantValue) attribute); 59 break; 60 case RUNTIME_VISIBLE_ANNOTATIONS: 61 case RUNTIME_INVISIBLE_ANNOTATIONS: 62 writeAnnotation((Attribute.Annotations) attribute); 63 break; 64 case ANNOTATION_DEFAULT: 65 writeAnnotationDefault((Attribute.AnnotationDefault) attribute); 66 break; 67 case RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS: 68 case RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS: 69 writeParameterAnnotations((Attribute.ParameterAnnotations) attribute); 70 break; 71 case DEPRECATED: 72 writeDeprecated(attribute); 73 break; 74 case RUNTIME_INVISIBLE_TYPE_ANNOTATIONS: 75 case RUNTIME_VISIBLE_TYPE_ANNOTATIONS: 76 writeTypeAnnotation((Attribute.TypeAnnotations) attribute); 77 break; 78 case METHOD_PARAMETERS: 79 writeMethodParameters((Attribute.MethodParameters) attribute); 80 break; 81 default: 82 throw new AssertionError(attribute.kind()); 83 } 84 } 85 writeInnerClasses(InnerClasses attribute)86 private void writeInnerClasses(InnerClasses attribute) { 87 output.writeShort(pool.utf8(attribute.kind().signature())); 88 output.writeInt(attribute.inners.size() * 8 + 2); 89 output.writeShort(attribute.inners.size()); 90 for (ClassFile.InnerClass inner : attribute.inners) { 91 output.writeShort(pool.classInfo(inner.innerClass())); 92 output.writeShort(pool.classInfo(inner.outerClass())); 93 output.writeShort(pool.utf8(inner.innerName())); 94 output.writeShort(inner.access()); 95 } 96 } 97 writeExceptionsAttribute(ExceptionsAttribute attribute)98 private void writeExceptionsAttribute(ExceptionsAttribute attribute) { 99 output.writeShort(pool.utf8(attribute.kind().signature())); 100 output.writeInt(2 + attribute.exceptions.size() * 2); 101 output.writeShort(attribute.exceptions.size()); 102 for (String exception : attribute.exceptions) { 103 output.writeShort(pool.classInfo(exception)); 104 } 105 } 106 writeSignatureAttribute(Signature attribute)107 private void writeSignatureAttribute(Signature attribute) { 108 output.writeShort(pool.utf8(attribute.kind().signature())); 109 output.writeInt(2); 110 output.writeShort(pool.utf8(attribute.signature)); 111 } 112 writeConstantValue(ConstantValue attribute)113 public void writeConstantValue(ConstantValue attribute) { 114 output.writeShort(pool.utf8(attribute.kind().signature())); 115 output.writeInt(2); 116 Const.Value value = attribute.value; 117 switch (value.constantTypeKind()) { 118 case INT: 119 case CHAR: 120 case SHORT: 121 case BYTE: 122 output.writeShort(pool.integer(value.asInteger().value())); 123 break; 124 case LONG: 125 output.writeShort(pool.longInfo(value.asLong().value())); 126 break; 127 case DOUBLE: 128 output.writeShort(pool.doubleInfo(value.asDouble().value())); 129 break; 130 case FLOAT: 131 output.writeShort(pool.floatInfo(value.asFloat().value())); 132 break; 133 case BOOLEAN: 134 output.writeShort(pool.integer(value.asBoolean().value() ? 1 : 0)); 135 break; 136 case STRING: 137 output.writeShort(pool.string(value.asString().value())); 138 break; 139 default: 140 throw new AssertionError(value.constantTypeKind()); 141 } 142 } 143 writeAnnotation(Annotations attribute)144 public void writeAnnotation(Annotations attribute) { 145 output.writeShort(pool.utf8(attribute.kind().signature())); 146 ByteArrayDataOutput tmp = ByteStreams.newDataOutput(); 147 tmp.writeShort(attribute.annotations().size()); 148 for (AnnotationInfo annotation : attribute.annotations()) { 149 new AnnotationWriter(pool, tmp).writeAnnotation(annotation); 150 } 151 byte[] data = tmp.toByteArray(); 152 output.writeInt(data.length); 153 output.write(data); 154 } 155 writeAnnotationDefault(Attribute.AnnotationDefault attribute)156 public void writeAnnotationDefault(Attribute.AnnotationDefault attribute) { 157 output.writeShort(pool.utf8(attribute.kind().signature())); 158 ByteArrayDataOutput tmp = ByteStreams.newDataOutput(); 159 new AnnotationWriter(pool, tmp).writeElementValue(attribute.value()); 160 byte[] data = tmp.toByteArray(); 161 output.writeInt(data.length); 162 output.write(data); 163 } 164 writeParameterAnnotations(Attribute.ParameterAnnotations attribute)165 public void writeParameterAnnotations(Attribute.ParameterAnnotations attribute) { 166 output.writeShort(pool.utf8(attribute.kind().signature())); 167 ByteArrayDataOutput tmp = ByteStreams.newDataOutput(); 168 tmp.writeByte(attribute.annotations().size()); 169 for (List<AnnotationInfo> parameterAnnotations : attribute.annotations()) { 170 tmp.writeShort(parameterAnnotations.size()); 171 for (AnnotationInfo annotation : parameterAnnotations) { 172 new AnnotationWriter(pool, tmp).writeAnnotation(annotation); 173 } 174 } 175 byte[] data = tmp.toByteArray(); 176 output.writeInt(data.length); 177 output.write(data); 178 } 179 writeDeprecated(Attribute attribute)180 private void writeDeprecated(Attribute attribute) { 181 output.writeShort(pool.utf8(attribute.kind().signature())); 182 output.writeInt(0); 183 } 184 writeTypeAnnotation(TypeAnnotations attribute)185 private void writeTypeAnnotation(TypeAnnotations attribute) { 186 output.writeShort(pool.utf8(attribute.kind().signature())); 187 ByteArrayDataOutput tmp = ByteStreams.newDataOutput(); 188 tmp.writeShort(attribute.annotations().size()); 189 for (TypeAnnotationInfo annotation : attribute.annotations()) { 190 new AnnotationWriter(pool, tmp).writeTypeAnnotation(annotation); 191 } 192 byte[] data = tmp.toByteArray(); 193 output.writeInt(data.length); 194 output.write(data); 195 } 196 writeMethodParameters(MethodParameters attribute)197 private void writeMethodParameters(MethodParameters attribute) { 198 output.writeShort(pool.utf8(attribute.kind().signature())); 199 output.writeInt(attribute.parameters().size() * 4 + 1); 200 output.writeByte(attribute.parameters().size()); 201 for (ParameterInfo parameter : attribute.parameters()) { 202 output.writeShort(parameter.name() != null ? pool.utf8(parameter.name()) : 0); 203 output.writeShort(parameter.access()); 204 } 205 } 206 } 207