1 /*
  2  * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 package jdk.internal.classfile.impl;
 26 
 27 import java.lang.classfile.*;
 28 import java.lang.classfile.attribute.*;
 29 import java.lang.classfile.components.ClassRemapper;
 30 import java.lang.classfile.constantpool.Utf8Entry;
 31 import java.lang.classfile.instruction.ConstantInstruction.LoadConstantInstruction;
 32 import java.lang.classfile.instruction.*;
 33 import java.lang.constant.*;
 34 import java.util.List;
 35 import java.util.function.Function;
 36 
 37 public record ClassRemapperImpl(Function<ClassDesc, ClassDesc> mapFunction) implements ClassRemapper {
 38 
 39     @Override
 40     public void accept(ClassBuilder clb, ClassElement cle) {
 41         switch (cle) {
 42             case FieldModel fm ->
 43                 clb.withField(fm.fieldName().stringValue(), map(
 44                         fm.fieldTypeSymbol()), fb -> fb.transform(fm, asFieldTransform()));
 45             case MethodModel mm ->
 46                 clb.withMethod(mm.methodName().stringValue(), mapMethodDesc(
 47                         mm.methodTypeSymbol()), mm.flags().flagsMask(), mb -> mb.transform(mm, asMethodTransform()));
 48             case Superclass sc ->
 49                 clb.withSuperclass(map(sc.superclassEntry().asSymbol()));
 50             case Interfaces ins ->
 51                 clb.withInterfaceSymbols(Util.mappedList(ins.interfaces(), in ->
 52                         map(in.asSymbol())));
 53             case SignatureAttribute sa ->
 54                 clb.with(SignatureAttribute.of(mapClassSignature(sa.asClassSignature())));
 55             case InnerClassesAttribute ica ->
 56                 clb.with(InnerClassesAttribute.of(ica.classes().stream().map(ici ->
 57                         InnerClassInfo.of(map(ici.innerClass().asSymbol()),
 58                                 ici.outerClass().map(oc -> map(oc.asSymbol())),
 59                                 ici.innerName().map(Utf8Entry::stringValue),
 60                                 ici.flagsMask())).toList()));
 61             case EnclosingMethodAttribute ema ->
 62                 clb.with(EnclosingMethodAttribute.of(map(ema.enclosingClass().asSymbol()),
 63                         ema.enclosingMethodName().map(Utf8Entry::stringValue),
 64                         ema.enclosingMethodTypeSymbol().map(this::mapMethodDesc)));
 65             case RecordAttribute ra ->
 66                 clb.with(RecordAttribute.of(ra.components().stream()
 67                         .map(this::mapRecordComponent).toList()));
 68             case ModuleAttribute ma ->
 69                 clb.with(ModuleAttribute.of(ma.moduleName(), ma.moduleFlagsMask(),
 70                         ma.moduleVersion().orElse(null),
 71                         ma.requires(), ma.exports(), ma.opens(),
 72                         ma.uses().stream().map(ce ->
 73                                 clb.constantPool().classEntry(map(ce.asSymbol()))).toList(),
 74                         ma.provides().stream().map(mp ->
 75                                 ModuleProvideInfo.of(map(mp.provides().asSymbol()),
 76                                         mp.providesWith().stream().map(pw ->
 77                                                 map(pw.asSymbol())).toList())).toList()));
 78             case NestHostAttribute nha ->
 79                 clb.with(NestHostAttribute.of(map(nha.nestHost().asSymbol())));
 80             case NestMembersAttribute nma ->
 81                 clb.with(NestMembersAttribute.ofSymbols(nma.nestMembers().stream()
 82                         .map(nm -> map(nm.asSymbol())).toList()));
 83             case PermittedSubclassesAttribute psa ->
 84                 clb.with(PermittedSubclassesAttribute.ofSymbols(
 85                         psa.permittedSubclasses().stream().map(ps ->
 86                                 map(ps.asSymbol())).toList()));
 87             case LoadableDescriptorsAttribute pa ->
 88                 clb.with(LoadableDescriptorsAttribute.of(pa.loadableDescriptors()));
 89             case RuntimeVisibleAnnotationsAttribute aa ->
 90                 clb.with(RuntimeVisibleAnnotationsAttribute.of(
 91                         mapAnnotations(aa.annotations())));
 92             case RuntimeInvisibleAnnotationsAttribute aa ->
 93                 clb.with(RuntimeInvisibleAnnotationsAttribute.of(
 94                         mapAnnotations(aa.annotations())));
 95             case RuntimeVisibleTypeAnnotationsAttribute aa ->
 96                 clb.with(RuntimeVisibleTypeAnnotationsAttribute.of(
 97                         mapTypeAnnotations(aa.annotations())));
 98             case RuntimeInvisibleTypeAnnotationsAttribute aa ->
 99                 clb.with(RuntimeInvisibleTypeAnnotationsAttribute.of(
100                         mapTypeAnnotations(aa.annotations())));
101             default ->
102                 clb.with(cle);
103         }
104     }
105 
106     @Override
107     public FieldTransform asFieldTransform() {
108         return (FieldBuilder fb, FieldElement fe) -> {
109             switch (fe) {
110                 case SignatureAttribute sa ->
111                     fb.with(SignatureAttribute.of(
112                             mapSignature(sa.asTypeSignature())));
113                 case RuntimeVisibleAnnotationsAttribute aa ->
114                     fb.with(RuntimeVisibleAnnotationsAttribute.of(
115                             mapAnnotations(aa.annotations())));
116                 case RuntimeInvisibleAnnotationsAttribute aa ->
117                     fb.with(RuntimeInvisibleAnnotationsAttribute.of(
118                             mapAnnotations(aa.annotations())));
119                 case RuntimeVisibleTypeAnnotationsAttribute aa ->
120                     fb.with(RuntimeVisibleTypeAnnotationsAttribute.of(
121                             mapTypeAnnotations(aa.annotations())));
122                 case RuntimeInvisibleTypeAnnotationsAttribute aa ->
123                     fb.with(RuntimeInvisibleTypeAnnotationsAttribute.of(
124                             mapTypeAnnotations(aa.annotations())));
125                 default ->
126                     fb.with(fe);
127             }
128         };
129     }
130 
131     @Override
132     public MethodTransform asMethodTransform() {
133         return (MethodBuilder mb, MethodElement me) -> {
134             switch (me) {
135                 case AnnotationDefaultAttribute ada ->
136                     mb.with(AnnotationDefaultAttribute.of(
137                             mapAnnotationValue(ada.defaultValue())));
138                 case CodeModel com ->
139                     mb.transformCode(com, asCodeTransform());
140                 case ExceptionsAttribute ea ->
141                     mb.with(ExceptionsAttribute.ofSymbols(
142                             ea.exceptions().stream().map(ce ->
143                                     map(ce.asSymbol())).toList()));
144                 case SignatureAttribute sa ->
145                     mb.with(SignatureAttribute.of(
146                             mapMethodSignature(sa.asMethodSignature())));
147                 case RuntimeVisibleAnnotationsAttribute aa ->
148                     mb.with(RuntimeVisibleAnnotationsAttribute.of(
149                             mapAnnotations(aa.annotations())));
150                 case RuntimeInvisibleAnnotationsAttribute aa ->
151                     mb.with(RuntimeInvisibleAnnotationsAttribute.of(
152                             mapAnnotations(aa.annotations())));
153                 case RuntimeVisibleParameterAnnotationsAttribute paa ->
154                     mb.with(RuntimeVisibleParameterAnnotationsAttribute.of(
155                             paa.parameterAnnotations().stream()
156                                     .map(this::mapAnnotations).toList()));
157                 case RuntimeInvisibleParameterAnnotationsAttribute paa ->
158                     mb.with(RuntimeInvisibleParameterAnnotationsAttribute.of(
159                             paa.parameterAnnotations().stream()
160                                     .map(this::mapAnnotations).toList()));
161                 case RuntimeVisibleTypeAnnotationsAttribute aa ->
162                     mb.with(RuntimeVisibleTypeAnnotationsAttribute.of(
163                             mapTypeAnnotations(aa.annotations())));
164                 case RuntimeInvisibleTypeAnnotationsAttribute aa ->
165                     mb.with(RuntimeInvisibleTypeAnnotationsAttribute.of(
166                             mapTypeAnnotations(aa.annotations())));
167                 default ->
168                     mb.with(me);
169             }
170         };
171     }
172 
173     @Override
174     public CodeTransform asCodeTransform() {
175         return (CodeBuilder cob, CodeElement coe) -> {
176             switch (coe) {
177                 case FieldInstruction fai ->
178                     cob.fieldAccess(fai.opcode(), map(fai.owner().asSymbol()),
179                             fai.name().stringValue(), map(fai.typeSymbol()));
180                 case InvokeInstruction ii ->
181                     cob.invoke(ii.opcode(), map(ii.owner().asSymbol()),
182                             ii.name().stringValue(), mapMethodDesc(ii.typeSymbol()),
183                             ii.isInterface());
184                 case InvokeDynamicInstruction idi ->
185                     cob.invokedynamic(DynamicCallSiteDesc.of(
186                             mapDirectMethodHandle(idi.bootstrapMethod()), idi.name().stringValue(),
187                             mapMethodDesc(idi.typeSymbol()),
188                             idi.bootstrapArgs().stream().map(this::mapConstantValue).toArray(ConstantDesc[]::new)));
189                 case NewObjectInstruction c ->
190                     cob.new_(map(c.className().asSymbol()));
191                 case NewReferenceArrayInstruction c ->
192                     cob.anewarray(map(c.componentType().asSymbol()));
193                 case NewMultiArrayInstruction c ->
194                     cob.multianewarray(map(c.arrayType().asSymbol()), c.dimensions());
195                 case TypeCheckInstruction c ->
196                     cob.with(TypeCheckInstruction.of(c.opcode(), map(c.type().asSymbol())));
197                 case ExceptionCatch c ->
198                     cob.exceptionCatch(c.tryStart(), c.tryEnd(), c.handler(),c.catchType()
199                             .map(d -> TemporaryConstantPool.INSTANCE.classEntry(map(d.asSymbol()))));
200                 case LocalVariable c ->
201                     cob.localVariable(c.slot(), c.name().stringValue(), map(c.typeSymbol()),
202                             c.startScope(), c.endScope());
203                 case LocalVariableType c ->
204                     cob.localVariableType(c.slot(), c.name().stringValue(),
205                             mapSignature(c.signatureSymbol()), c.startScope(), c.endScope());
206                 case LoadConstantInstruction ldc ->
207                     cob.ldc(mapConstantValue(ldc.constantValue()));
208                 case RuntimeVisibleTypeAnnotationsAttribute aa ->
209                     cob.with(RuntimeVisibleTypeAnnotationsAttribute.of(
210                             mapTypeAnnotations(aa.annotations())));
211                 case RuntimeInvisibleTypeAnnotationsAttribute aa ->
212                     cob.with(RuntimeInvisibleTypeAnnotationsAttribute.of(
213                             mapTypeAnnotations(aa.annotations())));
214                 default ->
215                     cob.with(coe);
216             }
217         };
218     }
219 
220     @Override
221     public ClassDesc map(ClassDesc desc) {
222         if (desc == null) return null;
223         if (desc.isArray()) return map(desc.componentType()).arrayType();
224         if (desc.isPrimitive()) return desc;
225         return mapFunction.apply(desc);
226     }
227 
228     MethodTypeDesc mapMethodDesc(MethodTypeDesc desc) {
229         return MethodTypeDesc.of(map(desc.returnType()),
230                 desc.parameterList().stream().map(this::map).toArray(ClassDesc[]::new));
231     }
232 
233     ClassSignature mapClassSignature(ClassSignature signature) {
234         return ClassSignature.of(mapTypeParams(signature.typeParameters()),
235                 mapSignature(signature.superclassSignature()),
236                 signature.superinterfaceSignatures().stream()
237                         .map(this::mapSignature).toArray(Signature.ClassTypeSig[]::new));
238     }
239 
240     MethodSignature mapMethodSignature(MethodSignature signature) {
241         return MethodSignature.of(mapTypeParams(signature.typeParameters()),
242                 signature.throwableSignatures().stream().map(this::mapSignature).toList(),
243                 mapSignature(signature.result()),
244                 signature.arguments().stream()
245                         .map(this::mapSignature).toArray(Signature[]::new));
246     }
247 
248     RecordComponentInfo mapRecordComponent(RecordComponentInfo component) {
249         return RecordComponentInfo.of(component.name().stringValue(),
250                 map(component.descriptorSymbol()),
251                 component.attributes().stream().map(atr ->
252                     switch (atr) {
253                         case SignatureAttribute sa ->
254                             SignatureAttribute.of(
255                                     mapSignature(sa.asTypeSignature()));
256                         case RuntimeVisibleAnnotationsAttribute aa ->
257                             RuntimeVisibleAnnotationsAttribute.of(
258                                     mapAnnotations(aa.annotations()));
259                         case RuntimeInvisibleAnnotationsAttribute aa ->
260                             RuntimeInvisibleAnnotationsAttribute.of(
261                                     mapAnnotations(aa.annotations()));
262                         case RuntimeVisibleTypeAnnotationsAttribute aa ->
263                             RuntimeVisibleTypeAnnotationsAttribute.of(
264                                     mapTypeAnnotations(aa.annotations()));
265                         case RuntimeInvisibleTypeAnnotationsAttribute aa ->
266                             RuntimeInvisibleTypeAnnotationsAttribute.of(
267                                     mapTypeAnnotations(aa.annotations()));
268                         default -> atr;
269                     }).toList());
270     }
271 
272     DirectMethodHandleDesc mapDirectMethodHandle(DirectMethodHandleDesc dmhd) {
273         return switch (dmhd.kind()) {
274             case GETTER, SETTER, STATIC_GETTER, STATIC_SETTER ->
275                 MethodHandleDesc.ofField(dmhd.kind(), map(dmhd.owner()),
276                         dmhd.methodName(),
277                         map(ClassDesc.ofDescriptor(dmhd.lookupDescriptor())));
278             default ->
279                 MethodHandleDesc.ofMethod(dmhd.kind(), map(dmhd.owner()),
280                         dmhd.methodName(),
281                         mapMethodDesc(MethodTypeDesc.ofDescriptor(dmhd.lookupDescriptor())));
282         };
283     }
284 
285     ConstantDesc mapConstantValue(ConstantDesc value) {
286         return switch (value) {
287             case ClassDesc cd ->
288                 map(cd);
289             case DynamicConstantDesc<?> dcd ->
290                 mapDynamicConstant(dcd);
291             case DirectMethodHandleDesc dmhd ->
292                 mapDirectMethodHandle(dmhd);
293             case MethodTypeDesc mtd ->
294                 mapMethodDesc(mtd);
295             default -> value;
296         };
297     }
298 
299     DynamicConstantDesc<?> mapDynamicConstant(DynamicConstantDesc<?> dcd) {
300         return DynamicConstantDesc.ofNamed(mapDirectMethodHandle(dcd.bootstrapMethod()),
301                 dcd.constantName(),
302                 map(dcd.constantType()),
303                 dcd.bootstrapArgsList().stream().map(this::mapConstantValue).toArray(ConstantDesc[]::new));
304     }
305 
306     @SuppressWarnings("unchecked")
307     <S extends Signature> S mapSignature(S signature) {
308         return (S) switch (signature) {
309             case Signature.ArrayTypeSig ats ->
310                 Signature.ArrayTypeSig.of(mapSignature(ats.componentSignature()));
311             case Signature.ClassTypeSig cts ->
312                 Signature.ClassTypeSig.of(
313                         cts.outerType().map(this::mapSignature).orElse(null),
314                         map(cts.classDesc()),
315                         cts.typeArgs().stream().map(ta -> switch (ta) {
316                             case Signature.TypeArg.Unbounded u -> u;
317                             case Signature.TypeArg.Bounded bta -> Signature.TypeArg.bounded(
318                                     bta.wildcardIndicator(), mapSignature(bta.boundType()));
319                         }).toArray(Signature.TypeArg[]::new));
320             default -> signature;
321         };
322     }
323 
324     List<Annotation> mapAnnotations(List<Annotation> annotations) {
325         return annotations.stream().map(this::mapAnnotation).toList();
326     }
327 
328     Annotation mapAnnotation(Annotation a) {
329         return Annotation.of(map(a.classSymbol()), a.elements().stream().map(el ->
330                 AnnotationElement.of(el.name(), mapAnnotationValue(el.value()))).toList());
331     }
332 
333     AnnotationValue mapAnnotationValue(AnnotationValue val) {
334         return switch (val) {
335             case AnnotationValue.OfAnnotation oa ->
336                 AnnotationValue.ofAnnotation(mapAnnotation(oa.annotation()));
337             case AnnotationValue.OfArray oa ->
338                 AnnotationValue.ofArray(oa.values().stream().map(this::mapAnnotationValue).toList());
339             case AnnotationValue.OfConstant oc -> oc;
340             case AnnotationValue.OfClass oc ->
341                 AnnotationValue.ofClass(map(oc.classSymbol()));
342             case AnnotationValue.OfEnum oe ->
343                 AnnotationValue.ofEnum(map(oe.classSymbol()), oe.constantName().stringValue());
344         };
345     }
346 
347     List<TypeAnnotation> mapTypeAnnotations(List<TypeAnnotation> typeAnnotations) {
348         return typeAnnotations.stream().map(a -> TypeAnnotation.of(a.targetInfo(),
349                 a.targetPath(), mapAnnotation(a.annotation()))).toList();
350     }
351 
352     List<Signature.TypeParam> mapTypeParams(List<Signature.TypeParam> typeParams) {
353         return typeParams.stream().map(tp -> Signature.TypeParam.of(tp.identifier(),
354                 tp.classBound().map(this::mapSignature),
355                 tp.interfaceBounds().stream()
356                         .map(this::mapSignature).toArray(Signature.RefTypeSig[]::new))).toList();
357     }
358 
359 }