[ 
https://issues.apache.org/jira/browse/WINK-363?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Georg Sander updated WINK-363:
------------------------------

    Description: 
The ByteArrayProvider is properly registered and is found through 
ProvidersRegistry in Java 6,but not in Java 7. The effect is a consequence of 
Java bug http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5041784 which got 
fixed in Java 7. It can also affect other array entity providers.

Explanation: 

ProvidersRegistry collects the providers for the target type byte[] by checking 
whether the provider type and the target type are assignable. The corresponding 
utilities are in GenericsUtils. To determine the provider type, 
GenericsUtil.getGenericInterfaceParamType retrieves the type from the generic 
interfaces of ByteArrayProvider. The type parameters in the generic interfaces 
are represented as java.lang.reflect.Type in Java 6 but as java.lang.Class in 
Java 7. As consequence, the method GenericsUtils.isAssignableFrom fails to see 
that the type parameter is an array, hence it returns that byte[] is not 
assignable to the retrieved type of ByteArrayProvider.

Here is a simple Java program that explains the difference between Java 6 and 
Java 7. 

In Java 6, the output is:

Type Parameter byte[]
Type Parameter class class 
sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl
Is Generic Array true

In Java 7, the output is:

Type Parameter class [B
Type Parameter class class java.lang.Class
Is Generic Array false

{code}
import java.lang.reflect.GenericArrayType;

import java.lang.reflect.ParameterizedType;

import java.lang.reflect.Type;

public class Test
{

  public static void main(String[] args) {
    Class cls = ByteArrayProvider.class;
    Type[] interfaces = cls.getGenericInterfaces();
    for (Type type : interfaces) {
      if (type instanceof ParameterizedType) {
        ParameterizedType pType = (ParameterizedType)type;
        Type t = pType.getActualTypeArguments()[0];
        System.err.println("Type Parameter " + t);
        System.err.println("Type Parameter class " + t.getClass());
        System.err.println("Is Generic Array " + (t instanceof 
GenericArrayType));
      }
    }
  }
}

interface MessageBodyWriter<T> { }

class ByteArrayProvider implements MessageBodyWriter<byte[]> { }
{code}


I suggest the following fix in GenericsUtils (tested locally in Wink 1.1.3):

{code:title=GenericsUtils.isAssignableFrom|borderStyle=solid}
    public static boolean isAssignableFrom(Type type, Class<?> cls) {
        if (cls.isArray()) {
            if (type instanceof GenericArrayType) {
                GenericArrayType genericArray = (GenericArrayType)type;
                Class<?> componentType = cls.getComponentType();
                return isAssignableFrom(genericArray.getGenericComponentType(), 
componentType);
            }
            else if ((type instanceof Class<?>) && ((Class<?>)type).isArray()) {
                Class<?> componentType1 = ((Class<?>)type).getComponentType();
                Class<?> componentType2 = cls.getComponentType();
                return isAssignableFrom(componentType1, componentType2);
            }
        } else {
            if (type instanceof GenericArrayType == false) {
                Class<?> classType = getClassType(type, null);
                if (classType == Object.class || 
classType.isAssignableFrom(cls)) {
                    return true;
                }
            }
        }
        return false;
    }
{code}


  was:
The ByteArrayProvider is properly registered and is found through 
ProvidersRegistry in Java 6,but not in Java 7. The effect is a consequence of 
Java bug http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5041784 which got 
fixed in Java 7. It can also affect other array entity providers.

Explanation: 

ProvidersRegistry collects the providers for the target type byte[] by checking 
whether the provider type and the target type are assignable. The corresponding 
utilities are in GenericsUtils. To determine the provider type, 
GenericsUtil.getGenericInterfaceParamType retrieves the type from the generic 
interfaces of ByteArrayProvider. The type parameters in the generic interfaces 
are represented as java.lang.reflect.Type in Java 6 but as java.lang.Class in 
Java 7. As consequence, the method GenericsUtils.isAssignableFrom fails to see 
that the type parameter is an array, hence it returns that byte[] is not 
assignable to the retrieved type of ByteArrayProvider.

Here is a simple Java program that explains the difference between Java 6 and 
Java 7. 

In Java 6, the output is:

Type Parameter byte[]
Type Parameter class class 
sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl
Is Generic Array true

In Java 7, the output is:

Type Parameter class [B
Type Parameter class class java.lang.Class
Is Generic Array false

------------------------------------------------
{code}
import java.lang.reflect.GenericArrayType;

import java.lang.reflect.ParameterizedType;

import java.lang.reflect.Type;

public class Test
{

  public static void main(String[] args) {
    Class cls = ByteArrayProvider.class;
    Type[] interfaces = cls.getGenericInterfaces();
    for (Type type : interfaces) {
      if (type instanceof ParameterizedType) {
        ParameterizedType pType = (ParameterizedType)type;
        Type t = pType.getActualTypeArguments()[0];
        System.err.println("Type Parameter " + t);
        System.err.println("Type Parameter class " + t.getClass());
        System.err.println("Is Generic Array " + (t instanceof 
GenericArrayType));
      }
    }
  }
}
{code}

interface MessageBodyWriter<T> { }

class ByteArrayProvider implements MessageBodyWriter<byte[]> { }

-------------------------


I suggest the following fix in GenericsUtils (tested locally in Wink 1.1.3):

{code:title=GenericsUtils.isAssignableFrom|borderStyle=solid}
    public static boolean isAssignableFrom(Type type, Class<?> cls) {
        if (cls.isArray()) {
            if (type instanceof GenericArrayType) {
                GenericArrayType genericArray = (GenericArrayType)type;
                Class<?> componentType = cls.getComponentType();
                return isAssignableFrom(genericArray.getGenericComponentType(), 
componentType);
            }
            else if ((type instanceof Class<?>) && ((Class<?>)type).isArray()) {
                Class<?> componentType1 = ((Class<?>)type).getComponentType();
                Class<?> componentType2 = cls.getComponentType();
                return isAssignableFrom(componentType1, componentType2);
            }
        } else {
            if (type instanceof GenericArrayType == false) {
                Class<?> classType = getClassType(type, null);
                if (classType == Object.class || 
classType.isAssignableFrom(cls)) {
                    return true;
                }
            }
        }
        return false;
    }
{code}


    
> Failure to find array entity providers (such as ByteArrayProvider) in Java 7
> ----------------------------------------------------------------------------
>
>                 Key: WINK-363
>                 URL: https://issues.apache.org/jira/browse/WINK-363
>             Project: Wink
>          Issue Type: Bug
>          Components: Providers
>    Affects Versions: 1.1.3
>         Environment: Linux, Java 1.7.0-b147
>            Reporter: Georg Sander
>
> The ByteArrayProvider is properly registered and is found through 
> ProvidersRegistry in Java 6,but not in Java 7. The effect is a consequence of 
> Java bug http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5041784 which got 
> fixed in Java 7. It can also affect other array entity providers.
> Explanation: 
> ProvidersRegistry collects the providers for the target type byte[] by 
> checking whether the provider type and the target type are assignable. The 
> corresponding utilities are in GenericsUtils. To determine the provider type, 
> GenericsUtil.getGenericInterfaceParamType retrieves the type from the generic 
> interfaces of ByteArrayProvider. The type parameters in the generic 
> interfaces are represented as java.lang.reflect.Type in Java 6 but as 
> java.lang.Class in Java 7. As consequence, the method 
> GenericsUtils.isAssignableFrom fails to see that the type parameter is an 
> array, hence it returns that byte[] is not assignable to the retrieved type 
> of ByteArrayProvider.
> Here is a simple Java program that explains the difference between Java 6 and 
> Java 7. 
> In Java 6, the output is:
> Type Parameter byte[]
> Type Parameter class class 
> sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl
> Is Generic Array true
> In Java 7, the output is:
> Type Parameter class [B
> Type Parameter class class java.lang.Class
> Is Generic Array false
> {code}
> import java.lang.reflect.GenericArrayType;
> import java.lang.reflect.ParameterizedType;
> import java.lang.reflect.Type;
> public class Test
> {
>   public static void main(String[] args) {
>     Class cls = ByteArrayProvider.class;
>     Type[] interfaces = cls.getGenericInterfaces();
>     for (Type type : interfaces) {
>       if (type instanceof ParameterizedType) {
>         ParameterizedType pType = (ParameterizedType)type;
>         Type t = pType.getActualTypeArguments()[0];
>         System.err.println("Type Parameter " + t);
>         System.err.println("Type Parameter class " + t.getClass());
>         System.err.println("Is Generic Array " + (t instanceof 
> GenericArrayType));
>       }
>     }
>   }
> }
> interface MessageBodyWriter<T> { }
> class ByteArrayProvider implements MessageBodyWriter<byte[]> { }
> {code}
> I suggest the following fix in GenericsUtils (tested locally in Wink 1.1.3):
> {code:title=GenericsUtils.isAssignableFrom|borderStyle=solid}
>     public static boolean isAssignableFrom(Type type, Class<?> cls) {
>         if (cls.isArray()) {
>             if (type instanceof GenericArrayType) {
>                 GenericArrayType genericArray = (GenericArrayType)type;
>                 Class<?> componentType = cls.getComponentType();
>                 return 
> isAssignableFrom(genericArray.getGenericComponentType(), componentType);
>             }
>             else if ((type instanceof Class<?>) && 
> ((Class<?>)type).isArray()) {
>                 Class<?> componentType1 = ((Class<?>)type).getComponentType();
>                 Class<?> componentType2 = cls.getComponentType();
>                 return isAssignableFrom(componentType1, componentType2);
>             }
>         } else {
>             if (type instanceof GenericArrayType == false) {
>                 Class<?> classType = getClassType(type, null);
>                 if (classType == Object.class || 
> classType.isAssignableFrom(cls)) {
>                     return true;
>                 }
>             }
>         }
>         return false;
>     }
> {code}

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: 
https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

Reply via email to