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