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