Converter: bugfix errorHandler which is skipped for proxies
Originally reported on in the Felix community as
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;
@@ -173,7 +176,13 @@ class CustomConverterImpl implements InternalConverter {
}
}
- return del.to(type);
+ T 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 {
@@ -192,6 +201,53 @@ class CustomConverterImpl implements InternalConverter {
}
}
+ @SuppressWarnings("unchecked")
+ private <T> T wrapErrorHandling(final T wrapped, final Type type) {
+ final Class< ? > cls = wrapped.getClass();
+ return (T) Proxy.newProxyInstance(cls.getClassLoader(),
+ cls.getInterfaces(), new InvocationHandler() {
+ @SuppressWarnings("boxing")
+ @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(wrapped,
+ 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);
