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