1 // ASM: a very small and fast Java bytecode manipulation framework 2 // Copyright (c) 2000-2011 INRIA, France Telecom 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 7 // are met: 8 // 1. Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // 2. Redistributions in binary form must reproduce the above copyright 11 // notice, this list of conditions and the following disclaimer in the 12 // documentation and/or other materials provided with the distribution. 13 // 3. Neither the name of the copyright holders nor the names of its 14 // contributors may be used to endorse or promote products derived from 15 // this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 // THE POSSIBILITY OF SUCH DAMAGE. 28 29 package org.objectweb.asm.commons; 30 31 import org.objectweb.asm.AnnotationVisitor; 32 import org.objectweb.asm.Handle; 33 import org.objectweb.asm.Label; 34 import org.objectweb.asm.MethodVisitor; 35 import org.objectweb.asm.Opcodes; 36 import org.objectweb.asm.TypePath; 37 38 /** 39 * A {@link MethodVisitor} that remaps types with a {@link Remapper}. 40 * 41 * @author Eugene Kuleshov 42 */ 43 public class MethodRemapper extends MethodVisitor { 44 45 /** The remapper used to remap the types in the visited field. */ 46 protected final Remapper remapper; 47 48 /** 49 * Constructs a new {@link MethodRemapper}. <i>Subclasses must not use this constructor</i>. 50 * Instead, they must use the {@link #MethodRemapper(int,MethodVisitor,Remapper)} version. 51 * 52 * @param methodVisitor the method visitor this remapper must delegate to. 53 * @param remapper the remapper to use to remap the types in the visited method. 54 */ MethodRemapper(final MethodVisitor methodVisitor, final Remapper remapper)55 public MethodRemapper(final MethodVisitor methodVisitor, final Remapper remapper) { 56 this(/* latest api = */ Opcodes.ASM9, methodVisitor, remapper); 57 } 58 59 /** 60 * Constructs a new {@link MethodRemapper}. 61 * 62 * @param api the ASM API version supported by this remapper. Must be one of the {@code 63 * ASM}<i>x</i> values in {@link Opcodes}. 64 * @param methodVisitor the method visitor this remapper must delegate to. 65 * @param remapper the remapper to use to remap the types in the visited method. 66 */ MethodRemapper( final int api, final MethodVisitor methodVisitor, final Remapper remapper)67 protected MethodRemapper( 68 final int api, final MethodVisitor methodVisitor, final Remapper remapper) { 69 super(api, methodVisitor); 70 this.remapper = remapper; 71 } 72 73 @Override visitAnnotationDefault()74 public AnnotationVisitor visitAnnotationDefault() { 75 AnnotationVisitor annotationVisitor = super.visitAnnotationDefault(); 76 return annotationVisitor == null 77 ? annotationVisitor 78 : createAnnotationRemapper(/* descriptor = */ null, annotationVisitor); 79 } 80 81 @Override visitAnnotation(final String descriptor, final boolean visible)82 public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) { 83 AnnotationVisitor annotationVisitor = 84 super.visitAnnotation(remapper.mapDesc(descriptor), visible); 85 return annotationVisitor == null 86 ? annotationVisitor 87 : createAnnotationRemapper(descriptor, annotationVisitor); 88 } 89 90 @Override visitTypeAnnotation( final int typeRef, final TypePath typePath, final String descriptor, final boolean visible)91 public AnnotationVisitor visitTypeAnnotation( 92 final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { 93 AnnotationVisitor annotationVisitor = 94 super.visitTypeAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible); 95 return annotationVisitor == null 96 ? annotationVisitor 97 : createAnnotationRemapper(descriptor, annotationVisitor); 98 } 99 100 @Override visitParameterAnnotation( final int parameter, final String descriptor, final boolean visible)101 public AnnotationVisitor visitParameterAnnotation( 102 final int parameter, final String descriptor, final boolean visible) { 103 AnnotationVisitor annotationVisitor = 104 super.visitParameterAnnotation(parameter, remapper.mapDesc(descriptor), visible); 105 return annotationVisitor == null 106 ? annotationVisitor 107 : createAnnotationRemapper(descriptor, annotationVisitor); 108 } 109 110 @Override visitFrame( final int type, final int numLocal, final Object[] local, final int numStack, final Object[] stack)111 public void visitFrame( 112 final int type, 113 final int numLocal, 114 final Object[] local, 115 final int numStack, 116 final Object[] stack) { 117 super.visitFrame( 118 type, 119 numLocal, 120 remapFrameTypes(numLocal, local), 121 numStack, 122 remapFrameTypes(numStack, stack)); 123 } 124 remapFrameTypes(final int numTypes, final Object[] frameTypes)125 private Object[] remapFrameTypes(final int numTypes, final Object[] frameTypes) { 126 if (frameTypes == null) { 127 return frameTypes; 128 } 129 Object[] remappedFrameTypes = null; 130 for (int i = 0; i < numTypes; ++i) { 131 if (frameTypes[i] instanceof String) { 132 if (remappedFrameTypes == null) { 133 remappedFrameTypes = new Object[numTypes]; 134 System.arraycopy(frameTypes, 0, remappedFrameTypes, 0, numTypes); 135 } 136 remappedFrameTypes[i] = remapper.mapType((String) frameTypes[i]); 137 } 138 } 139 return remappedFrameTypes == null ? frameTypes : remappedFrameTypes; 140 } 141 142 @Override visitFieldInsn( final int opcode, final String owner, final String name, final String descriptor)143 public void visitFieldInsn( 144 final int opcode, final String owner, final String name, final String descriptor) { 145 super.visitFieldInsn( 146 opcode, 147 remapper.mapType(owner), 148 remapper.mapFieldName(owner, name, descriptor), 149 remapper.mapDesc(descriptor)); 150 } 151 152 @Override visitMethodInsn( final int opcodeAndSource, final String owner, final String name, final String descriptor, final boolean isInterface)153 public void visitMethodInsn( 154 final int opcodeAndSource, 155 final String owner, 156 final String name, 157 final String descriptor, 158 final boolean isInterface) { 159 if (api < Opcodes.ASM5 && (opcodeAndSource & Opcodes.SOURCE_DEPRECATED) == 0) { 160 // Redirect the call to the deprecated version of this method. 161 super.visitMethodInsn(opcodeAndSource, owner, name, descriptor, isInterface); 162 return; 163 } 164 super.visitMethodInsn( 165 opcodeAndSource, 166 remapper.mapType(owner), 167 remapper.mapMethodName(owner, name, descriptor), 168 remapper.mapMethodDesc(descriptor), 169 isInterface); 170 } 171 172 @Override visitInvokeDynamicInsn( final String name, final String descriptor, final Handle bootstrapMethodHandle, final Object... bootstrapMethodArguments)173 public void visitInvokeDynamicInsn( 174 final String name, 175 final String descriptor, 176 final Handle bootstrapMethodHandle, 177 final Object... bootstrapMethodArguments) { 178 Object[] remappedBootstrapMethodArguments = new Object[bootstrapMethodArguments.length]; 179 for (int i = 0; i < bootstrapMethodArguments.length; ++i) { 180 remappedBootstrapMethodArguments[i] = remapper.mapValue(bootstrapMethodArguments[i]); 181 } 182 super.visitInvokeDynamicInsn( 183 remapper.mapInvokeDynamicMethodName(name, descriptor), 184 remapper.mapMethodDesc(descriptor), 185 (Handle) remapper.mapValue(bootstrapMethodHandle), 186 remappedBootstrapMethodArguments); 187 } 188 189 @Override visitTypeInsn(final int opcode, final String type)190 public void visitTypeInsn(final int opcode, final String type) { 191 super.visitTypeInsn(opcode, remapper.mapType(type)); 192 } 193 194 @Override visitLdcInsn(final Object value)195 public void visitLdcInsn(final Object value) { 196 super.visitLdcInsn(remapper.mapValue(value)); 197 } 198 199 @Override visitMultiANewArrayInsn(final String descriptor, final int numDimensions)200 public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) { 201 super.visitMultiANewArrayInsn(remapper.mapDesc(descriptor), numDimensions); 202 } 203 204 @Override visitInsnAnnotation( final int typeRef, final TypePath typePath, final String descriptor, final boolean visible)205 public AnnotationVisitor visitInsnAnnotation( 206 final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { 207 AnnotationVisitor annotationVisitor = 208 super.visitInsnAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible); 209 return annotationVisitor == null 210 ? annotationVisitor 211 : createAnnotationRemapper(descriptor, annotationVisitor); 212 } 213 214 @Override visitTryCatchBlock( final Label start, final Label end, final Label handler, final String type)215 public void visitTryCatchBlock( 216 final Label start, final Label end, final Label handler, final String type) { 217 super.visitTryCatchBlock(start, end, handler, type == null ? null : remapper.mapType(type)); 218 } 219 220 @Override visitTryCatchAnnotation( final int typeRef, final TypePath typePath, final String descriptor, final boolean visible)221 public AnnotationVisitor visitTryCatchAnnotation( 222 final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { 223 AnnotationVisitor annotationVisitor = 224 super.visitTryCatchAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible); 225 return annotationVisitor == null 226 ? annotationVisitor 227 : createAnnotationRemapper(descriptor, annotationVisitor); 228 } 229 230 @Override visitLocalVariable( final String name, final String descriptor, final String signature, final Label start, final Label end, final int index)231 public void visitLocalVariable( 232 final String name, 233 final String descriptor, 234 final String signature, 235 final Label start, 236 final Label end, 237 final int index) { 238 super.visitLocalVariable( 239 name, 240 remapper.mapDesc(descriptor), 241 remapper.mapSignature(signature, true), 242 start, 243 end, 244 index); 245 } 246 247 @Override visitLocalVariableAnnotation( final int typeRef, final TypePath typePath, final Label[] start, final Label[] end, final int[] index, final String descriptor, final boolean visible)248 public AnnotationVisitor visitLocalVariableAnnotation( 249 final int typeRef, 250 final TypePath typePath, 251 final Label[] start, 252 final Label[] end, 253 final int[] index, 254 final String descriptor, 255 final boolean visible) { 256 AnnotationVisitor annotationVisitor = 257 super.visitLocalVariableAnnotation( 258 typeRef, typePath, start, end, index, remapper.mapDesc(descriptor), visible); 259 return annotationVisitor == null 260 ? annotationVisitor 261 : createAnnotationRemapper(descriptor, annotationVisitor); 262 } 263 264 /** 265 * Constructs a new remapper for annotations. The default implementation of this method returns a 266 * new {@link AnnotationRemapper}. 267 * 268 * @param annotationVisitor the AnnotationVisitor the remapper must delegate to. 269 * @return the newly created remapper. 270 * @deprecated use {@link #createAnnotationRemapper(String, AnnotationVisitor)} instead. 271 */ 272 @Deprecated createAnnotationRemapper(final AnnotationVisitor annotationVisitor)273 protected AnnotationVisitor createAnnotationRemapper(final AnnotationVisitor annotationVisitor) { 274 return new AnnotationRemapper(api, /* descriptor = */ null, annotationVisitor, remapper); 275 } 276 277 /** 278 * Constructs a new remapper for annotations. The default implementation of this method returns a 279 * new {@link AnnotationRemapper}. 280 * 281 * @param descriptor the descriptor of the visited annotation. 282 * @param annotationVisitor the AnnotationVisitor the remapper must delegate to. 283 * @return the newly created remapper. 284 */ createAnnotationRemapper( final String descriptor, final AnnotationVisitor annotationVisitor)285 protected AnnotationVisitor createAnnotationRemapper( 286 final String descriptor, final AnnotationVisitor annotationVisitor) { 287 return new AnnotationRemapper(api, descriptor, annotationVisitor, remapper) 288 .orDeprecatedValue(createAnnotationRemapper(annotationVisitor)); 289 } 290 } 291