• 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 java.util.List;
32 import org.objectweb.asm.AnnotationVisitor;
33 import org.objectweb.asm.Attribute;
34 import org.objectweb.asm.ClassVisitor;
35 import org.objectweb.asm.FieldVisitor;
36 import org.objectweb.asm.MethodVisitor;
37 import org.objectweb.asm.ModuleVisitor;
38 import org.objectweb.asm.Opcodes;
39 import org.objectweb.asm.RecordComponentVisitor;
40 import org.objectweb.asm.TypePath;
41 
42 /**
43  * A {@link ClassVisitor} that remaps types with a {@link Remapper}.
44  *
45  * <p><i>This visitor has several limitations</i>. A non-exhaustive list is the following:
46  *
47  * <ul>
48  *   <li>it cannot remap type names in dynamically computed strings (remapping of type names in
49  *       static values is supported).
50  *   <li>it cannot remap values derived from type names at compile time, such as
51  *       <ul>
52  *         <li>type name hashcodes used by some Java compilers to implement the string switch
53  *             statement.
54  *         <li>some compound strings used by some Java compilers to implement lambda
55  *             deserialization.
56  *       </ul>
57  * </ul>
58  *
59  * @author Eugene Kuleshov
60  */
61 public class ClassRemapper extends ClassVisitor {
62 
63   /** The remapper used to remap the types in the visited class. */
64   protected final Remapper remapper;
65 
66   /** The internal name of the visited class. */
67   protected String className;
68 
69   /**
70    * Constructs a new {@link ClassRemapper}. <i>Subclasses must not use this constructor</i>.
71    * Instead, they must use the {@link #ClassRemapper(int,ClassVisitor,Remapper)} version.
72    *
73    * @param classVisitor the class visitor this remapper must delegate to.
74    * @param remapper the remapper to use to remap the types in the visited class.
75    */
ClassRemapper(final ClassVisitor classVisitor, final Remapper remapper)76   public ClassRemapper(final ClassVisitor classVisitor, final Remapper remapper) {
77     this(/* latest api = */ Opcodes.ASM9, classVisitor, remapper);
78   }
79 
80   /**
81    * Constructs a new {@link ClassRemapper}.
82    *
83    * @param api the ASM API version supported by this remapper. Must be one of the {@code
84    *     ASM}<i>x</i> values in {@link Opcodes}.
85    * @param classVisitor the class visitor this remapper must delegate to.
86    * @param remapper the remapper to use to remap the types in the visited class.
87    */
ClassRemapper(final int api, final ClassVisitor classVisitor, final Remapper remapper)88   protected ClassRemapper(final int api, final ClassVisitor classVisitor, final Remapper remapper) {
89     super(api, classVisitor);
90     this.remapper = remapper;
91   }
92 
93   @Override
visit( final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces)94   public void visit(
95       final int version,
96       final int access,
97       final String name,
98       final String signature,
99       final String superName,
100       final String[] interfaces) {
101     this.className = name;
102     super.visit(
103         version,
104         access,
105         remapper.mapType(name),
106         remapper.mapSignature(signature, false),
107         remapper.mapType(superName),
108         interfaces == null ? null : remapper.mapTypes(interfaces));
109   }
110 
111   @Override
visitModule(final String name, final int flags, final String version)112   public ModuleVisitor visitModule(final String name, final int flags, final String version) {
113     ModuleVisitor moduleVisitor = super.visitModule(remapper.mapModuleName(name), flags, version);
114     return moduleVisitor == null ? null : createModuleRemapper(moduleVisitor);
115   }
116 
117   @Override
visitAnnotation(final String descriptor, final boolean visible)118   public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
119     AnnotationVisitor annotationVisitor =
120         super.visitAnnotation(remapper.mapDesc(descriptor), visible);
121     return annotationVisitor == null
122         ? null
123         : createAnnotationRemapper(descriptor, annotationVisitor);
124   }
125 
126   @Override
visitTypeAnnotation( final int typeRef, final TypePath typePath, final String descriptor, final boolean visible)127   public AnnotationVisitor visitTypeAnnotation(
128       final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
129     AnnotationVisitor annotationVisitor =
130         super.visitTypeAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible);
131     return annotationVisitor == null
132         ? null
133         : createAnnotationRemapper(descriptor, annotationVisitor);
134   }
135 
136   @Override
visitAttribute(final Attribute attribute)137   public void visitAttribute(final Attribute attribute) {
138     if (attribute instanceof ModuleHashesAttribute) {
139       ModuleHashesAttribute moduleHashesAttribute = (ModuleHashesAttribute) attribute;
140       List<String> modules = moduleHashesAttribute.modules;
141       for (int i = 0; i < modules.size(); ++i) {
142         modules.set(i, remapper.mapModuleName(modules.get(i)));
143       }
144     }
145     super.visitAttribute(attribute);
146   }
147 
148   @Override
visitRecordComponent( final String name, final String descriptor, final String signature)149   public RecordComponentVisitor visitRecordComponent(
150       final String name, final String descriptor, final String signature) {
151     RecordComponentVisitor recordComponentVisitor =
152         super.visitRecordComponent(
153             remapper.mapRecordComponentName(className, name, descriptor),
154             remapper.mapDesc(descriptor),
155             remapper.mapSignature(signature, true));
156     return recordComponentVisitor == null
157         ? null
158         : createRecordComponentRemapper(recordComponentVisitor);
159   }
160 
161   @Override
visitField( final int access, final String name, final String descriptor, final String signature, final Object value)162   public FieldVisitor visitField(
163       final int access,
164       final String name,
165       final String descriptor,
166       final String signature,
167       final Object value) {
168     FieldVisitor fieldVisitor =
169         super.visitField(
170             access,
171             remapper.mapFieldName(className, name, descriptor),
172             remapper.mapDesc(descriptor),
173             remapper.mapSignature(signature, true),
174             (value == null) ? null : remapper.mapValue(value));
175     return fieldVisitor == null ? null : createFieldRemapper(fieldVisitor);
176   }
177 
178   @Override
visitMethod( final int access, final String name, final String descriptor, final String signature, final String[] exceptions)179   public MethodVisitor visitMethod(
180       final int access,
181       final String name,
182       final String descriptor,
183       final String signature,
184       final String[] exceptions) {
185     String remappedDescriptor = remapper.mapMethodDesc(descriptor);
186     MethodVisitor methodVisitor =
187         super.visitMethod(
188             access,
189             remapper.mapMethodName(className, name, descriptor),
190             remappedDescriptor,
191             remapper.mapSignature(signature, false),
192             exceptions == null ? null : remapper.mapTypes(exceptions));
193     return methodVisitor == null ? null : createMethodRemapper(methodVisitor);
194   }
195 
196   @Override
visitInnerClass( final String name, final String outerName, final String innerName, final int access)197   public void visitInnerClass(
198       final String name, final String outerName, final String innerName, final int access) {
199     super.visitInnerClass(
200         remapper.mapType(name),
201         outerName == null ? null : remapper.mapType(outerName),
202         innerName == null ? null : remapper.mapInnerClassName(name, outerName, innerName),
203         access);
204   }
205 
206   @Override
visitOuterClass(final String owner, final String name, final String descriptor)207   public void visitOuterClass(final String owner, final String name, final String descriptor) {
208     super.visitOuterClass(
209         remapper.mapType(owner),
210         name == null ? null : remapper.mapMethodName(owner, name, descriptor),
211         descriptor == null ? null : remapper.mapMethodDesc(descriptor));
212   }
213 
214   @Override
visitNestHost(final String nestHost)215   public void visitNestHost(final String nestHost) {
216     super.visitNestHost(remapper.mapType(nestHost));
217   }
218 
219   @Override
visitNestMember(final String nestMember)220   public void visitNestMember(final String nestMember) {
221     super.visitNestMember(remapper.mapType(nestMember));
222   }
223 
224   @Override
visitPermittedSubclass(final String permittedSubclass)225   public void visitPermittedSubclass(final String permittedSubclass) {
226     super.visitPermittedSubclass(remapper.mapType(permittedSubclass));
227   }
228 
229   /**
230    * Constructs a new remapper for fields. The default implementation of this method returns a new
231    * {@link FieldRemapper}.
232    *
233    * @param fieldVisitor the FieldVisitor the remapper must delegate to.
234    * @return the newly created remapper.
235    */
createFieldRemapper(final FieldVisitor fieldVisitor)236   protected FieldVisitor createFieldRemapper(final FieldVisitor fieldVisitor) {
237     return new FieldRemapper(api, fieldVisitor, remapper);
238   }
239 
240   /**
241    * Constructs a new remapper for methods. The default implementation of this method returns a new
242    * {@link MethodRemapper}.
243    *
244    * @param methodVisitor the MethodVisitor the remapper must delegate to.
245    * @return the newly created remapper.
246    */
createMethodRemapper(final MethodVisitor methodVisitor)247   protected MethodVisitor createMethodRemapper(final MethodVisitor methodVisitor) {
248     return new MethodRemapper(api, methodVisitor, remapper);
249   }
250 
251   /**
252    * Constructs a new remapper for annotations. The default implementation of this method returns a
253    * new {@link AnnotationRemapper}.
254    *
255    * @param annotationVisitor the AnnotationVisitor the remapper must delegate to.
256    * @return the newly created remapper.
257    * @deprecated use {@link #createAnnotationRemapper(String, AnnotationVisitor)} instead.
258    */
259   @Deprecated
createAnnotationRemapper(final AnnotationVisitor annotationVisitor)260   protected AnnotationVisitor createAnnotationRemapper(final AnnotationVisitor annotationVisitor) {
261     return new AnnotationRemapper(api, /* descriptor = */ null, annotationVisitor, remapper);
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 descriptor the descriptor of the visited annotation.
269    * @param annotationVisitor the AnnotationVisitor the remapper must delegate to.
270    * @return the newly created remapper.
271    */
createAnnotationRemapper( final String descriptor, final AnnotationVisitor annotationVisitor)272   protected AnnotationVisitor createAnnotationRemapper(
273       final String descriptor, final AnnotationVisitor annotationVisitor) {
274     return new AnnotationRemapper(api, descriptor, annotationVisitor, remapper)
275         .orDeprecatedValue(createAnnotationRemapper(annotationVisitor));
276   }
277 
278   /**
279    * Constructs a new remapper for modules. The default implementation of this method returns a new
280    * {@link ModuleRemapper}.
281    *
282    * @param moduleVisitor the ModuleVisitor the remapper must delegate to.
283    * @return the newly created remapper.
284    */
createModuleRemapper(final ModuleVisitor moduleVisitor)285   protected ModuleVisitor createModuleRemapper(final ModuleVisitor moduleVisitor) {
286     return new ModuleRemapper(api, moduleVisitor, remapper);
287   }
288 
289   /**
290    * Constructs a new remapper for record components. The default implementation of this method
291    * returns a new {@link RecordComponentRemapper}.
292    *
293    * @param recordComponentVisitor the RecordComponentVisitor the remapper must delegate to.
294    * @return the newly created remapper.
295    */
createRecordComponentRemapper( final RecordComponentVisitor recordComponentVisitor)296   protected RecordComponentVisitor createRecordComponentRemapper(
297       final RecordComponentVisitor recordComponentVisitor) {
298     return new RecordComponentRemapper(api, recordComponentVisitor, remapper);
299   }
300 }
301