Merge pull request #10 from stbischof/conv_def_method
[converter] handle default methods - FELIX-6239
diff --git a/converter/converter/src/main/java/org/osgi/util/converter/ConvertingImpl.java b/converter/converter/src/main/java/org/osgi/util/converter/ConvertingImpl.java
index c9e3722..0733060 100644
--- a/converter/converter/src/main/java/org/osgi/util/converter/ConvertingImpl.java
+++ b/converter/converter/src/main/java/org/osgi/util/converter/ConvertingImpl.java
@@ -17,6 +17,9 @@
package org.osgi.util.converter;
import java.lang.annotation.Annotation;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
@@ -810,6 +813,32 @@
if (cls.isAnnotation()) {
val = method.getDefaultValue();
}
+ else if (method.isDefault())
+ {
+ double javaVersion = Double.parseDouble(
+ System.getProperty("java.class.version"));
+ double java8 = 52.0;
+ if (javaVersion > java8)
+ {
+ val = MethodHandles.lookup().findSpecial(
+ method.getDeclaringClass(), method.getName(),
+ MethodType.methodType(method.getReturnType(),
+ new Class[] {}),
+ method.getDeclaringClass()).bindTo(
+ proxy).invokeWithArguments(args);
+ }
+ else
+ {
+ Constructor<Lookup> c = Lookup.class.getDeclaredConstructor(
+ Class.class);
+ if (!c.isAccessible())
+ {
+ c.setAccessible(true);
+ }
+ val = c.newInstance(cls).in(cls).unreflectSpecial(method,
+ cls).bindTo(proxy).invokeWithArguments(args);
+ }
+ }
if (val == null) {
if (args != null && args.length == 1) {
diff --git a/converter/converter/src/test/java/org/osgi/util/converter/ConverterTest.java b/converter/converter/src/test/java/org/osgi/util/converter/ConverterTest.java
index ef00c13..166b9c9 100644
--- a/converter/converter/src/test/java/org/osgi/util/converter/ConverterTest.java
+++ b/converter/converter/src/test/java/org/osgi/util/converter/ConverterTest.java
@@ -1465,6 +1465,14 @@
assertNotNull(k);
}
+ @Test
+ public void testDefaultInterfaceMethod() throws Throwable
+ {
+ Class<?> clazz = InterfaceWithDefaultMethod.class;
+ InterfaceWithDefaultMethod i = (InterfaceWithDefaultMethod) Converters.standardConverter().convert(
+ new HashMap<String, Object>()).to(clazz);
+ assertEquals(InterfaceWithDefaultMethod.RESULT, i.defaultMethod());
+ }
static interface MyIntf2 {
String code();
Integer value();
diff --git a/converter/converter/src/test/java/org/osgi/util/converter/InterfaceWithDefaultMethod.java b/converter/converter/src/test/java/org/osgi/util/converter/InterfaceWithDefaultMethod.java
new file mode 100644
index 0000000..c8a42ff
--- /dev/null
+++ b/converter/converter/src/test/java/org/osgi/util/converter/InterfaceWithDefaultMethod.java
@@ -0,0 +1,11 @@
+package org.osgi.util.converter;
+
+public interface InterfaceWithDefaultMethod
+{
+ public static final String RESULT = "r";
+
+ public default String defaultMethod()
+ {
+ return RESULT;
+ }
+}
\ No newline at end of file