Skip to content

Commit

Permalink
fix Illegal reflective acces in Java 11
Browse files Browse the repository at this point in the history
  • Loading branch information
agliznetsov authored and elaatifi committed Oct 3, 2021
1 parent 232848f commit c622bf3
Show file tree
Hide file tree
Showing 11 changed files with 508 additions and 461 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ma.glasnost.orika.generated;

/**
* This interface is used as a parameter during class generation in order to be able to avoid Illegal reflective access
*/
public interface GeneratedPackageClass {
}
Original file line number Diff line number Diff line change
Expand Up @@ -1395,7 +1395,7 @@ private void buildClassMapRegistry() {
for (final MapperKey parentMapperKey : classMap.getUsedMappers()) {
ClassMap<Object, Object> usedClassMap = classMapsDictionary.get(parentMapperKey);
if (usedClassMap == null) {
throw exceptionUtil.newMappingException("Cannot find class mapping using mapper : " + classMap.getMapperClassName());
throw exceptionUtil.newMappingException("Cannot find class mapping using mapper : " + classMap.getMapperSimpleClassName());
}
usedClassMapSet.add(usedClassMap);
}
Expand Down Expand Up @@ -1501,7 +1501,7 @@ private void initializeUsedMappers(Mapper<?, ?> mapper, ClassMap<?, ?> classMap,
private void collectUsedMappers(ClassMap<?, ?> classMap, Set<Mapper<Object, Object>> parentMappers, MapperKey parentMapperKey, MappingContext context) {
Mapper<Object, Object> parentMapper = lookupMapper(parentMapperKey, context);
if (parentMapper == null) {
throw exceptionUtil.newMappingException("Cannot find used mappers for : " + classMap.getMapperClassName());
throw exceptionUtil.newMappingException("Cannot find used mappers for : " + classMap.getMapperSimpleClassName());
}
if (parentMapper instanceof MultipleMapperWrapper) {
MultipleMapperWrapper multiMapperWrapper = (MultipleMapperWrapper) parentMapper;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,6 @@ public Class<?> compileClass(SourceCodeContext sourceCode) throws SourceCodeGene
try {
writeSourceFile(sourceCode);

// TODO: do we really need this check here?
// assureTypeIsAccessible(this.getClass());

Boolean existing = superClasses.put(sourceCode.getSuperClass(), true);
if (existing == null || !existing) {
classPool.insertClassPath(new ClassClassPath(sourceCode.getSuperClass()));
Expand Down Expand Up @@ -242,8 +239,12 @@ public Class<?> compileClass(SourceCodeContext sourceCode) throws SourceCodeGene
}

}
compiledClass = byteCodeClass.toClass(Thread.currentThread().getContextClassLoader(), this.getClass().getProtectionDomain());


//this code causes Illegal reflective access in Java 11
//compiledClass = byteCodeClass.toClass(Thread.currentThread().getContextClassLoader(), this.getClass().getProtectionDomain());

compiledClass = byteCodeClass.toClass(sourceCode.getPackageNeighbour());

writeClassFile(sourceCode, byteCodeClass);

} catch (NotFoundException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,11 @@ public GeneratedMapperBase build(ClassMap<?, ?> classMap, MappingContext context
logDetails.append("Generating new mapper for (").append(srcName).append(", ").append(dstName).append(")");
}

final SourceCodeContext mapperCode = new SourceCodeContext(classMap.getMapperClassName(), GeneratedMapperBase.class, context,
final SourceCodeContext mapperCode = new SourceCodeContext(
classMap.getMapperSimpleClassName(),
classMap.getMapperPackageNeighbour(),
GeneratedMapperBase.class,
context,
logDetails);

Set<FieldMap> mappedFields = new LinkedHashSet<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import ma.glasnost.orika.metadata.MapperKey;
import ma.glasnost.orika.metadata.Type;
import ma.glasnost.orika.metadata.TypeFactory;
import ma.glasnost.orika.util.ClassHelper;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -74,7 +76,6 @@ public ObjectFactoryGenerator(MapperFactory mapperFactory, ConstructorResolverSt
public GeneratedObjectFactory build(Type<?> type, Type<?> sourceType, MappingContext context) {

String className = type.getSimpleName() + "_" + sourceType.getSimpleName() + "_ObjectFactory" + nameSuffix;
className = prependPackageName(getPackageName(type), className);
try {
StringBuilder logDetails;
if (LOGGER.isDebugEnabled()) {
Expand All @@ -83,8 +84,11 @@ public GeneratedObjectFactory build(Type<?> type, Type<?> sourceType, MappingCon
} else {
logDetails = null;
}

final SourceCodeContext factoryCode = new SourceCodeContext(className, GeneratedObjectFactory.class, context, logDetails);

Class<?> packageNeighbour = ClassHelper.getPackageNeighbour(type, sourceType);
final SourceCodeContext factoryCode = new SourceCodeContext(className,
packageNeighbour,
GeneratedObjectFactory.class, context, logDetails);

UsedTypesContext usedTypes = new UsedTypesContext();
UsedConvertersContext usedConverters = new UsedConvertersContext();
Expand Down Expand Up @@ -114,9 +118,6 @@ private static String getPackageName(Type<?> type) {
Package typePackage = type.getRawType().getPackage();
return typePackage == null ? "" : typePackage.getName();
}
private static String prependPackageName(String packageName, String className) {
return packageName.isEmpty() || packageName.startsWith("java.") ? className : packageName + "." + className;
}

private void addCreateMethod(SourceCodeContext code, UsedTypesContext usedTypes, UsedConvertersContext usedConverters,
UsedMapperFacadesContext usedMappers, Type<?> type, Type<?> sourceType, MappingContext mappingContext, StringBuilder logDetails) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import ma.glasnost.orika.MappingContext;
import ma.glasnost.orika.Properties;
import ma.glasnost.orika.converter.ConverterFactory;
import ma.glasnost.orika.generated.GeneratedPackageClass;
import ma.glasnost.orika.impl.AggregateFilter;
import ma.glasnost.orika.impl.GeneratedObjectBase;
import ma.glasnost.orika.impl.generator.CompilerStrategy.SourceCodeGenerationException;
Expand Down Expand Up @@ -75,6 +76,7 @@ public class SourceCodeContext {
private final List<String> methods;
private final List<String> fields;
private final Class<?> superClass;
private final Class<?> packageNeighbour;

private final UsedTypesContext usedTypes;
private final UsedConvertersContext usedConverters;
Expand All @@ -98,7 +100,8 @@ public class SourceCodeContext {
* @param logDetails
*/
@SuppressWarnings("unchecked")
public SourceCodeContext(final String baseClassName, Class<?> superClass, MappingContext mappingContext, StringBuilder logDetails) {
public SourceCodeContext(final String baseClassName, Class<?> packageNeighbour, Class<?> superClass,
MappingContext mappingContext, StringBuilder logDetails) {

this.mapperFactory = (MapperFactory) mappingContext.getProperty(Properties.MAPPER_FACTORY);
this.codeGenerationStrategy = (CodeGenerationStrategy) mappingContext.getProperty(Properties.CODE_GENERATION_STRATEGY);
Expand All @@ -107,17 +110,17 @@ public SourceCodeContext(final String baseClassName, Class<?> superClass, Mappin
this.filters = (Collection<Filter<Object, Object>>) mappingContext.getProperty(Properties.FILTERS);
this.shouldCaptureFieldContext = (Boolean) mappingContext.getProperty(Properties.CAPTURE_FIELD_CONTEXT);

String safeBaseClassName = baseClassName.replace("[]", "$Array");
this.classSimpleName = baseClassName.replace("[]", "$Array");
this.sourceBuilder = new StringBuilder();
this.superClass = superClass;

int namePos = safeBaseClassName.lastIndexOf(".");
if (namePos > 0) {
this.packageName = safeBaseClassName.substring(0, namePos);
this.classSimpleName = safeBaseClassName.substring(namePos + 1);
if (packageNeighbour != null) {
int namePos = packageNeighbour.getName().lastIndexOf(".");
this.packageName = packageNeighbour.getName().substring(0, namePos);
this.packageNeighbour = packageNeighbour;
} else {
this.packageName = "ma.glasnost.orika.generated";
this.classSimpleName = safeBaseClassName;
this.packageNeighbour = GeneratedPackageClass.class;
}

this.classSimpleName = makeUniqueClassName(this.classSimpleName);
Expand All @@ -138,7 +141,7 @@ public SourceCodeContext(final String baseClassName, Class<?> superClass, Mappin

this.aggregateFieldMaps = new LinkedHashMap<>();
}

private String makeUniqueClassName(String name) {
return name + System.nanoTime() + "$" + UNIQUE_CLASS_INDEX.getAndIncrement();
}
Expand Down Expand Up @@ -185,7 +188,11 @@ public String getClassSimpleName() {
public String getPackageName() {
return packageName;
}


public Class<?> getPackageNeighbour() {
return packageNeighbour;
}

public String getClassName() {
return className;
}
Expand Down
40 changes: 5 additions & 35 deletions core/src/main/java/ma/glasnost/orika/metadata/ClassMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import ma.glasnost.orika.MappedTypePair;
import ma.glasnost.orika.Mapper;
import ma.glasnost.orika.util.ClassHelper;

import java.lang.reflect.Modifier;
import java.util.Collections;
Expand Down Expand Up @@ -160,43 +161,12 @@ public Mapper<A, B> getCustomizedMapper() {
/**
* @return
*/
public String getMapperClassName() {
String className = "Orika_" + getBTypeName() + "_" + getATypeName() + "_Mapper";

boolean aIsPublic = Modifier.isPublic(getAType().getRawType().getModifiers());
boolean bIsPublic = Modifier.isPublic(getBType().getRawType().getModifiers());

if (aIsPublic) {
if (bIsPublic) {
// both public, no package needed
return className;
} else {
// A public, B not --> use package of B
return prependPackageName(getPackageName(getBType()), className);
}
} else {
if (bIsPublic) {
// A not public, B is --> use package of A
return prependPackageName(getPackageName(getAType()), className);
} else {
// both package private --> make sure they're in the same package
String aPackage = getPackageName(getAType());
if (aPackage.equals(getPackageName(getBType()))) {
return prependPackageName(aPackage, className);
} else {
throw new RuntimeException(getAType() + " and " + getBType() + " are both package private but are in different packages");
}
}
}
}

private static String prependPackageName(String packageName, String className) {
return packageName.isEmpty() || packageName.startsWith("java.") ? className : packageName + "." + className;
public Class<?> getMapperPackageNeighbour() {
return ClassHelper.getPackageNeighbour(getAType(), getBType());
}

private static String getPackageName(Type<?> type) {
Package typePackage = type.getRawType().getPackage();
return type == null ? "" : typePackage.getName();
public String getMapperSimpleClassName() {
return "Orika_" + getBTypeName() + "_" + getATypeName() + "_Mapper";
}

/**
Expand Down
Loading

0 comments on commit c622bf3

Please sign in to comment.