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