Coverage Report - org.mule.transformer.types.DataTypeFactory
 
Classes in this File Line Coverage Branch Coverage Complexity
DataTypeFactory
0%
0/85
0%
0/38
0
DataTypeFactory$1ProxyIndicator
0%
0/6
N/A
0
 
 1  
 /*
 2  
  * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 3  
  * The software in this package is published under the terms of the CPAL v1.0
 4  
  * license, a copy of which has been included with this distribution in the
 5  
  * LICENSE.txt file.
 6  
  */
 7  
 package org.mule.transformer.types;
 8  
 
 9  
 import org.mule.api.MuleMessage;
 10  
 import org.mule.api.config.MuleProperties;
 11  
 import org.mule.api.transformer.DataType;
 12  
 import org.mule.util.generics.GenericsUtils;
 13  
 import org.mule.util.generics.MethodParameter;
 14  
 
 15  
 import java.io.InputStream;
 16  
 import java.lang.ref.WeakReference;
 17  
 import java.lang.reflect.Field;
 18  
 import java.lang.reflect.Method;
 19  
 import java.lang.reflect.Proxy;
 20  
 import java.util.Collection;
 21  
 
 22  
 import javax.activation.DataHandler;
 23  
 import javax.activation.DataSource;
 24  
 
 25  
 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
 26  
 
 27  
 /**
 28  
  * Factory class used to create {@link DataType} objects based on the parameter types passed into
 29  
  * the factory methods.
 30  
  *
 31  
  * @since 3.0
 32  
  */
 33  0
 public class DataTypeFactory
 34  
 {
 35  0
     public static final DataType<String> TEXT_STRING = new SimpleDataType<String>(String.class, MimeTypes.TEXT);
 36  0
     public static final DataType<String> XML_STRING = new SimpleDataType<String>(String.class, MimeTypes.XML);
 37  0
     public static final DataType<String> JSON_STRING = new SimpleDataType<String>(String.class, MimeTypes.JSON);
 38  0
     public static final DataType<String> HTML_STRING = new SimpleDataType<String>(String.class, MimeTypes.HTML);
 39  0
     public static final DataType<String> ATOM_STRING = new SimpleDataType<String>(String.class, MimeTypes.ATOM);
 40  0
     public static final DataType<String> RSS_STRING = new SimpleDataType<String>(String.class, MimeTypes.RSS);
 41  
 
 42  
     //Common Java types
 43  0
     public static final DataType<String> STRING = new SimpleDataType<String>(String.class);
 44  0
     public static final DataType<String> OBJECT = new SimpleDataType<String>(Object.class);
 45  0
     public static final DataType<String> BYTE_ARRAY = new SimpleDataType<String>(byte[].class);
 46  0
     public static final DataType<String> INPUT_STREAM = new SimpleDataType<String>(InputStream.class);
 47  0
     public static final DataType<String> MULE_MESSAGE = new SimpleDataType<String>(MuleMessage.class);
 48  
 
 49  
     public static <T> DataType<T> create(Class<T> type)
 50  
     {
 51  0
         return create(type, MimeTypes.ANY);
 52  
     }
 53  
 
 54  
     public static <T> DataType<T> createImmutable(Class<T> type)
 55  
     {
 56  0
         return new ImmutableDataType<T>(create(type, MimeTypes.ANY));
 57  
     }
 58  
 
 59  
     public static <T> DataType<T> createWithEncoding(Class<T> type, String encoding)
 60  
     {
 61  0
         DataType<T> dataType = create(type);
 62  0
         dataType.setEncoding(encoding);
 63  0
         return dataType;
 64  
     }
 65  
 
 66  
     public static <T> DataType<T> create(Class<T> type, String mimeType)
 67  
     {
 68  0
         if (Collection.class.isAssignableFrom(type))
 69  
         {
 70  0
             Class<? extends Collection<?>> collectionType = (Class<? extends Collection<?>>)type;
 71  0
             Class<?> itemType = GenericsUtils.getCollectionType(collectionType);
 72  0
             if (itemType == null)
 73  
             {
 74  0
                 return new CollectionDataType(collectionType, mimeType);
 75  
             }
 76  
             else
 77  
             {
 78  0
                 return new CollectionDataType(collectionType, itemType, mimeType);
 79  
             }
 80  
         }
 81  
 
 82  
         // Special case where proxies are used for testing
 83  0
         if (isProxyClass(type))
 84  
         {
 85  0
             return new SimpleDataType<T>(type.getInterfaces()[0], mimeType);
 86  
         }
 87  
 
 88  0
         return new SimpleDataType<T>(type, mimeType);
 89  
     }
 90  
 
 91  
     public static <T> DataType create(Class<? extends Collection> collClass, Class<T> itemType)
 92  
     {
 93  0
         return create(collClass, itemType, null);
 94  
     }
 95  
 
 96  
     public static <T> DataType create(Class<? extends Collection> collClass, Class<T> itemType, String mimeType)
 97  
     {
 98  0
         return new CollectionDataType(collClass, itemType, mimeType);
 99  
     }
 100  
 
 101  
     /**
 102  
      * Will create a {@link org.mule.api.transformer.DataType} object from an object instance. This method will check
 103  
      * if the object o is a {@link org.mule.api.MuleMessage} instance and will take the type from the message payload
 104  
      * and check if a mime type is set on the message and used that when constructing the {@link org.mule.api.transformer.DataType}
 105  
      * object.
 106  
      *
 107  
      * @param o an object instance.  This can be a {@link org.mule.api.MuleMessage}, a collection, a proxy instance or any other
 108  
      *          object
 109  
      * @return a data type that represents the object type.
 110  
      */
 111  
     public static DataType<?> createFromObject(Object o)
 112  
     {
 113  0
         Class<?> type = o.getClass();
 114  0
         String mime = null;
 115  0
         if (o instanceof DataType)
 116  
         {
 117  0
             return (DataType<?>)o;
 118  
         }
 119  0
         else if (o instanceof MuleMessage)
 120  
         {
 121  0
             MuleMessage mm = (MuleMessage) o;
 122  0
             type = mm.getPayload().getClass();
 123  
             //TODO better mime handling, see MULE-4639
 124  
             //case insensitive
 125  0
             mime = mm.getInboundProperty(MuleProperties.CONTENT_TYPE_PROPERTY);
 126  0
             if (mime == null)
 127  
             {
 128  
                 //case insensitive
 129  0
                 mime = mm.getInboundProperty("ContentType");
 130  
             }
 131  0
         }
 132  0
         else if (o instanceof DataHandler)
 133  
         {
 134  0
             mime = ((DataHandler) o).getContentType();
 135  
         }
 136  0
         else if (o instanceof DataSource)
 137  
         {
 138  0
             mime = ((DataSource) o).getContentType();
 139  
         }
 140  
 
 141  0
         if (mime != null)
 142  
         {
 143  0
             int i = mime.indexOf(";");
 144  0
             mime = (i > -1 ? mime.substring(0, i) : mime);
 145  
             //TODO set the charset on the DataType when the field is introduced BL-140
 146  0
         }
 147  
         else
 148  
         {
 149  0
             mime = MimeTypes.ANY;
 150  
         }
 151  
 
 152  0
         return create(type, mime);
 153  
     }
 154  
 
 155  
     public static DataType<?> createFromReturnType(Method m)
 156  
     {
 157  0
         return createFromReturnType(m, null);
 158  
     }
 159  
 
 160  
     public static DataType<?> createFromReturnType(Method m, String mimeType)
 161  
     {
 162  0
         if (Collection.class.isAssignableFrom(m.getReturnType()))
 163  
         {
 164  0
             Class<? extends Collection> cType = (Class<? extends Collection>) m.getReturnType();
 165  0
             Class itemType = GenericsUtils.getCollectionReturnType(m);
 166  
 
 167  0
             if (itemType != null)
 168  
             {
 169  0
                 return new CollectionDataType(cType, itemType, mimeType);
 170  
             }
 171  
             else
 172  
             {
 173  0
                 return new CollectionDataType(cType, mimeType);
 174  
             }
 175  
         }
 176  
         else
 177  
         {
 178  0
             return new SimpleDataType(m.getReturnType(), mimeType);
 179  
         }
 180  
     }
 181  
 
 182  
     public static DataType createFromParameterType(Method m, int paramIndex)
 183  
     {
 184  0
         return createFromParameterType(m, paramIndex, null);
 185  
     }
 186  
 
 187  
     public static DataType createFromParameterType(Method m, int paramIndex, String mimeType)
 188  
     {
 189  0
         if (Collection.class.isAssignableFrom(m.getParameterTypes()[paramIndex]))
 190  
         {
 191  0
             Class<? extends Collection> cType = (Class<? extends Collection>) m.getParameterTypes()[paramIndex];
 192  0
             Class itemType = GenericsUtils.getCollectionParameterType(new MethodParameter(m, paramIndex));
 193  
 
 194  0
             if (itemType != null)
 195  
             {
 196  0
                 return new CollectionDataType(cType, itemType, mimeType);
 197  
             }
 198  
             else
 199  
             {
 200  0
                 return new CollectionDataType(cType, mimeType);
 201  
             }
 202  
         }
 203  
         else
 204  
         {
 205  0
             return new SimpleDataType(m.getParameterTypes()[paramIndex], mimeType);
 206  
         }
 207  
     }
 208  
 
 209  
     public static DataType<?> createFromField(Field f)
 210  
     {
 211  0
         return createFromField(f, null);
 212  
     }
 213  
 
 214  
     public static DataType<?> createFromField(Field f, String mimeType)
 215  
     {
 216  0
         if (Collection.class.isAssignableFrom(f.getType()))
 217  
         {
 218  0
             Class<? extends Collection> cType = (Class<? extends Collection>) f.getType();
 219  0
             Class itemType = GenericsUtils.getCollectionFieldType(f);
 220  
 
 221  0
             if (itemType != null)
 222  
             {
 223  0
                 return new CollectionDataType(cType, itemType, mimeType);
 224  
             }
 225  
             else
 226  
             {
 227  0
                 return new CollectionDataType(cType, mimeType);
 228  
             }
 229  
         }
 230  
         else
 231  
         {
 232  0
             return new SimpleDataType(f.getType(), mimeType);
 233  
         }
 234  
     }
 235  
 
 236  
 
 237  0
     private static ConcurrentHashMap proxyClassCache = new ConcurrentHashMap();
 238  
     /**
 239  
      * Cache which classes are proxies.  Very experimental
 240  
      */
 241  
     protected static<T> boolean isProxyClass(Class<T> type)
 242  
     {
 243  
         /**
 244  
          * map value
 245  
          */
 246  
         class ProxyIndicator
 247  
         {
 248  
             private final WeakReference<Class> targetClassRef;
 249  
             private final boolean isProxy;
 250  
 
 251  
             ProxyIndicator(Class targetClass, boolean proxy)
 252  0
             {
 253  0
                 this.targetClassRef = new WeakReference<Class>(targetClass);
 254  0
                 isProxy = proxy;
 255  0
             }
 256  
 
 257  
             public Class getTargetClass()
 258  
             {
 259  0
                 return targetClassRef.get();
 260  
             }
 261  
 
 262  
             public boolean isProxy()
 263  
             {
 264  0
                 return isProxy;
 265  
             }
 266  
         }
 267  
 
 268  0
         String typeName = type.getName();
 269  0
         ProxyIndicator indicator = (ProxyIndicator) proxyClassCache.get(typeName);
 270  0
         if (indicator != null)
 271  
         {
 272  0
             Class classInMap = indicator.getTargetClass();
 273  0
             if (classInMap == type)
 274  
             {
 275  0
                 return indicator.isProxy();
 276  
             }
 277  0
             else if (classInMap != null)
 278  
             {
 279  
                 // We have duplicate class names from different active classloaders.  Skip the optimization for this one
 280  0
                 return Proxy.isProxyClass(type);
 281  
             }
 282  
         }
 283  
         // Either there's no indicator in the map or there's one that is due to be replaced
 284  0
         boolean isProxy = Proxy.isProxyClass(type);
 285  0
         proxyClassCache.put(typeName, new ProxyIndicator(type, isProxy));
 286  0
         return isProxy;
 287  
     }
 288  
 }