Skip to content

Commit

Permalink
Update --
Browse files Browse the repository at this point in the history
  • Loading branch information
ljacqu committed Nov 16, 2023
1 parent 1eaa86f commit 9094e23
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 179 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
import org.jetbrains.annotations.Nullable;

/**
* Represents a property within a bean class, as used in {@link ch.jalu.configme.beanmapper.MapperImpl}.
* Represents a property within a bean class, as used in
* {@link ch.jalu.configme.beanmapper.instantiation.BeanInspector}.
* There, for instance, there is a {@link BeanDescriptionFactory} field responsible for creating bean descriptions.
* <p>
* Default implementation is {@link BeanPropertyDescriptionImpl}.
* Default implementation is {@link FieldProperty}.
*/
public interface BeanPropertyDescription {

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import ch.jalu.configme.beanmapper.ConfigMeMapperException;
import ch.jalu.configme.exception.ConfigMeException;
import ch.jalu.configme.internal.record.ReflectionHelper;
import ch.jalu.typeresolver.FieldUtils;
import ch.jalu.typeresolver.TypeInfo;
import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -40,9 +41,8 @@ public FieldProperty(@NotNull Field field,
}

public void setValue(@NotNull Object bean, @NotNull Object value) {
if (!field.isAccessible()) {
field.setAccessible(true); // todo: exception handling
}
ReflectionHelper.setAccessibleIfNeeded(field);

try {
field.set(bean, value);
} catch (IllegalArgumentException | IllegalAccessException e) {
Expand All @@ -53,9 +53,8 @@ public void setValue(@NotNull Object bean, @NotNull Object value) {

@Override
public @Nullable Object getValue(@NotNull Object bean) {
if (!field.isAccessible()) {
field.setAccessible(true); // todo: exception handling
}
ReflectionHelper.setAccessibleIfNeeded(field);

try {
return field.get(bean);
} catch (IllegalArgumentException | IllegalAccessException e) {
Expand All @@ -67,4 +66,9 @@ public void setValue(@NotNull Object bean, @NotNull Object value) {
public @NotNull BeanPropertyComments getComments() {
return comments;
}

@Override
public @NotNull String toString() {
return "FieldProperty '" + getName() + "' for field '" + FieldUtils.formatField(field) + "'";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import ch.jalu.configme.Comment;
import ch.jalu.configme.SettingsHolder;
import ch.jalu.configme.exception.ConfigMeException;
import ch.jalu.configme.internal.record.ReflectionHelper;
import ch.jalu.configme.properties.Property;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -152,7 +153,7 @@ protected void setCommentForPropertyField(@NotNull Field field, @NotNull String
protected @Nullable Property<?> getPropertyField(@NotNull Field field) {
if (Property.class.isAssignableFrom(field.getType()) && Modifier.isStatic(field.getModifiers())) {
try {
setFieldAccessibleIfNeeded(field);
ReflectionHelper.setAccessibleIfNeeded(field);
return (Property<?>) field.get(null);
} catch (IllegalAccessException e) {
throw new ConfigMeException("Could not fetch field '" + field.getName() + "' from class '"
Expand All @@ -162,27 +163,6 @@ protected void setCommentForPropertyField(@NotNull Field field, @NotNull String
return null;
}

/**
* Sets the Field object to be accessible if needed; this makes the code support constants in Kotlin without the
* {@code @JvmField} annotation. This method only calls {@link Field#setAccessible} if it is needed to avoid
* potential issues with a security manager. Within Java itself, only {@code public static final} property fields
* are expected.
*
* @param field the field to process
*/
protected void setFieldAccessibleIfNeeded(@NotNull Field field) {
try {
if (!Modifier.isPublic(field.getModifiers())) {
field.setAccessible(true);
}
// CHECKSTYLE:OFF
} catch (Exception e) {
// CHECKSTYLE: ON
throw new ConfigMeException("Failed to modify access for field '" + field.getName() + "' from class '"
+ field.getDeclaringClass().getSimpleName() + "'", e);
}
}

protected void collectSectionComments(@NotNull Class<? extends SettingsHolder> clazz) {
SettingsHolder settingsHolder = createSettingsHolderInstance(clazz);
settingsHolder.registerComments(commentsConfiguration);
Expand All @@ -198,7 +178,7 @@ protected void collectSectionComments(@NotNull Class<? extends SettingsHolder> c
protected <T extends SettingsHolder> @NotNull T createSettingsHolderInstance(@NotNull Class<T> clazz) {
try {
Constructor<T> constructor = clazz.getDeclaredConstructor();
constructor.setAccessible(true);
ReflectionHelper.setAccessibleIfNeeded(constructor);
return constructor.newInstance();
} catch (NoSuchMethodException e) {
throw new ConfigMeException("Expected no-args constructor to be available for " + clazz, e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;

/**
Expand Down Expand Up @@ -56,4 +57,20 @@ public class ReflectionHelper {
throw new ConfigMeException("Failed to call " + method + " for " + instance, e);
}
}

/**
* Makes the given accessible object (e.g. a field) accessible if it isn't yet.
*
* @param accessibleObject the reflected object to make accessible (if needed)
*/
public static void setAccessibleIfNeeded(AccessibleObject accessibleObject) {
// #347: Catch InaccessibleObjectException, use #trySetAccessible?
if (!accessibleObject.isAccessible()) {
try {
accessibleObject.setAccessible(true);
} catch (SecurityException e) {
throw new ConfigMeException("Failed to make " + accessibleObject + " accessible", e);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ void shouldThrowForWhenExportNameIsNullForProperty() {

// then
assertThat(ex.getMessage(),
equalTo("Custom name of Bean property '' with getter 'public java.lang.String ch.jalu.configme.samples.beanannotations.BeanWithEmptyName.getAuthor()' may not be empty"));
equalTo("Custom name of FieldProperty '' for field 'BeanWithEmptyName#author' may not be empty"));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
package ch.jalu.configme.beanmapper.propertydescription;

import ch.jalu.configme.beanmapper.ConfigMeMapperException;
import ch.jalu.configme.samples.beanannotations.AnnotatedEntry;
import org.junit.jupiter.api.Test;

import java.util.Collection;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.jupiter.api.Assertions.assertThrows;

/**
* Test for {@link BeanPropertyDescriptionImpl}.
* Test for {@link FieldProperty}.
*/
class BeanPropertyDescriptionImplTest {
class FieldPropertyTest {

@Test
void shouldGetProperties() {
Expand All @@ -29,17 +27,6 @@ void shouldGetProperties() {
assertThat(result1, equalTo(77));
}

@Test
void shouldHandlePropertyGetError() {
// given
BeanPropertyDescription sizeProperty = getDescriptor("size", SampleBean.class);
SampleBean bean = new ThrowingBean();

// when / then
assertThrows(ConfigMeMapperException.class,
() -> sizeProperty.getValue(bean));
}

@Test
void shouldHaveAppropriateStringRepresentation() {
// given
Expand All @@ -52,8 +39,7 @@ void shouldHaveAppropriateStringRepresentation() {
String output = "Found " + hasIdProperty;

// then
assertThat(output, equalTo("Found Bean property 'has-id' with getter "
+ "'public boolean ch.jalu.configme.samples.beanannotations.AnnotatedEntry.getHasId()'"));
assertThat(output, equalTo("Found FieldProperty 'has-id' for field 'AnnotatedEntry#hasId'"));
}

private static BeanPropertyDescription getDescriptor(String name, Class<?> clazz) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
import ch.jalu.configme.properties.Property;
import ch.jalu.configme.samples.ClassWithPrivatePropertyField;
import ch.jalu.configme.samples.TestConfiguration;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
Expand All @@ -24,8 +22,6 @@
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.sameInstance;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.jupiter.api.Assertions.assertThrows;
Expand Down Expand Up @@ -99,42 +95,6 @@ void shouldAccessPrivateField() throws NoSuchFieldException {
assertThat(result, sameInstance(ClassWithPrivatePropertyField.getPrivatePropertyValue()));
}

@Test
void shouldThrowWrappedExceptionIfFieldCannotBeAccessed() throws NoSuchFieldException {
// given
ConfigurationDataBuilder configurationDataBuilder = new ConfigurationDataBuilder() {
@Override
protected void setFieldAccessibleIfNeeded(@NotNull Field field) {
// do nothing
}
};

Field privateProperty = ClassWithPrivatePropertyField.class.getDeclaredField("PRIVATE_INT_PROPERTY");

// when
ConfigMeException ex = assertThrows(ConfigMeException.class,
() -> configurationDataBuilder.getPropertyField(privateProperty));

// then
assertThat(ex.getMessage(), equalTo("Could not fetch field 'PRIVATE_INT_PROPERTY' from class 'ClassWithPrivatePropertyField'. Is it maybe not public?"));
assertThat(ex.getCause(), instanceOf(IllegalAccessException.class));
}

@Test
@Disabled // #347: Enable once we move away from Java 8
void shouldThrowIfFieldCannotBeMadeAccessible() {
// given
ConfigurationDataBuilder configDataBuilder = new ConfigurationDataBuilder();

// when
ConfigMeException ex = assertThrows(ConfigMeException.class,
() -> configDataBuilder.setFieldAccessibleIfNeeded(Integer.class.getDeclaredField("digits")));

// then
assertThat(ex.getMessage(), equalTo("Failed to modify access for field 'digits' from class 'Integer'"));
assertThat(ex.getCause(), notNullValue()); // instanceOf(InaccessibleObjectException.class)
}

@Test
void shouldCreateConfigDataWithPropertiesList() {
// given
Expand Down
Loading

0 comments on commit 9094e23

Please sign in to comment.