Skip to content

Commit

Permalink
Ensure compatibility with Android's limited Java SE subset
Browse files Browse the repository at this point in the history
Android utilizes a subset of the Java SE library, which excludes several packages and classes. This commit removes calls to methods unavailable on Android or wraps them in `try-catch` blocks with appropriate fallbacks. These changes ensure the Easy Random library functions on Android platforms.
  • Loading branch information
mjureczko committed Nov 22, 2024
1 parent b55a318 commit c7fafb0
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 58 deletions.
2 changes: 1 addition & 1 deletion easy-random-bean-validation/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.github.dvgaba</groupId>
<artifactId>easy-random</artifactId>
<version>7.1.0</version>
<version>7.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>easy-random-bean-validation</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion easy-random-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.github.dvgaba</groupId>
<artifactId>easy-random</artifactId>
<version>7.1.0</version>
<version>7.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>easy-random-core</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,11 @@ public <T> T createInstance(Class<T> type, RandomizerContext context) {
private <T> T createNewInstance(final Class<T> type) {
try {
Constructor<T> noArgConstructor = type.getDeclaredConstructor();
noArgConstructor.trySetAccessible();
try {
noArgConstructor.trySetAccessible();
} catch(NoSuchMethodError e) {
noArgConstructor.setAccessible(true);
}
return noArgConstructor.newInstance();
} catch (Exception exception) {
return objenesis.newInstance(type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,13 @@
*/
package org.jeasy.random.randomizers.registry;

import static java.sql.Date.valueOf;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URI;
import java.net.URL;
import java.nio.charset.Charset;
import java.time.LocalDate;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
Expand Down Expand Up @@ -132,4 +131,8 @@ public Randomizer<?> getRandomizer(final Field field) {
public Randomizer<?> getRandomizer(Class<?> type) {
return randomizers.get(type);
}

private static Date valueOf(LocalDate date) {
return new Date(date.getYear() - 1900, date.getMonthValue() -1, date.getDayOfMonth());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import java.util.concurrent.*;
import java.util.function.Supplier;
import java.util.stream.Stream;

import org.jeasy.random.ObjectCreationException;
import org.jeasy.random.annotation.RandomizerArgument;
import org.jeasy.random.api.Randomizer;
Expand All @@ -42,20 +43,22 @@
/**
* Reflection utility methods.
*
* <strong>This class is intended for internal use only. All public methods
* (except {@link ReflectionUtils#asRandomizer(java.util.function.Supplier)}
* might change between minor versions without notice.</strong>
* <strong>This class is intended for internal use only. All public methods
* (except {@link ReflectionUtils#asRandomizer(java.util.function.Supplier)}
* might change between minor versions without notice.</strong>
*
* @author Mahmoud Ben Hassine (mahmoud.benhassine@icloud.com)
*/
public final class ReflectionUtils {

private ReflectionUtils() {}
private ReflectionUtils() {
}

/**
* Create a dynamic proxy that adapts the given {@link Supplier} to a {@link Randomizer}.
*
* @param supplier to adapt
* @param <T> target type
* @param <T> target type
* @return the proxy randomizer
*/
@SuppressWarnings("unchecked")
Expand All @@ -80,9 +83,9 @@ public Object invoke(final Object proxy, final Method method, final Object[] arg
}

return (Randomizer<T>) Proxy.newProxyInstance(
Randomizer.class.getClassLoader(),
new Class[] { Randomizer.class },
new RandomizerProxy(supplier)
Randomizer.class.getClassLoader(),
new Class[]{Randomizer.class},
new RandomizerProxy(supplier)
);
}

Expand Down Expand Up @@ -124,7 +127,7 @@ public static List<Field> getInheritedFields(Class<?> type) {
* @throws IllegalAccessException if the property cannot be set
*/
public static void setProperty(final Object object, final Field field, final Object value)
throws IllegalAccessException, InvocationTargetException {
throws IllegalAccessException, InvocationTargetException {
try {
Optional<Method> setter = getWriteMethod(field);
if (setter.isPresent()) {
Expand All @@ -147,7 +150,7 @@ public static void setProperty(final Object object, final Field field, final Obj
* @throws IllegalAccessException if the property cannot be set
*/
public static void setFieldValue(final Object object, final Field field, final Object value)
throws IllegalAccessException {
throws IllegalAccessException {
boolean access = field.trySetAccessible();
field.set(object, value);
field.setAccessible(access);
Expand All @@ -162,10 +165,15 @@ public static void setFieldValue(final Object object, final Field field, final O
* @throws IllegalAccessException if field cannot be accessed
*/
public static Object getFieldValue(final Object object, final Field field) throws IllegalAccessException {
boolean access = field.trySetAccessible();
Object value = field.get(object);
field.setAccessible(access);
return value;
try {
boolean access = field.trySetAccessible();
Object value = field.get(object);
field.setAccessible(access);
return value;
} catch (NoSuchMethodError e) {
field.setAccessible(true);
return field.get(object);
}
}

/**
Expand Down Expand Up @@ -193,7 +201,7 @@ public static Class<?> getWrapperType(Class<?> primitiveType) {
* @throws IllegalAccessException if field cannot be accessed
*/
public static boolean isPrimitiveFieldWithDefaultValue(final Object object, final Field field)
throws IllegalAccessException {
throws IllegalAccessException {
Class<?> fieldType = field.getType();
if (!fieldType.isPrimitive()) {
return false;
Expand Down Expand Up @@ -329,10 +337,10 @@ public static boolean isPopulatable(final Type type) {
*/
public static boolean isIntrospectable(final Class<?> type) {
return (
!isEnumType(type) &&
!isArrayType(type) &&
!(isCollectionType(type) && isJdkBuiltIn(type)) &&
!(isMapType(type) && isJdkBuiltIn(type))
!isEnumType(type) &&
!isArrayType(type) &&
!(isCollectionType(type) && isJdkBuiltIn(type)) &&
!(isMapType(type) && isJdkBuiltIn(type))
);
}

Expand Down Expand Up @@ -421,11 +429,11 @@ public static List<Class<?>> filterSameParameterizedTypes(final List<Class<?>> t
for (Class<?> currentConcreteType : types) {
List<Type[]> actualTypeArguments = getActualTypeArgumentsOfGenericInterfaces(currentConcreteType);
typesWithSameParameterizedTypes.addAll(
actualTypeArguments
.stream()
.filter(currentTypeArguments -> Arrays.equals(fieldArugmentTypes, currentTypeArguments))
.map(currentTypeArguments -> currentConcreteType)
.toList()
actualTypeArguments
.stream()
.filter(currentTypeArguments -> Arrays.equals(fieldArugmentTypes, currentTypeArguments))
.map(currentTypeArguments -> currentConcreteType)
.toList()
);
}
return typesWithSameParameterizedTypes;
Expand All @@ -436,29 +444,29 @@ public static List<Class<?>> filterSameParameterizedTypes(final List<Class<?>> t
/**
* Looks for given annotationType on given field or read method for field.
*
* @param field field to check
* @param field field to check
* @param annotationType Type of annotation you're looking for.
* @param <T> the actual type of annotation
* @param <T> the actual type of annotation
* @return given annotation if field or read method has this annotation or null.
*/
public static <T extends Annotation> T getAnnotation(Field field, Class<T> annotationType) {
return field.getAnnotation(annotationType) == null
? getAnnotationFromReadMethod(getReadMethod(field).orElse(null), annotationType)
: field.getAnnotation(annotationType);
? getAnnotationFromReadMethod(getReadMethod(field).orElse(null), annotationType)
: field.getAnnotation(annotationType);
}

/**
* Checks if field or corresponding read method is annotated with given annotationType.
*
* @param field Field to check
* @param field Field to check
* @param annotationType Annotation you're looking for.
* @return true if field or read method it annotated with given annotationType or false.
*/
public static boolean isAnnotationPresent(Field field, Class<? extends Annotation> annotationType) {
final Optional<Method> readMethod = getReadMethod(field);
return (
field.isAnnotationPresent(annotationType) ||
(readMethod.isPresent() && readMethod.get().isAnnotationPresent(annotationType))
field.isAnnotationPresent(annotationType) ||
(readMethod.isPresent() && readMethod.get().isAnnotationPresent(annotationType))
);
}

Expand Down Expand Up @@ -494,7 +502,8 @@ public static Collection<?> getEmptyImplementationForCollectionInterface(final C

/**
* Create an empty collection for the given type.
* @param fieldType for which an empty collection should we created
*
* @param fieldType for which an empty collection should we created
* @param initialSize initial size of the collection
* @return empty collection
*/
Expand All @@ -504,7 +513,7 @@ public static Collection<?> createEmptyCollectionForType(Class<?> fieldType, int
try {
collection = (Collection<?>) fieldType.getDeclaredConstructor().newInstance();
} catch (
InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e
InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e
) {
if (fieldType.equals(ArrayBlockingQueue.class)) {
collection = new ArrayBlockingQueue<>(initialSize);
Expand All @@ -517,6 +526,7 @@ public static Collection<?> createEmptyCollectionForType(Class<?> fieldType, int

/**
* Return an empty implementation for the given {@link Map} interface.
*
* @param mapInterface for which an empty implementation should be returned
* @return empty implementation for the given {@link Map} interface.
*/
Expand Down Expand Up @@ -557,6 +567,7 @@ public static Optional<Method> getWriteMethod(Field field) {

/**
* Get the read method for given field.
*
* @param field field to get the read method for.
* @return Optional of read method or empty if field has no read method
*/
Expand Down Expand Up @@ -605,27 +616,27 @@ public static <T> Randomizer<T> newInstance(final Class<T> type, final Randomize
try {
if (notEmpty(randomizerArguments)) {
Optional<Constructor<?>> matchingConstructor = Stream
.of(type.getConstructors())
.filter(constructor ->
hasSameArgumentNumber(constructor, randomizerArguments) &&
hasSameArgumentTypes(constructor, randomizerArguments)
)
.findFirst();
.of(type.getConstructors())
.filter(constructor ->
hasSameArgumentNumber(constructor, randomizerArguments) &&
hasSameArgumentTypes(constructor, randomizerArguments)
)
.findFirst();
if (matchingConstructor.isPresent()) {
return (Randomizer<T>) matchingConstructor.get().newInstance(convertArguments(randomizerArguments));
}
}
return (Randomizer<T>) type.getDeclaredConstructor().newInstance();
} catch (
IllegalAccessException | InvocationTargetException | InstantiationException | NoSuchMethodException e
IllegalAccessException | InvocationTargetException | InstantiationException | NoSuchMethodException e
) {
throw new ObjectCreationException(
format(
"Could not create Randomizer of type: %s with constructor arguments: %s",
type,
Arrays.toString(randomizerArguments)
),
e
format(
"Could not create Randomizer of type: %s with constructor arguments: %s",
type,
Arrays.toString(randomizerArguments)
),
e
);
}
}
Expand All @@ -635,15 +646,15 @@ private static boolean notEmpty(final RandomizerArgument[] randomizerArguments)
}

private static boolean hasSameArgumentNumber(
final Constructor<?> constructor,
final RandomizerArgument[] randomizerArguments
final Constructor<?> constructor,
final RandomizerArgument[] randomizerArguments
) {
return constructor.getParameterCount() == randomizerArguments.length;
}

private static boolean hasSameArgumentTypes(
final Constructor<?> constructor,
final RandomizerArgument[] randomizerArguments
final Constructor<?> constructor,
final RandomizerArgument[] randomizerArguments
) {
Class<?>[] constructorParameterTypes = constructor.getParameterTypes();
for (int i = 0; i < randomizerArguments.length; i++) {
Expand Down
2 changes: 1 addition & 1 deletion easy-random-protobuf/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.github.dvgaba</groupId>
<artifactId>easy-random</artifactId>
<version>7.1.0</version>
<version>7.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>easy-random-protobuf</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion easy-random-randomizers/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.github.dvgaba</groupId>
<artifactId>easy-random</artifactId>
<version>7.1.0</version>
<version>7.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>easy-random-randomizers</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.dvgaba</groupId>
<artifactId>easy-random</artifactId>
<version>7.1.0</version>
<version>7.1.1-SNAPSHOT</version>
<packaging>pom</packaging>

<build>
Expand Down

0 comments on commit c7fafb0

Please sign in to comment.