001// ASM: a very small and fast Java bytecode manipulation framework 002// Copyright (c) 2000-2011 INRIA, France Telecom 003// All rights reserved. 004// 005// Redistribution and use in source and binary forms, with or without 006// modification, are permitted provided that the following conditions 007// are met: 008// 1. Redistributions of source code must retain the above copyright 009// notice, this list of conditions and the following disclaimer. 010// 2. Redistributions in binary form must reproduce the above copyright 011// notice, this list of conditions and the following disclaimer in the 012// documentation and/or other materials provided with the distribution. 013// 3. Neither the name of the copyright holders nor the names of its 014// contributors may be used to endorse or promote products derived from 015// this software without specific prior written permission. 016// 017// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 018// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 019// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 020// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 021// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 022// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 023// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 024// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 025// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 026// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 027// THE POSSIBILITY OF SUCH DAMAGE. 028 029package io.ebean.enhance.asm.commons; 030 031import io.ebean.enhance.asm.AnnotationVisitor; 032import io.ebean.enhance.asm.Attribute; 033import io.ebean.enhance.asm.ClassVisitor; 034import io.ebean.enhance.asm.FieldVisitor; 035import io.ebean.enhance.asm.MethodVisitor; 036import io.ebean.enhance.asm.ModuleVisitor; 037import io.ebean.enhance.asm.Opcodes; 038import io.ebean.enhance.asm.TypePath; 039 040import java.util.List; 041 042/** 043 * A {@link ClassVisitor} that remaps types with a {@link Remapper}. 044 * 045 * @author Eugene Kuleshov 046 */ 047public class ClassRemapper extends ClassVisitor { 048 049 /** The remapper used to remap the types in the visited class. */ 050 protected final Remapper remapper; 051 052 /** The internal name of the visited class. */ 053 protected String className; 054 055 /** 056 * Constructs a new {@link ClassRemapper}. <i>Subclasses must not use this constructor</i>. 057 * Instead, they must use the {@link #ClassRemapper(int, ClassVisitor, Remapper)} version. 058 * 059 * @param classVisitor the class visitor this remapper must deleted to. 060 * @param remapper the remapper to use to remap the types in the visited class. 061 */ 062 public ClassRemapper(final ClassVisitor classVisitor, final Remapper remapper) { 063 this(Opcodes.ASM7, classVisitor, remapper); 064 } 065 066 /** 067 * Constructs a new {@link ClassRemapper}. 068 * 069 * @param api the ASM API version supported by this remapper. Must be one of {@link 070 * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link 071 * Opcodes#ASM6} or {@link Opcodes#ASM7}. 072 * @param classVisitor the class visitor this remapper must deleted to. 073 * @param remapper the remapper to use to remap the types in the visited class. 074 */ 075 protected ClassRemapper(final int api, final ClassVisitor classVisitor, final Remapper remapper) { 076 super(api, classVisitor); 077 this.remapper = remapper; 078 } 079 080 @Override 081 public void visit( 082 final int version, 083 final int access, 084 final String name, 085 final String signature, 086 final String superName, 087 final String[] interfaces) { 088 this.className = name; 089 super.visit( 090 version, 091 access, 092 remapper.mapType(name), 093 remapper.mapSignature(signature, false), 094 remapper.mapType(superName), 095 interfaces == null ? null : remapper.mapTypes(interfaces)); 096 } 097 098 @Override 099 public ModuleVisitor visitModule(final String name, final int flags, final String version) { 100 ModuleVisitor moduleVisitor = super.visitModule(remapper.mapModuleName(name), flags, version); 101 return moduleVisitor == null ? null : createModuleRemapper(moduleVisitor); 102 } 103 104 @Override 105 public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) { 106 AnnotationVisitor annotationVisitor = 107 super.visitAnnotation(remapper.mapDesc(descriptor), visible); 108 return annotationVisitor == null ? null : createAnnotationRemapper(annotationVisitor); 109 } 110 111 @Override 112 public AnnotationVisitor visitTypeAnnotation( 113 final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { 114 AnnotationVisitor annotationVisitor = 115 super.visitTypeAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible); 116 return annotationVisitor == null ? null : createAnnotationRemapper(annotationVisitor); 117 } 118 119 @Override 120 public void visitAttribute(final Attribute attribute) { 121 if (attribute instanceof ModuleHashesAttribute) { 122 ModuleHashesAttribute moduleHashesAttribute = (ModuleHashesAttribute) attribute; 123 List<String> modules = moduleHashesAttribute.modules; 124 for (int i = 0; i < modules.size(); ++i) { 125 modules.set(i, remapper.mapModuleName(modules.get(i))); 126 } 127 } 128 super.visitAttribute(attribute); 129 } 130 131 @Override 132 public FieldVisitor visitField( 133 final int access, 134 final String name, 135 final String descriptor, 136 final String signature, 137 final Object value) { 138 FieldVisitor fieldVisitor = 139 super.visitField( 140 access, 141 remapper.mapFieldName(className, name, descriptor), 142 remapper.mapDesc(descriptor), 143 remapper.mapSignature(signature, true), 144 (value == null) ? null : remapper.mapValue(value)); 145 return fieldVisitor == null ? null : createFieldRemapper(fieldVisitor); 146 } 147 148 @Override 149 public MethodVisitor visitMethod( 150 final int access, 151 final String name, 152 final String descriptor, 153 final String signature, 154 final String[] exceptions) { 155 String remappedDescriptor = remapper.mapMethodDesc(descriptor); 156 MethodVisitor methodVisitor = 157 super.visitMethod( 158 access, 159 remapper.mapMethodName(className, name, descriptor), 160 remappedDescriptor, 161 remapper.mapSignature(signature, false), 162 exceptions == null ? null : remapper.mapTypes(exceptions)); 163 return methodVisitor == null ? null : createMethodRemapper(methodVisitor); 164 } 165 166 @Override 167 public void visitInnerClass( 168 final String name, final String outerName, final String innerName, final int access) { 169 super.visitInnerClass( 170 remapper.mapType(name), 171 outerName == null ? null : remapper.mapType(outerName), 172 innerName == null ? null : remapper.mapInnerClassName(name, outerName, innerName), 173 access); 174 } 175 176 @Override 177 public void visitOuterClass(final String owner, final String name, final String descriptor) { 178 super.visitOuterClass( 179 remapper.mapType(owner), 180 name == null ? null : remapper.mapMethodName(owner, name, descriptor), 181 descriptor == null ? null : remapper.mapMethodDesc(descriptor)); 182 } 183 184 @Override 185 public void visitNestHost(final String nestHost) { 186 super.visitNestHost(remapper.mapType(nestHost)); 187 } 188 189 @Override 190 public void visitNestMember(final String nestMember) { 191 super.visitNestMember(remapper.mapType(nestMember)); 192 } 193 194 /** 195 * Constructs a new remapper for fields. The default implementation of this method returns a new 196 * {@link FieldRemapper}. 197 * 198 * @param fieldVisitor the FieldVisitor the remapper must delegate to. 199 * @return the newly created remapper. 200 */ 201 protected FieldVisitor createFieldRemapper(final FieldVisitor fieldVisitor) { 202 return new FieldRemapper(api, fieldVisitor, remapper); 203 } 204 205 /** 206 * Constructs a new remapper for methods. The default implementation of this method returns a new 207 * {@link MethodRemapper}. 208 * 209 * @param methodVisitor the MethodVisitor the remapper must delegate to. 210 * @return the newly created remapper. 211 */ 212 protected MethodVisitor createMethodRemapper(final MethodVisitor methodVisitor) { 213 return new MethodRemapper(api, methodVisitor, remapper); 214 } 215 216 /** 217 * Constructs a new remapper for annotations. The default implementation of this method returns a 218 * new {@link AnnotationRemapper}. 219 * 220 * @param annotationVisitor the AnnotationVisitor the remapper must delegate to. 221 * @return the newly created remapper. 222 */ 223 protected AnnotationVisitor createAnnotationRemapper(final AnnotationVisitor annotationVisitor) { 224 return new AnnotationRemapper(api, annotationVisitor, remapper); 225 } 226 227 /** 228 * Constructs a new remapper for modules. The default implementation of this method returns a new 229 * {@link ModuleRemapper}. 230 * 231 * @param moduleVisitor the ModuleVisitor the remapper must delegate to. 232 * @return the newly created remapper. 233 */ 234 protected ModuleVisitor createModuleRemapper(final ModuleVisitor moduleVisitor) { 235 return new ModuleRemapper(api, moduleVisitor, remapper); 236 } 237}