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