1 32 package net.sf.retrotranslator.transformer; 33 34 import net.sf.retrotranslator.runtime.asm.*; 35 import net.sf.retrotranslator.runtime.impl.BytecodeTransformer; 36 37 40 class ClassTransformer implements BytecodeTransformer { 41 42 private boolean lazy; 43 private boolean stripsign; 44 private boolean retainflags; 45 private EmbeddingConverter converter; 46 private SystemLogger logger; 47 private ReplacementLocatorFactory factory; 48 49 public ClassTransformer(boolean lazy, boolean stripsign, boolean retainflags, SystemLogger logger, 50 EmbeddingConverter converter, ReplacementLocatorFactory factory) { 51 this.lazy = lazy; 52 this.stripsign = stripsign; 53 this.retainflags = retainflags; 54 this.converter = converter; 55 this.logger = logger; 56 this.factory = factory; 57 } 58 59 public byte[] transform(byte[] bytes, int offset, int length) { 60 if (lazy && !factory.getTarget().isBefore(TransformerTools.getClassVersion(bytes, offset))) { 61 if (offset == 0 && length == bytes.length) return bytes; 62 byte[] result = new byte[length]; 63 System.arraycopy(bytes, offset, result, 0, length); 64 return result; 65 } 66 ClassWriter classWriter = new ClassWriter(true); 67 MethodCounter counter = new MethodCounter(); 68 ClassVisitor visitor = new DuplicateInterfacesVisitor( 69 new VersionVisitor(classWriter, factory.getTarget()), logger, counter); 70 boolean isTarget14 = factory.getTarget() == ClassVersion.VERSION_14; 71 if (isTarget14) { 72 visitor = new ArrayCloningVisitor(new ClassLiteralVisitor(visitor)); 73 } 74 if (converter != null) { 75 visitor = new PrefixingVisitor(visitor, converter); 76 } 77 if (isTarget14 && !factory.isRetainapi()) { 78 visitor = new SpecificReplacementVisitor(visitor, factory.isAdvanced()); 79 } 80 if (!factory.isEmpty()) { 81 visitor = new GeneralReplacementVisitor(new EnumVisitor(visitor), factory.getLocator()); 82 } 83 if (stripsign) { 84 visitor = new SignatureStrippingVisitor(visitor); 85 } 86 new ClassReader(bytes, offset, length).accept(visitor, false); 87 if (counter.containsDuplicates()) { 88 byte[] bytecode = classWriter.toByteArray(); 89 classWriter = new ClassWriter(true); 90 new ClassReader(bytecode).accept(new DuplicateMethodsVisitor(classWriter, logger, counter), false); 91 } 92 return classWriter.toByteArray(isTarget14 && !retainflags); 93 } 94 95 } 96 | Popular Tags |