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.Opcodes; 032import io.ebean.enhance.asm.signature.SignatureVisitor; 033 034import java.util.ArrayList; 035 036/** 037 * A {@link SignatureVisitor} that remaps types with a {@link Remapper}. 038 * 039 * @author Eugene Kuleshov 040 */ 041public class SignatureRemapper extends SignatureVisitor { 042 043 private final SignatureVisitor signatureVisitor; 044 045 private final Remapper remapper; 046 047 private ArrayList<String> classNames = new ArrayList<>(); 048 049 /** 050 * Constructs a new {@link SignatureRemapper}. <i>Subclasses must not use this constructor</i>. 051 * Instead, they must use the {@link #SignatureRemapper(int, SignatureVisitor,Remapper)} version. 052 * 053 * @param signatureVisitor the signature visitor this remapper must deleted to. 054 * @param remapper the remapper to use to remap the types in the visited signature. 055 */ 056 public SignatureRemapper(final SignatureVisitor signatureVisitor, final Remapper remapper) { 057 this(Opcodes.ASM7, signatureVisitor, remapper); 058 } 059 060 /** 061 * Constructs a new {@link SignatureRemapper}. 062 * 063 * @param api the ASM API version supported by this remapper. Must be one of {@link 064 * Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link 065 * Opcodes#ASM6}. 066 * @param signatureVisitor the signature visitor this remapper must deleted to. 067 * @param remapper the remapper to use to remap the types in the visited signature. 068 */ 069 protected SignatureRemapper( 070 final int api, final SignatureVisitor signatureVisitor, final Remapper remapper) { 071 super(api); 072 this.signatureVisitor = signatureVisitor; 073 this.remapper = remapper; 074 } 075 076 @Override 077 public void visitClassType(final String name) { 078 classNames.add(name); 079 signatureVisitor.visitClassType(remapper.mapType(name)); 080 } 081 082 @Override 083 public void visitInnerClassType(final String name) { 084 String outerClassName = classNames.remove(classNames.size() - 1); 085 String className = outerClassName + '$' + name; 086 classNames.add(className); 087 String remappedOuter = remapper.mapType(outerClassName) + '$'; 088 String remappedName = remapper.mapType(className); 089 int index = 090 remappedName.startsWith(remappedOuter) 091 ? remappedOuter.length() 092 : remappedName.lastIndexOf('$') + 1; 093 signatureVisitor.visitInnerClassType(remappedName.substring(index)); 094 } 095 096 @Override 097 public void visitFormalTypeParameter(final String name) { 098 signatureVisitor.visitFormalTypeParameter(name); 099 } 100 101 @Override 102 public void visitTypeVariable(final String name) { 103 signatureVisitor.visitTypeVariable(name); 104 } 105 106 @Override 107 public SignatureVisitor visitArrayType() { 108 signatureVisitor.visitArrayType(); 109 return this; 110 } 111 112 @Override 113 public void visitBaseType(final char descriptor) { 114 signatureVisitor.visitBaseType(descriptor); 115 } 116 117 @Override 118 public SignatureVisitor visitClassBound() { 119 signatureVisitor.visitClassBound(); 120 return this; 121 } 122 123 @Override 124 public SignatureVisitor visitExceptionType() { 125 signatureVisitor.visitExceptionType(); 126 return this; 127 } 128 129 @Override 130 public SignatureVisitor visitInterface() { 131 signatureVisitor.visitInterface(); 132 return this; 133 } 134 135 @Override 136 public SignatureVisitor visitInterfaceBound() { 137 signatureVisitor.visitInterfaceBound(); 138 return this; 139 } 140 141 @Override 142 public SignatureVisitor visitParameterType() { 143 signatureVisitor.visitParameterType(); 144 return this; 145 } 146 147 @Override 148 public SignatureVisitor visitReturnType() { 149 signatureVisitor.visitReturnType(); 150 return this; 151 } 152 153 @Override 154 public SignatureVisitor visitSuperclass() { 155 signatureVisitor.visitSuperclass(); 156 return this; 157 } 158 159 @Override 160 public void visitTypeArgument() { 161 signatureVisitor.visitTypeArgument(); 162 } 163 164 @Override 165 public SignatureVisitor visitTypeArgument(final char wildcard) { 166 signatureVisitor.visitTypeArgument(wildcard); 167 return this; 168 } 169 170 @Override 171 public void visitEnd() { 172 signatureVisitor.visitEnd(); 173 classNames.remove(classNames.size() - 1); 174 } 175}