1
2
3
4
5
6
7
8
9
10 package org.mule.registry;
11
12 import org.mule.api.MuleContext;
13 import org.mule.api.MuleException;
14 import org.mule.api.context.MuleContextAware;
15 import org.mule.api.lifecycle.Disposable;
16 import org.mule.api.lifecycle.Initialisable;
17 import org.mule.api.lifecycle.InitialisationException;
18 import org.mule.api.registry.ResolverException;
19 import org.mule.api.registry.TransformerResolver;
20 import org.mule.api.transformer.DataType;
21 import org.mule.api.transformer.DiscoverableTransformer;
22 import org.mule.api.transformer.Transformer;
23 import org.mule.config.i18n.CoreMessages;
24 import org.mule.transformer.TransformerChain;
25 import org.mule.transformer.TransformerWeighting;
26 import org.mule.transformer.simple.ObjectToByteArray;
27 import org.mule.transformer.simple.ObjectToString;
28 import org.mule.transformer.types.SimpleDataType;
29
30 import java.util.List;
31 import java.util.Map;
32 import java.util.concurrent.ConcurrentHashMap;
33
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36
37
38
39
40
41
42 public class TypeBasedTransformerResolver implements TransformerResolver, MuleContextAware, Disposable, Initialisable
43 {
44
45
46
47 protected transient final Log logger = LogFactory.getLog(TypeBasedTransformerResolver.class);
48
49 private ObjectToString objectToString;
50 private ObjectToByteArray objectToByteArray;
51
52 private MuleContext muleContext;
53
54 protected Map<String, Transformer> exactTransformerCache = new ConcurrentHashMap
55
56
57 public void setMuleContext(MuleContext context)
58 {
59 this.muleContext = context;
60 }
61
62 public void initialise() throws InitialisationException
63 {
64 try
65 {
66 objectToString = new ObjectToString();
67 objectToByteArray = new ObjectToByteArray();
68 muleContext.getRegistry().applyProcessorsAndLifecycle(objectToString);
69 muleContext.getRegistry().applyProcessorsAndLifecycle(objectToByteArray);
70 }
71 catch (MuleException e)
72 {
73 throw new InitialisationException(e, this);
74 }
75 }
76
77 public Transformer resolve(DataType source, DataType result) throws ResolverException
78 {
79 Transformer transformer = exactTransformerCache.get(source.toString() + result.toString());
80 if (transformer != null)
81 {
82 return transformer;
83 }
84
85 List<Transformer> trans = muleContext.getRegistry().lookupTransformers(source, result);
86
87 transformer = getNearestTransformerMatch(trans, source.getType(), result.getType());
88
89
90 Transformer secondPass;
91
92 if (transformer == null)
93 {
94
95
96 if (result.getType().equals(String.class))
97 {
98 secondPass = objectToString;
99 }
100 else if (result.getType().equals(byte[].class))
101 {
102 secondPass = objectToByteArray;
103 }
104 else
105 {
106 return null;
107 }
108
109 trans = muleContext.getRegistry().lookupTransformers(source, new SimpleDataType(Object.class));
110
111 transformer = getNearestTransformerMatch(trans, source.getType(), result.getType());
112 if (transformer != null)
113 {
114 transformer = new TransformerChain(transformer, secondPass);
115 try
116 {
117 muleContext.getRegistry().registerTransformer(transformer);
118 }
119 catch (MuleException e)
120 {
121 throw new ResolverException(e.getI18nMessage(), e);
122 }
123 }
124 }
125
126 if (transformer != null)
127 {
128 exactTransformerCache.put(source.toString() + result.toString(), transformer);
129 }
130 return transformer;
131 }
132
133 protected Transformer getNearestTransformerMatch(List<Transformer> trans, Class input, Class output) throws ResolverException
134 {
135 if (trans.size() > 1)
136 {
137 if (logger.isDebugEnabled())
138 {
139 logger.debug("Comparing transformers for best match: input = " + input + " output = " + output + " Possible transformers = " + trans);
140 }
141 TransformerWeighting weighting = null;
142 for (Transformer transformer : trans)
143 {
144 TransformerWeighting current = new TransformerWeighting(input, output, transformer);
145 if (weighting == null)
146 {
147 weighting = current;
148 }
149 else
150 {
151 int compare = current.compareTo(weighting);
152 if (compare == 1)
153 {
154 weighting = current;
155 }
156 else if (compare == 0)
157 {
158
159 if (!weighting.getTransformer().getClass().equals(current.getTransformer().getClass()))
160 {
161 throw new ResolverException(CoreMessages.transformHasMultipleMatches(input, output,
162 current.getTransformer(), weighting.getTransformer()));
163 }
164 }
165 }
166 }
167 return weighting.getTransformer();
168 }
169 else if (trans.size() == 0)
170 {
171 return null;
172 }
173 else
174 {
175 return trans.get(0);
176 }
177 }
178
179 public void dispose()
180 {
181 exactTransformerCache.clear();
182 }
183
184 public void transformerChange(Transformer transformer, RegistryAction registryAction)
185 {
186 if (transformer instanceof DiscoverableTransformer)
187 {
188 exactTransformerCache.clear();
189 }
190 }
191 }