1
2
3
4
5
6
7
8
9
10 package org.mule.module.xml.transformer.jaxb;
11
12 import org.mule.api.MuleContext;
13 import org.mule.api.context.MuleContextAware;
14 import org.mule.api.lifecycle.Disposable;
15 import org.mule.api.registry.RegistrationException;
16 import org.mule.api.registry.ResolverException;
17 import org.mule.api.registry.TransformerResolver;
18 import org.mule.api.transformer.DataType;
19 import org.mule.api.transformer.Transformer;
20 import org.mule.config.i18n.CoreMessages;
21 import org.mule.transformer.simple.ObjectToString;
22 import org.mule.util.annotation.AnnotationUtils;
23
24 import java.io.IOException;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.concurrent.ConcurrentHashMap;
28
29 import javax.xml.bind.JAXBContext;
30
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33
34
35
36
37
38
39
40
41
42
43
44
45 public class JAXBTransformerResolver implements TransformerResolver, MuleContextAware, Disposable
46 {
47 public static final String[] ignoredPackages = {"java.,javax.,org.w3c.,org.mule.transport., org.mule.module."};
48
49
50
51
52 protected transient final Log logger = LogFactory.getLog(JAXBTransformerResolver.class);
53
54 private MuleContext muleContext;
55
56
57 private Map<String, Transformer> transformerCache = new ConcurrentHashMap<String, Transformer>();
58
59 private JAXBContextResolver resolver;
60
61 public void setMuleContext(MuleContext context)
62 {
63 muleContext = context;
64 }
65
66 public Transformer resolve(DataType source, DataType result) throws ResolverException
67 {
68 Transformer t = transformerCache.get(source.toString() + result.toString());
69 if (t != null)
70 {
71 return t;
72 }
73
74 try
75 {
76 JAXBContext jaxb = getContextResolver().resolve(JAXBContext.class, source, result, muleContext);
77
78 if(jaxb==null)
79 {
80 return null;
81 }
82 boolean marshal = false;
83 Class annotatedType = null;
84
85
86 if (getContextResolver().getMatchingClasses().contains(result.getType()))
87 {
88 annotatedType = result.getType();
89 marshal = false;
90 }
91 else
92 {
93 if (getContextResolver().getMatchingClasses().contains(source.getType()))
94 {
95 annotatedType = source.getType();
96 marshal = true;
97 }
98 }
99
100 if (annotatedType == null)
101 {
102 annotatedType = result.getType();
103 boolean isJAXB = hasJaxbAnnotations(annotatedType);
104 if (!isJAXB)
105 {
106 marshal = true;
107 annotatedType = source.getType();
108 isJAXB = hasJaxbAnnotations(annotatedType);
109 }
110
111 if (!isJAXB)
112 {
113 return null;
114 }
115 }
116
117
118 List<Transformer> ts = muleContext.getRegistry().lookupTransformers(source, result);
119 if (ts.size() == 1 && !(ts.get(0) instanceof ObjectToString))
120 {
121 t = ts.get(0);
122 }
123 else
124 {
125 if (marshal)
126 {
127 t = new JAXBMarshallerTransformer(jaxb, result);
128 }
129 else
130 {
131 t = new JAXBUnmarshallerTransformer(jaxb, result);
132 }
133 }
134
135 transformerCache.put(source.toString() + result.toString(), t);
136 return t;
137
138 }
139 catch (Exception e)
140 {
141 throw new ResolverException(CoreMessages.createStaticMessage("Failed to unmarshal"), e);
142 }
143 }
144
145 public void transformerChange(Transformer transformer, RegistryAction registryAction)
146 {
147
148 }
149
150 public void dispose()
151 {
152 transformerCache.clear();
153 }
154
155 protected JAXBContextResolver getContextResolver() throws RegistrationException
156 {
157 if(resolver==null)
158 {
159 resolver = muleContext.getRegistry().lookupObject(JAXBContextResolver.class);
160 }
161 return resolver;
162 }
163
164 protected boolean hasJaxbAnnotations(Class annotatedType)
165 {
166 String p = annotatedType.getPackage().getName();
167 for (int i = 0; i < ignoredPackages.length; i++)
168 {
169 if(p.startsWith(ignoredPackages[i])) return false;
170 }
171
172 try
173 {
174 return AnnotationUtils.hasAnnotationWithPackage("javax.xml.bind.annotation", annotatedType);
175 }
176 catch (IOException e)
177 {
178 logger.warn("Failed to scan class for Jaxb annotations: " + annotatedType, e);
179 return false;
180 }
181 }
182 }