Skip to content

Commit

Permalink
fixed DefaultmapperImpl stack overflow issue when parse recursive value
Browse files Browse the repository at this point in the history
  • Loading branch information
ppoffice committed Nov 20, 2017
1 parent 02bd149 commit 1a4baef
Show file tree
Hide file tree
Showing 6 changed files with 251 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,40 @@ public <T extends Message> MappingResult mapToDomainField(final FieldResolver fi
final Object domain) throws MappingException {
Object protobufFieldValue = getFieldValue(FieldUtils.createProtobufGetterName(fieldResolver), protobuf);
if (FieldUtils.isComplexType(fieldResolver.getField())) {
return new MappingResult(MappingResult.Result.NESTED_MAPPING, protobufFieldValue, domain);
boolean hasFieldValue = true;
try {
String hasserName = FieldUtils.createProtobufHasserName(fieldResolver);
if (hasserName != null) {
hasFieldValue = hasFieldValue(hasserName, protobuf);
}
} catch (MappingException ignored) {} // not `has` method, continue
if (hasFieldValue) {
return new MappingResult(MappingResult.Result.NESTED_MAPPING, protobufFieldValue, domain);
}
return new MappingResult(MappingResult.Result.MAPPED, null, domain);
}
if (FieldUtils.isCollectionType(fieldResolver.getField())) {
return new MappingResult(MappingResult.Result.COLLECTION_MAPPING, protobufFieldValue, domain);
}
return new MappingResult(MappingResult.Result.MAPPED, protobufFieldValue, domain);
}

private boolean hasFieldValue(final String hasserName, final Object source) throws MappingException {
Class<?> sourceClass = source.getClass();
try {
return (boolean) sourceClass.getMethod(hasserName).invoke(source);
} catch (IllegalAccessException e) {
throw new MappingException(
String.format("Access denied. '%s.%s()'", sourceClass.getName(), hasserName));
} catch (InvocationTargetException e) {
throw new MappingException(
String.format("Can't decide if field has value through '%s.%s()'", sourceClass.getName(), hasserName));
} catch (NoSuchMethodException e) {
throw new MappingException(
String.format("Hasser not found. '%s.%s()'", sourceClass.getName(), hasserName));
}
}

private Object getFieldValue(final String getterName, final Object source) throws MappingException {
Class<?> sourceClass = source.getClass();
try {
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/net/badata/protobuf/converter/utils/FieldUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
*/
public final class FieldUtils {

private static final String HASSER_PREFIX = "has";
private static final String GETTER_PREFIX = "get";
private static final String SETTER_PREFIX = "set";
private static final String BOOLEAN_GETTER_PREFIX = "is";
Expand Down Expand Up @@ -80,6 +81,19 @@ public static boolean isCollectionType(final Class<?> type) {
return Collection.class.isAssignableFrom(type);
}

/**
* Create protobuf getter name for domain field.
*
* @param fieldResolver Domain object field resolver.
* @return Protobuf field getter name.
*/
public static String createProtobufHasserName(final FieldResolver fieldResolver) {
if (isCollectionType(fieldResolver.getProtobufType())) {
return null;
}
return StringUtils.createMethodName(HASSER_PREFIX, fieldResolver.getProtobufName());
}

/**
* Create protobuf getter name for domain field.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ private void createTestProtobuf() {
.addComplexListValue(ConverterProto.PrimitiveTest.newBuilder().setIntValue(1001))
.addComplexSetValue(ConverterProto.PrimitiveTest.newBuilder().setIntValue(1002))
.setBytesValue(ByteString.copyFrom(new byte[]{ 0, 1, 3, 7 }))
.setRecursiveValue(ConverterProto.ConverterTest.newBuilder().setIntValue(1))
.build();
}

Expand Down Expand Up @@ -95,6 +96,10 @@ private void createTestDomain() {
testDomain.setComplexNullableCollectionValue(null);

testDomain.setBytesValue(ByteString.copyFrom(new byte[]{ 0, 1, 3, 7 }));

ConverterDomain.Test nestedValue = new ConverterDomain.Test();
nestedValue.setIntValue(1);
testDomain.setRecursiveValue(nestedValue);
}

private void createIgnoredFieldsMap() {
Expand Down Expand Up @@ -151,7 +156,8 @@ public void testProtobufToDomain() {

Assert.assertTrue(result.getComplexNullableCollectionValue().isEmpty());

Assert.assertEquals(testProtobuf.getBytesValue(), testDomain.getBytesValue());
Assert.assertEquals(testProtobuf.getBytesValue(), result.getBytesValue());
Assert.assertEquals((Object) testProtobuf.getRecursiveValue().getIntValue(), result.getRecursiveValue().getIntValue());
}

@Test
Expand Down Expand Up @@ -208,6 +214,7 @@ public void testDomainToProtobuf() {
result.getComplexSetValue(0).getIntValue());

Assert.assertTrue(result.getComplexNullableCollectionValueList().isEmpty());
Assert.assertEquals((Object) testDomain.getRecursiveValue().getIntValue(), result.getRecursiveValue().getIntValue());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ public static class Test {
private List<PrimitiveTest> complexNullableCollectionValue;
@ProtoField
private ByteString bytesValue;
@ProtoField
private Test recursiveValue;


public Long getLongValue() {
Expand Down Expand Up @@ -172,6 +174,14 @@ public ByteString getBytesValue() {
public void setBytesValue(ByteString bytesValue) {
this.bytesValue = bytesValue;
}

public Test getRecursiveValue() {
return recursiveValue;
}

public void setRecursiveValue(Test recursiveValue) {
this.recursiveValue = recursiveValue;
}
}

@ProtoClass(ConverterProto.PrimitiveTest.class)
Expand Down
Loading

0 comments on commit 1a4baef

Please sign in to comment.