blob: b40e70297bcbaa00a26ee41d60abd1529e81e0df [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fury.builder;
import com.google.common.reflect.TypeToken;
import java.util.Collections;
import org.apache.fury.Fury;
import org.apache.fury.codegen.CodeGenerator;
import org.apache.fury.codegen.CompileUnit;
import org.apache.fury.meta.ClassDef;
import org.apache.fury.resolver.ClassResolver;
import org.apache.fury.resolver.FieldResolver;
import org.apache.fury.serializer.Serializer;
import org.apache.fury.util.Preconditions;
/** Codec util to create and load jit serializer class. */
public class CodecUtils {
// TODO(chaokunyang) how to uninstall org.apache.fury.codegen/builder classes for graalvm build
// time
// maybe use a temporal URLClassLoader
public static <T> Class<? extends Serializer<T>> loadOrGenObjectCodecClass(
Class<T> cls, Fury fury) {
Preconditions.checkNotNull(fury);
BaseObjectCodecBuilder codecBuilder = new ObjectCodecBuilder(cls, fury);
return loadOrGenCodecClass(cls, fury, codecBuilder);
}
public static <T> Class<? extends Serializer<T>> loadOrGenMetaSharedCodecClass(
Fury fury, Class<T> cls, ClassDef classDef) {
Preconditions.checkNotNull(fury);
MetaSharedCodecBuilder codecBuilder =
new MetaSharedCodecBuilder(TypeToken.of(cls), fury, classDef);
return loadOrGenCodecClass(cls, fury, codecBuilder);
}
public static <T> Class<? extends Serializer<T>> loadOrGenCompatibleCodecClass(
Class<T> cls, Fury fury) {
FieldResolver resolver = FieldResolver.of(fury, cls, true, false);
return loadOrGenCompatibleCodecClass(cls, fury, resolver, Generated.GeneratedSerializer.class);
}
public static <T> Class<? extends Serializer<T>> loadOrGenCompatibleCodecClass(
Class<T> cls, Fury fury, FieldResolver fieldResolver, Class<?> parentSerializerClass) {
Preconditions.checkNotNull(fury);
BaseObjectCodecBuilder codecBuilder =
new CompatibleCodecBuilder(TypeToken.of(cls), fury, fieldResolver, parentSerializerClass);
return loadOrGenCodecClass(cls, fury, codecBuilder);
}
@SuppressWarnings("unchecked")
static <T> Class<? extends Serializer<T>> loadOrGenCodecClass(
Class<T> beanClass, Fury fury, BaseObjectCodecBuilder codecBuilder) {
// use genCodeFunc to avoid gen code repeatedly
CompileUnit compileUnit =
new CompileUnit(
CodeGenerator.getPackage(beanClass),
codecBuilder.codecClassName(beanClass),
codecBuilder::genCode);
CodeGenerator codeGenerator;
ClassLoader beanClassClassLoader =
beanClass.getClassLoader() == null
? Thread.currentThread().getContextClassLoader()
: beanClass.getClassLoader();
if (beanClassClassLoader == null) {
beanClassClassLoader = fury.getClass().getClassLoader();
}
ClassResolver classResolver = fury.getClassResolver();
try {
// generated code imported fury classes.
beanClassClassLoader.loadClass(Fury.class.getName());
codeGenerator = classResolver.getCodeGenerator(beanClassClassLoader);
if (codeGenerator == null) {
codeGenerator = CodeGenerator.getSharedCodeGenerator(beanClassClassLoader);
// Hold strong reference of {@link CodeGenerator}, so the referent of `DelayedRef`
// won't be null.
classResolver.setCodeGenerator(beanClassClassLoader, codeGenerator);
}
} catch (ClassNotFoundException e) {
codeGenerator =
classResolver.getCodeGenerator(beanClassClassLoader, fury.getClass().getClassLoader());
ClassLoader[] loaders = {beanClassClassLoader, fury.getClass().getClassLoader()};
if (codeGenerator == null) {
codeGenerator =
CodeGenerator.getSharedCodeGenerator(
beanClassClassLoader, fury.getClass().getClassLoader());
// Hold strong reference of {@link CodeGenerator}, so the referent of `DelayedRef`
// won't be null.
classResolver.setCodeGenerator(loaders, codeGenerator);
}
}
ClassLoader classLoader =
codeGenerator.compile(
Collections.singletonList(compileUnit), compileState -> compileState.lock.lock());
String className = codecBuilder.codecQualifiedClassName(beanClass);
try {
return (Class<? extends Serializer<T>>) classLoader.loadClass(className);
} catch (ClassNotFoundException e) {
throw new IllegalStateException("Impossible because we just compiled class", e);
}
}
}