Author: davidb
Date: Thu Dec 20 15:36:43 2018
New Revision: 1849408

URL: http://svn.apache.org/viewvc?rev=1849408&view=rev
Log:
FELIX-6006 errorHandler not consulted for conversions implemented via proxies

Modified:
    
felix/trunk/converter/converter/src/main/java/org/osgi/util/converter/CustomConverterImpl.java
    
felix/trunk/converter/converter/src/test/java/org/osgi/util/converter/ConverterTest.java

Modified: 
felix/trunk/converter/converter/src/main/java/org/osgi/util/converter/CustomConverterImpl.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/converter/converter/src/main/java/org/osgi/util/converter/CustomConverterImpl.java?rev=1849408&r1=1849407&r2=1849408&view=diff
==============================================================================
--- 
felix/trunk/converter/converter/src/main/java/org/osgi/util/converter/CustomConverterImpl.java
 (original)
+++ 
felix/trunk/converter/converter/src/main/java/org/osgi/util/converter/CustomConverterImpl.java
 Thu Dec 20 15:36:43 2018
@@ -16,6 +16,9 @@
 
 package org.osgi.util.converter;
 
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
 import java.lang.reflect.Type;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -175,7 +178,12 @@ class CustomConverterImpl implements Int
                                        }
                                }
 
-                               return del.to(type);
+                               Object result = del.to(type);
+                               if (result != null && 
Proxy.isProxyClass(result.getClass()) && errorHandlers.size() > 0) {
+                                   return wrapErrorHandling(result, type);
+                               } else {
+                                   return result;
+                               }
                        } catch (Exception ex) {
                                for (ConverterFunction eh : errorHandlers) {
                                        try {
@@ -194,7 +202,48 @@ class CustomConverterImpl implements Int
                        }
                }
 
-               @Override
+               private Object wrapErrorHandling(final Object wrapped, final 
Type type) {
+                   final Class<?> cls = wrapped.getClass();
+                   return Proxy.newProxyInstance(cls.getClassLoader(), 
cls.getInterfaces(), new InvocationHandler() {
+                @Override
+                public Object invoke(Object proxy, Method method, Object[] 
args) throws Throwable {
+                    Class< ? > mdDecl = method.getDeclaringClass();
+                    if (mdDecl.equals(Object.class)) {
+                        switch (method.getName()) {
+                            case "equals" :
+                                return proxy == args[0];
+                            case "hashCode" :
+                                return System.identityHashCode(proxy);
+                            case "toString" :
+                                return "Proxy for " + cls;
+                            default :
+                                throw new 
UnsupportedOperationException("Method "
+                                        + method + " not supported on proxy 
for "
+                                        + cls);
+                        }
+                    }
+
+                    try {
+                        return method.invoke(wrapped, args);
+                    } catch (Exception ex) {
+                        for (ConverterFunction eh : errorHandlers) {
+                            try {
+                                Object handled = eh.apply(object, type);
+                                if (handled != ConverterFunction.CANNOT_HANDLE)
+                                    return handled;
+                            } catch (RuntimeException re) {
+                                throw re;
+                            } catch (Exception e) {
+                                throw new RuntimeException(e);
+                            }
+                        }
+                    }
+                    return null;
+                }
+            });
+        }
+
+        @Override
                public String toString() {
                        return to(String.class);
                }

Modified: 
felix/trunk/converter/converter/src/test/java/org/osgi/util/converter/ConverterTest.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/converter/converter/src/test/java/org/osgi/util/converter/ConverterTest.java?rev=1849408&r1=1849407&r2=1849408&view=diff
==============================================================================
--- 
felix/trunk/converter/converter/src/test/java/org/osgi/util/converter/ConverterTest.java
 (original)
+++ 
felix/trunk/converter/converter/src/test/java/org/osgi/util/converter/ConverterTest.java
 Thu Dec 20 15:36:43 2018
@@ -16,6 +16,13 @@
  */
 package org.osgi.util.converter;
 
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.Version;
+import org.osgi.util.converter.MyDTO.Count;
+import org.osgi.util.converter.MyEmbeddedDTO.Alpha;
+
 import java.lang.reflect.Type;
 import java.math.BigDecimal;
 import java.math.BigInteger;
@@ -60,13 +67,6 @@ import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.osgi.framework.Version;
-import org.osgi.util.converter.MyDTO.Count;
-import org.osgi.util.converter.MyEmbeddedDTO.Alpha;
-
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -442,6 +442,23 @@ public class ConverterTest {
     }
 
     @Test
+    public void testCustomErrorHandlingProxy() {
+        ConverterFunction errHandler = new ConverterFunction() {
+            @Override
+            public Object apply(Object obj, Type targetType) throws Exception {
+                return 123;
+            }
+        };
+        ConverterBuilder cb = converter.newConverterBuilder();
+        Converter c = cb.errorHandler(errHandler).build();
+
+        Map<?,?> m = new HashMap<>();
+
+        MyIntf i = c.convert(m).to(MyIntf.class);
+        assertEquals(123, i.value());
+    }
+
+    @Test
     public void testUUIDConversion() {
         UUID uuid = UUID.randomUUID();
         String s = converter.convert(uuid).to(String.class);


Reply via email to