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