1
2
3
4
5
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
29
30
31
32
33 public class DataTypeFactory
34 {
35 public static final DataType<String> TEXT_STRING = new SimpleDataType<String>(String.class, MimeTypes.TEXT);
36 public static final DataType<String> XML_STRING = new SimpleDataType<String>(String.class, MimeTypes.XML);
37 public static final DataType<String> JSON_STRING = new SimpleDataType<String>(String.class, MimeTypes.JSON);
38 public static final DataType<String> HTML_STRING = new SimpleDataType<String>(String.class, MimeTypes.HTML);
39 public static final DataType<String> ATOM_STRING = new SimpleDataType<String>(String.class, MimeTypes.ATOM);
40 public static final DataType<String> RSS_STRING = new SimpleDataType<String>(String.class, MimeTypes.RSS);
41
42
43 public static final DataType<String> STRING = new SimpleDataType<String>(String.class);
44 public static final DataType<String> OBJECT = new SimpleDataType<String>(Object.class);
45 public static final DataType<String> BYTE_ARRAY = new SimpleDataType<String>(byte[].class);
46 public static final DataType<String> INPUT_STREAM = new SimpleDataType<String>(InputStream.class);
47 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 return create(type, MimeTypes.ANY);
52 }
53
54 public static <T> DataType<T> createImmutable(Class<T> type)
55 {
56 return new ImmutableDataType<T>(create(type, MimeTypes.ANY));
57 }
58
59 public static <T> DataType<T> createWithEncoding(Class<T> type, String encoding)
60 {
61 DataType<T> dataType = create(type);
62 dataType.setEncoding(encoding);
63 return dataType;
64 }
65
66 public static <T> DataType<T> create(Class<T> type, String mimeType)
67 {
68 if (Collection.class.isAssignableFrom(type))
69 {
70 Class<? extends Collection<?>> collectionType = (Class<? extends Collection<?>>)type;
71 Class<?> itemType = GenericsUtils.getCollectionType(collectionType);
72 if (itemType == null)
73 {
74 return new CollectionDataType(collectionType, mimeType);
75 }
76 else
77 {
78 return new CollectionDataType(collectionType, itemType, mimeType);
79 }
80 }
81
82
83 if (isProxyClass(type))
84 {
85 return new SimpleDataType<T>(type.getInterfaces()[0], mimeType);
86 }
87
88 return new SimpleDataType<T>(type, mimeType);
89 }
90
91 public static <T> DataType create(Class<? extends Collection> collClass, Class<T> itemType)
92 {
93 return create(collClass, itemType, null);
94 }
95
96 public static <T> DataType create(Class<? extends Collection> collClass, Class<T> itemType, String mimeType)
97 {
98 return new CollectionDataType(collClass, itemType, mimeType);
99 }
100
101
102
103
104
105
106
107
108
109
110
111 public static DataType<?> createFromObject(Object o)
112 {
113 Class<?> type = o.getClass();
114 String mime = null;
115 if (o instanceof DataType)
116 {
117 return (DataType<?>)o;
118 }
119 else if (o instanceof MuleMessage)
120 {
121 MuleMessage mm = (MuleMessage) o;
122 type = mm.getPayload().getClass();
123
124
125 mime = mm.getInboundProperty(MuleProperties.CONTENT_TYPE_PROPERTY);
126 if (mime == null)
127 {
128
129 mime = mm.getInboundProperty("ContentType");
130 }
131 }
132 else if (o instanceof DataHandler)
133 {
134 mime = ((DataHandler) o).getContentType();
135 }
136 else if (o instanceof DataSource)
137 {
138 mime = ((DataSource) o).getContentType();
139 }
140
141 if (mime != null)
142 {
143 int i = mime.indexOf(";");
144 mime = (i > -1 ? mime.substring(0, i) : mime);
145
146 }
147 else
148 {
149 mime = MimeTypes.ANY;
150 }
151
152 return create(type, mime);
153 }
154
155 public static DataType<?> createFromReturnType(Method m)
156 {
157 return createFromReturnType(m, null);
158 }
159
160 public static DataType<?> createFromReturnType(Method m, String mimeType)
161 {
162 if (Collection.class.isAssignableFrom(m.getReturnType()))
163 {
164 Class<? extends Collection> cType = (Class<? extends Collection>) m.getReturnType();
165 Class itemType = GenericsUtils.getCollectionReturnType(m);
166
167 if (itemType != null)
168 {
169 return new CollectionDataType(cType, itemType, mimeType);
170 }
171 else
172 {
173 return new CollectionDataType(cType, mimeType);
174 }
175 }
176 else
177 {
178 return new SimpleDataType(m.getReturnType(), mimeType);
179 }
180 }
181
182 public static DataType createFromParameterType(Method m, int paramIndex)
183 {
184 return createFromParameterType(m, paramIndex, null);
185 }
186
187 public static DataType createFromParameterType(Method m, int paramIndex, String mimeType)
188 {
189 if (Collection.class.isAssignableFrom(m.getParameterTypes()[paramIndex]))
190 {
191 Class<? extends Collection> cType = (Class<? extends Collection>) m.getParameterTypes()[paramIndex];
192 Class itemType = GenericsUtils.getCollectionParameterType(new MethodParameter(m, paramIndex));
193
194 if (itemType != null)
195 {
196 return new CollectionDataType(cType, itemType, mimeType);
197 }
198 else
199 {
200 return new CollectionDataType(cType, mimeType);
201 }
202 }
203 else
204 {
205 return new SimpleDataType(m.getParameterTypes()[paramIndex], mimeType);
206 }
207 }
208
209 public static DataType<?> createFromField(Field f)
210 {
211 return createFromField(f, null);
212 }
213
214 public static DataType<?> createFromField(Field f, String mimeType)
215 {
216 if (Collection.class.isAssignableFrom(f.getType()))
217 {
218 Class<? extends Collection> cType = (Class<? extends Collection>) f.getType();
219 Class itemType = GenericsUtils.getCollectionFieldType(f);
220
221 if (itemType != null)
222 {
223 return new CollectionDataType(cType, itemType, mimeType);
224 }
225 else
226 {
227 return new CollectionDataType(cType, mimeType);
228 }
229 }
230 else
231 {
232 return new SimpleDataType(f.getType(), mimeType);
233 }
234 }
235
236
237 private static ConcurrentHashMap proxyClassCache = new ConcurrentHashMap();
238
239
240
241 protected static<T> boolean isProxyClass(Class<T> type)
242 {
243
244
245
246 class ProxyIndicator
247 {
248 private final WeakReference<Class> targetClassRef;
249 private final boolean isProxy;
250
251 ProxyIndicator(Class targetClass, boolean proxy)
252 {
253 this.targetClassRef = new WeakReference<Class>(targetClass);
254 isProxy = proxy;
255 }
256
257 public Class getTargetClass()
258 {
259 return targetClassRef.get();
260 }
261
262 public boolean isProxy()
263 {
264 return isProxy;
265 }
266 }
267
268 String typeName = type.getName();
269 ProxyIndicator indicator = (ProxyIndicator) proxyClassCache.get(typeName);
270 if (indicator != null)
271 {
272 Class classInMap = indicator.getTargetClass();
273 if (classInMap == type)
274 {
275 return indicator.isProxy();
276 }
277 else if (classInMap != null)
278 {
279
280 return Proxy.isProxyClass(type);
281 }
282 }
283
284 boolean isProxy = Proxy.isProxyClass(type);
285 proxyClassCache.put(typeName, new ProxyIndicator(type, isProxy));
286 return isProxy;
287 }
288 }