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.Annotation;
 28 import java.lang.classfile.AnnotationElement;
 29 import java.lang.classfile.AnnotationValue;
 30 import java.lang.classfile.ClassBuilder;
 31 import java.lang.classfile.ClassElement;
 32 import java.lang.classfile.ClassSignature;
 33 import java.lang.classfile.CodeBuilder;
 34 import java.lang.classfile.CodeElement;
 35 import java.lang.classfile.CodeModel;
 36 import java.lang.classfile.CodeTransform;
 37 import java.lang.classfile.FieldBuilder;
 38 import java.lang.classfile.FieldElement;
 39 import java.lang.classfile.FieldModel;
 40 import java.lang.classfile.FieldTransform;
 41 import java.lang.classfile.Interfaces;
 42 import java.lang.classfile.MethodBuilder;
 43 import java.lang.classfile.MethodElement;
 44 import java.lang.classfile.MethodModel;
 45 import java.lang.classfile.MethodSignature;
 46 import java.lang.classfile.MethodTransform;
 47 import java.lang.classfile.Signature;
 48 import java.lang.classfile.Superclass;
 49 import java.lang.classfile.TypeAnnotation;
 50 import java.lang.classfile.attribute.AnnotationDefaultAttribute;
 51 import java.lang.classfile.attribute.EnclosingMethodAttribute;
 52 import java.lang.classfile.attribute.ExceptionsAttribute;
 53 import java.lang.classfile.attribute.InnerClassInfo;
 54 import java.lang.classfile.attribute.InnerClassesAttribute;
 55 import java.lang.classfile.attribute.LoadableDescriptorsAttribute;
 56 import java.lang.classfile.attribute.ModuleAttribute;
 57 import java.lang.classfile.attribute.ModuleProvideInfo;
 58 import java.lang.classfile.attribute.NestHostAttribute;
 59 import java.lang.classfile.attribute.NestMembersAttribute;
 60 import java.lang.classfile.attribute.PermittedSubclassesAttribute;
 61 import java.lang.classfile.attribute.RecordAttribute;
 62 import java.lang.classfile.attribute.RecordComponentInfo;
 63 import java.lang.classfile.attribute.RuntimeInvisibleAnnotationsAttribute;
 64 import java.lang.classfile.attribute.RuntimeInvisibleParameterAnnotationsAttribute;
 65 import java.lang.classfile.attribute.RuntimeInvisibleTypeAnnotationsAttribute;
 66 import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute;
 67 import java.lang.classfile.attribute.RuntimeVisibleParameterAnnotationsAttribute;
 68 import java.lang.classfile.attribute.RuntimeVisibleTypeAnnotationsAttribute;
 69 import java.lang.classfile.attribute.SignatureAttribute;
 70 import java.lang.classfile.components.ClassRemapper;
 71 import java.lang.classfile.constantpool.Utf8Entry;
 72 import java.lang.classfile.instruction.ConstantInstruction.LoadConstantInstruction;
 73 import java.lang.classfile.instruction.ExceptionCatch;
 74 import java.lang.classfile.instruction.FieldInstruction;
 75 import java.lang.classfile.instruction.InvokeDynamicInstruction;
 76 import java.lang.classfile.instruction.InvokeInstruction;
 77 import java.lang.classfile.instruction.LocalVariable;
 78 import java.lang.classfile.instruction.LocalVariableType;
 79 import java.lang.classfile.instruction.NewMultiArrayInstruction;
 80 import java.lang.classfile.instruction.NewObjectInstruction;
 81 import java.lang.classfile.instruction.NewReferenceArrayInstruction;
 82 import java.lang.classfile.instruction.TypeCheckInstruction;
 83 
 84 import java.lang.constant.ClassDesc;
 85 import java.lang.constant.ConstantDesc;
 86 import java.lang.constant.DirectMethodHandleDesc;
 87 import java.lang.constant.DynamicCallSiteDesc;
 88 import java.lang.constant.DynamicConstantDesc;
 89 import java.lang.constant.MethodHandleDesc;
 90 import java.lang.constant.MethodTypeDesc;
 91 import java.util.List;
 92 import java.util.function.Function;
 93 
 94 public record ClassRemapperImpl(Function<ClassDesc, ClassDesc> mapFunction) implements ClassRemapper {
 95 
 96     @Override
 97     public void accept(ClassBuilder clb, ClassElement cle) {
 98         switch (cle) {
 99             case FieldModel fm ->
100                 clb.withField(fm.fieldName().stringValue(), map(
101                         fm.fieldTypeSymbol()), fb ->
102                                 fm.forEachElement(asFieldTransform().resolve(fb).consumer()));
103             case MethodModel mm ->
104                 clb.withMethod(mm.methodName().stringValue(), mapMethodDesc(
105                         mm.methodTypeSymbol()), mm.flags().flagsMask(), mb ->
106                                 mm.forEachElement(asMethodTransform().resolve(mb).consumer()));
107             case Superclass sc ->
108                 clb.withSuperclass(map(sc.superclassEntry().asSymbol()));
109             case Interfaces ins ->
110                 clb.withInterfaceSymbols(Util.mappedList(ins.interfaces(), in ->
111                         map(in.asSymbol())));
112             case SignatureAttribute sa ->
113                 clb.with(SignatureAttribute.of(mapClassSignature(sa.asClassSignature())));
114             case InnerClassesAttribute ica ->
115                 clb.with(InnerClassesAttribute.of(ica.classes().stream().map(ici ->
116                         InnerClassInfo.of(map(ici.innerClass().asSymbol()),
117                                 ici.outerClass().map(oc -> map(oc.asSymbol())),
118                                 ici.innerName().map(Utf8Entry::stringValue),
119                                 ici.flagsMask())).toList()));
120             case EnclosingMethodAttribute ema ->
121                 clb.with(EnclosingMethodAttribute.of(map(ema.enclosingClass().asSymbol()),
122                         ema.enclosingMethodName().map(Utf8Entry::stringValue),
123                         ema.enclosingMethodTypeSymbol().map(this::mapMethodDesc)));
124             case RecordAttribute ra ->
125                 clb.with(RecordAttribute.of(ra.components().stream()
126                         .map(this::mapRecordComponent).toList()));
127             case ModuleAttribute ma ->
128                 clb.with(ModuleAttribute.of(ma.moduleName(), ma.moduleFlagsMask(),
129                         ma.moduleVersion().orElse(null),
130                         ma.requires(), ma.exports(), ma.opens(),
131                         ma.uses().stream().map(ce ->
132                                 clb.constantPool().classEntry(map(ce.asSymbol()))).toList(),
133                         ma.provides().stream().map(mp ->
134                                 ModuleProvideInfo.of(map(mp.provides().asSymbol()),
135                                         mp.providesWith().stream().map(pw ->
136                                                 map(pw.asSymbol())).toList())).toList()));
137             case NestHostAttribute nha ->
138                 clb.with(NestHostAttribute.of(map(nha.nestHost().asSymbol())));
139             case NestMembersAttribute nma ->
140                 clb.with(NestMembersAttribute.ofSymbols(nma.nestMembers().stream()
141                         .map(nm -> map(nm.asSymbol())).toList()));
142             case PermittedSubclassesAttribute psa ->
143                 clb.with(PermittedSubclassesAttribute.ofSymbols(
144                         psa.permittedSubclasses().stream().map(ps ->
145                                 map(ps.asSymbol())).toList()));
146             case LoadableDescriptorsAttribute pa ->
147                 clb.with(LoadableDescriptorsAttribute.of(pa.loadableDescriptors()));
148             case RuntimeVisibleAnnotationsAttribute aa ->
149                 clb.with(RuntimeVisibleAnnotationsAttribute.of(
150                         mapAnnotations(aa.annotations())));
151             case RuntimeInvisibleAnnotationsAttribute aa ->
152                 clb.with(RuntimeInvisibleAnnotationsAttribute.of(
153                         mapAnnotations(aa.annotations())));
154             case RuntimeVisibleTypeAnnotationsAttribute aa ->
155                 clb.with(RuntimeVisibleTypeAnnotationsAttribute.of(
156                         mapTypeAnnotations(aa.annotations())));
157             case RuntimeInvisibleTypeAnnotationsAttribute aa ->
158                 clb.with(RuntimeInvisibleTypeAnnotationsAttribute.of(
159                         mapTypeAnnotations(aa.annotations())));
160             default ->
161                 clb.with(cle);
162         }
163     }
164 
165     @Override
166     public FieldTransform asFieldTransform() {
167         return (FieldBuilder fb, FieldElement fe) -> {
168             switch (fe) {
169                 case SignatureAttribute sa ->
170                     fb.with(SignatureAttribute.of(
171                             mapSignature(sa.asTypeSignature())));
172                 case RuntimeVisibleAnnotationsAttribute aa ->
173                     fb.with(RuntimeVisibleAnnotationsAttribute.of(
174                             mapAnnotations(aa.annotations())));
175                 case RuntimeInvisibleAnnotationsAttribute aa ->
176                     fb.with(RuntimeInvisibleAnnotationsAttribute.of(
177                             mapAnnotations(aa.annotations())));
178                 case RuntimeVisibleTypeAnnotationsAttribute aa ->
179                     fb.with(RuntimeVisibleTypeAnnotationsAttribute.of(
180                             mapTypeAnnotations(aa.annotations())));
181                 case RuntimeInvisibleTypeAnnotationsAttribute aa ->
182                     fb.with(RuntimeInvisibleTypeAnnotationsAttribute.of(
183                             mapTypeAnnotations(aa.annotations())));
184                 default ->
185                     fb.with(fe);
186             }
187         };
188     }
189 
190     @Override
191     public MethodTransform asMethodTransform() {
192         return (MethodBuilder mb, MethodElement me) -> {
193             switch (me) {
194                 case AnnotationDefaultAttribute ada ->
195                     mb.with(AnnotationDefaultAttribute.of(
196                             mapAnnotationValue(ada.defaultValue())));
197                 case CodeModel com ->
198                     mb.transformCode(com, asCodeTransform());
199                 case ExceptionsAttribute ea ->
200                     mb.with(ExceptionsAttribute.ofSymbols(
201                             ea.exceptions().stream().map(ce ->
202                                     map(ce.asSymbol())).toList()));
203                 case SignatureAttribute sa ->
204                     mb.with(SignatureAttribute.of(
205                             mapMethodSignature(sa.asMethodSignature())));
206                 case RuntimeVisibleAnnotationsAttribute aa ->
207                     mb.with(RuntimeVisibleAnnotationsAttribute.of(
208                             mapAnnotations(aa.annotations())));
209                 case RuntimeInvisibleAnnotationsAttribute aa ->
210                     mb.with(RuntimeInvisibleAnnotationsAttribute.of(
211                             mapAnnotations(aa.annotations())));
212                 case RuntimeVisibleParameterAnnotationsAttribute paa ->
213                     mb.with(RuntimeVisibleParameterAnnotationsAttribute.of(
214                             paa.parameterAnnotations().stream()
215                                     .map(this::mapAnnotations).toList()));
216                 case RuntimeInvisibleParameterAnnotationsAttribute paa ->
217                     mb.with(RuntimeInvisibleParameterAnnotationsAttribute.of(
218                             paa.parameterAnnotations().stream()
219                                     .map(this::mapAnnotations).toList()));
220                 case RuntimeVisibleTypeAnnotationsAttribute aa ->
221                     mb.with(RuntimeVisibleTypeAnnotationsAttribute.of(
222                             mapTypeAnnotations(aa.annotations())));
223                 case RuntimeInvisibleTypeAnnotationsAttribute aa ->
224                     mb.with(RuntimeInvisibleTypeAnnotationsAttribute.of(
225                             mapTypeAnnotations(aa.annotations())));
226                 default ->
227                     mb.with(me);
228             }
229         };
230     }
231 
232     @Override
233     public CodeTransform asCodeTransform() {
234         return (CodeBuilder cob, CodeElement coe) -> {
235             switch (coe) {
236                 case FieldInstruction fai ->
237                     cob.fieldAccess(fai.opcode(), map(fai.owner().asSymbol()),
238                             fai.name().stringValue(), map(fai.typeSymbol()));
239                 case InvokeInstruction ii ->
240                     cob.invoke(ii.opcode(), map(ii.owner().asSymbol()),
241                             ii.name().stringValue(), mapMethodDesc(ii.typeSymbol()),
242                             ii.isInterface());
243                 case InvokeDynamicInstruction idi ->
244                     cob.invokedynamic(DynamicCallSiteDesc.of(
245                             mapDirectMethodHandle(idi.bootstrapMethod()), idi.name().stringValue(),
246                             mapMethodDesc(idi.typeSymbol()),
247                             idi.bootstrapArgs().stream().map(this::mapConstantValue).toArray(ConstantDesc[]::new)));
248                 case NewObjectInstruction c ->
249                     cob.new_(map(c.className().asSymbol()));
250                 case NewReferenceArrayInstruction c ->
251                     cob.anewarray(map(c.componentType().asSymbol()));
252                 case NewMultiArrayInstruction c ->
253                     cob.multianewarray(map(c.arrayType().asSymbol()), c.dimensions());
254                 case TypeCheckInstruction c ->
255                     cob.with(TypeCheckInstruction.of(c.opcode(), map(c.type().asSymbol())));
256                 case ExceptionCatch c ->
257                     cob.exceptionCatch(c.tryStart(), c.tryEnd(), c.handler(),c.catchType()
258                             .map(d -> TemporaryConstantPool.INSTANCE.classEntry(map(d.asSymbol()))));
259                 case LocalVariable c ->
260                     cob.localVariable(c.slot(), c.name().stringValue(), map(c.typeSymbol()),
261                             c.startScope(), c.endScope());
262                 case LocalVariableType c ->
263                     cob.localVariableType(c.slot(), c.name().stringValue(),
264                             mapSignature(c.signatureSymbol()), c.startScope(), c.endScope());
265                 case LoadConstantInstruction ldc ->
266                     cob.loadConstant(ldc.opcode(),
267                             mapConstantValue(ldc.constantValue()));
268                 case RuntimeVisibleTypeAnnotationsAttribute aa ->
269                     cob.with(RuntimeVisibleTypeAnnotationsAttribute.of(
270                             mapTypeAnnotations(aa.annotations())));
271                 case RuntimeInvisibleTypeAnnotationsAttribute aa ->
272                     cob.with(RuntimeInvisibleTypeAnnotationsAttribute.of(
273                             mapTypeAnnotations(aa.annotations())));
274                 default ->
275                     cob.with(coe);
276             }
277         };
278     }
279 
280     @Override
281     public ClassDesc map(ClassDesc desc) {
282         if (desc == null) return null;
283         if (desc.isArray()) return map(desc.componentType()).arrayType();
284         if (desc.isPrimitive()) return desc;
285         return mapFunction.apply(desc);
286     }
287 
288     MethodTypeDesc mapMethodDesc(MethodTypeDesc desc) {
289         return MethodTypeDesc.of(map(desc.returnType()),
290                 desc.parameterList().stream().map(this::map).toArray(ClassDesc[]::new));
291     }
292 
293     ClassSignature mapClassSignature(ClassSignature signature) {
294         return ClassSignature.of(mapTypeParams(signature.typeParameters()),
295                 mapSignature(signature.superclassSignature()),
296                 signature.superinterfaceSignatures().stream()
297                         .map(this::mapSignature).toArray(Signature.ClassTypeSig[]::new));
298     }
299 
300     MethodSignature mapMethodSignature(MethodSignature signature) {
301         return MethodSignature.of(mapTypeParams(signature.typeParameters()),
302                 signature.throwableSignatures().stream().map(this::mapSignature).toList(),
303                 mapSignature(signature.result()),
304                 signature.arguments().stream()
305                         .map(this::mapSignature).toArray(Signature[]::new));
306     }
307 
308     RecordComponentInfo mapRecordComponent(RecordComponentInfo component) {
309         return RecordComponentInfo.of(component.name().stringValue(),
310                 map(component.descriptorSymbol()),
311                 component.attributes().stream().map(atr ->
312                     switch (atr) {
313                         case SignatureAttribute sa ->
314                             SignatureAttribute.of(
315                                     mapSignature(sa.asTypeSignature()));
316                         case RuntimeVisibleAnnotationsAttribute aa ->
317                             RuntimeVisibleAnnotationsAttribute.of(
318                                     mapAnnotations(aa.annotations()));
319                         case RuntimeInvisibleAnnotationsAttribute aa ->
320                             RuntimeInvisibleAnnotationsAttribute.of(
321                                     mapAnnotations(aa.annotations()));
322                         case RuntimeVisibleTypeAnnotationsAttribute aa ->
323                             RuntimeVisibleTypeAnnotationsAttribute.of(
324                                     mapTypeAnnotations(aa.annotations()));
325                         case RuntimeInvisibleTypeAnnotationsAttribute aa ->
326                             RuntimeInvisibleTypeAnnotationsAttribute.of(
327                                     mapTypeAnnotations(aa.annotations()));
328                         default -> atr;
329                     }).toList());
330     }
331 
332     DirectMethodHandleDesc mapDirectMethodHandle(DirectMethodHandleDesc dmhd) {
333         return switch (dmhd.kind()) {
334             case GETTER, SETTER, STATIC_GETTER, STATIC_SETTER ->
335                 MethodHandleDesc.ofField(dmhd.kind(), map(dmhd.owner()),
336                         dmhd.methodName(),
337                         map(ClassDesc.ofDescriptor(dmhd.lookupDescriptor())));
338             default ->
339                 MethodHandleDesc.ofMethod(dmhd.kind(), map(dmhd.owner()),
340                         dmhd.methodName(),
341                         mapMethodDesc(MethodTypeDesc.ofDescriptor(dmhd.lookupDescriptor())));
342         };
343     }
344 
345     ConstantDesc mapConstantValue(ConstantDesc value) {
346         return switch (value) {
347             case ClassDesc cd ->
348                 map(cd);
349             case DynamicConstantDesc<?> dcd ->
350                 mapDynamicConstant(dcd);
351             case DirectMethodHandleDesc dmhd ->
352                 mapDirectMethodHandle(dmhd);
353             case MethodTypeDesc mtd ->
354                 mapMethodDesc(mtd);
355             default -> value;
356         };
357     }
358 
359     DynamicConstantDesc<?> mapDynamicConstant(DynamicConstantDesc<?> dcd) {
360         return DynamicConstantDesc.ofNamed(mapDirectMethodHandle(dcd.bootstrapMethod()),
361                 dcd.constantName(),
362                 map(dcd.constantType()),
363                 dcd.bootstrapArgsList().stream().map(this::mapConstantValue).toArray(ConstantDesc[]::new));
364     }
365 
366     @SuppressWarnings("unchecked")
367     <S extends Signature> S mapSignature(S signature) {
368         return (S) switch (signature) {
369             case Signature.ArrayTypeSig ats ->
370                 Signature.ArrayTypeSig.of(mapSignature(ats.componentSignature()));
371             case Signature.ClassTypeSig cts ->
372                 Signature.ClassTypeSig.of(
373                         cts.outerType().map(this::mapSignature).orElse(null),
374                         map(cts.classDesc()),
375                         cts.typeArgs().stream().map(ta -> switch (ta) {
376                             case Signature.TypeArg.Unbounded u -> u;
377                             case Signature.TypeArg.Bounded bta -> Signature.TypeArg.bounded(
378                                     bta.wildcardIndicator(), mapSignature(bta.boundType()));
379                         }).toArray(Signature.TypeArg[]::new));
380             default -> signature;
381         };
382     }
383 
384     List<Annotation> mapAnnotations(List<Annotation> annotations) {
385         return annotations.stream().map(this::mapAnnotation).toList();
386     }
387 
388     Annotation mapAnnotation(Annotation a) {
389         return Annotation.of(map(a.classSymbol()), a.elements().stream().map(el ->
390                 AnnotationElement.of(el.name(), mapAnnotationValue(el.value()))).toList());
391     }
392 
393     AnnotationValue mapAnnotationValue(AnnotationValue val) {
394         return switch (val) {
395             case AnnotationValue.OfAnnotation oa ->
396                 AnnotationValue.ofAnnotation(mapAnnotation(oa.annotation()));
397             case AnnotationValue.OfArray oa ->
398                 AnnotationValue.ofArray(oa.values().stream().map(this::mapAnnotationValue).toList());
399             case AnnotationValue.OfConstant oc -> oc;
400             case AnnotationValue.OfClass oc ->
401                 AnnotationValue.ofClass(map(oc.classSymbol()));
402             case AnnotationValue.OfEnum oe ->
403                 AnnotationValue.ofEnum(map(oe.classSymbol()), oe.constantName().stringValue());
404         };
405     }
406 
407     List<TypeAnnotation> mapTypeAnnotations(List<TypeAnnotation> typeAnnotations) {
408         return typeAnnotations.stream().map(a -> TypeAnnotation.of(a.targetInfo(),
409                 a.targetPath(), map(a.classSymbol()),
410                 a.elements().stream().map(el -> AnnotationElement.of(el.name(),
411                         mapAnnotationValue(el.value()))).toList())).toList();
412     }
413 
414     List<Signature.TypeParam> mapTypeParams(List<Signature.TypeParam> typeParams) {
415         return typeParams.stream().map(tp -> Signature.TypeParam.of(tp.identifier(),
416                 tp.classBound().map(this::mapSignature),
417                 tp.interfaceBounds().stream()
418                         .map(this::mapSignature).toArray(Signature.RefTypeSig[]::new))).toList();
419     }
420 
421 }