[#5442] Support default methods in DefaultRecordMapper.ProxyMapper

This commit is contained in:
lukaseder 2016-07-25 14:04:10 +02:00
parent 2ae8460ef0
commit e7b3740a4b

View File

@ -55,6 +55,7 @@ import static org.jooq.impl.Tools.hasColumnAnnotations;
import static org.jooq.tools.reflect.Reflect.accessible;
import java.beans.ConstructorProperties;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
@ -423,12 +424,15 @@ public class DefaultRecordMapper<R extends Record, E> implements RecordMapper<R,
*/
private class ProxyMapper implements RecordMapper<R, E> {
Constructor<Lookup> constructor;
@Override
public final E map(R record) {
return new MutablePOJOMapper(null, proxy()).map(record);
}
private E proxy() {
final Object[] result = new Object[1];
final Map<String, Object> map = new HashMap<String, Object>();
final InvocationHandler handler = new InvocationHandler() {
@ -439,22 +443,38 @@ public class DefaultRecordMapper<R extends Record, E> implements RecordMapper<R,
int length = (args == null ? 0 : args.length);
if (length == 0 && name.startsWith("get")) {
if (length == 0 && name.startsWith("get"))
return map.get(name.substring(3));
}
else if (length == 0 && name.startsWith("is")) {
else if (length == 0 && name.startsWith("is"))
return map.get(name.substring(2));
}
else if (length == 1 && name.startsWith("set")) {
else if (length == 1 && name.startsWith("set"))
map.put(name.substring(3), args[0]);
return null;
}
// [#5442] Default methods should be invoked to run client implementation
else if (method.isDefault())
try {
if (constructor == null)
constructor = accessible(Lookup.class.getDeclaredConstructor(Class.class, int.class));
Class<?> declaringClass = method.getDeclaringClass();
return constructor
.newInstance(declaringClass, Lookup.PRIVATE)
.unreflectSpecial(method, declaringClass)
.bindTo(result[0])
.invokeWithArguments(args);
}
catch (Throwable e) {
throw new MappingException("Cannot invoke default method", e);
}
return null;
}
};
return (E) Proxy.newProxyInstance(type.getClassLoader(), new Class[] { type }, handler);
result[0] = Proxy.newProxyInstance(type.getClassLoader(), new Class[] { type }, handler);
return (E) result[0];
}
}