• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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