1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.ws.config;
18
19 import org.springframework.beans.BeanMetadataElement;
20 import org.springframework.beans.factory.config.BeanDefinition;
21 import org.springframework.beans.factory.config.RuntimeBeanReference;
22 import org.springframework.beans.factory.parsing.BeanComponentDefinition;
23 import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
24 import org.springframework.beans.factory.support.ManagedList;
25 import org.springframework.beans.factory.support.RootBeanDefinition;
26 import org.springframework.beans.factory.xml.BeanDefinitionParser;
27 import org.springframework.beans.factory.xml.ParserContext;
28 import org.springframework.core.Ordered;
29 import org.springframework.util.ClassUtils;
30 import org.springframework.ws.server.endpoint.adapter.DefaultMethodEndpointAdapter;
31 import org.springframework.ws.server.endpoint.adapter.method.MarshallingPayloadMethodProcessor;
32 import org.springframework.ws.server.endpoint.adapter.method.MessageContextMethodArgumentResolver;
33 import org.springframework.ws.server.endpoint.adapter.method.SourcePayloadMethodProcessor;
34 import org.springframework.ws.server.endpoint.adapter.method.StaxPayloadMethodArgumentResolver;
35 import org.springframework.ws.server.endpoint.adapter.method.XPathParamMethodArgumentResolver;
36 import org.springframework.ws.server.endpoint.adapter.method.dom.Dom4jPayloadMethodProcessor;
37 import org.springframework.ws.server.endpoint.adapter.method.dom.DomPayloadMethodProcessor;
38 import org.springframework.ws.server.endpoint.adapter.method.dom.JDomPayloadMethodProcessor;
39 import org.springframework.ws.server.endpoint.adapter.method.dom.XomPayloadMethodProcessor;
40 import org.springframework.ws.server.endpoint.adapter.method.jaxb.JaxbElementPayloadMethodProcessor;
41 import org.springframework.ws.server.endpoint.adapter.method.jaxb.XmlRootElementPayloadMethodProcessor;
42 import org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping;
43 import org.springframework.ws.soap.addressing.server.AnnotationActionEndpointMapping;
44 import org.springframework.ws.soap.server.endpoint.SimpleSoapExceptionResolver;
45 import org.springframework.ws.soap.server.endpoint.SoapFaultAnnotationExceptionResolver;
46 import org.springframework.ws.soap.server.endpoint.adapter.method.SoapHeaderElementMethodArgumentResolver;
47 import org.springframework.ws.soap.server.endpoint.adapter.method.SoapMethodArgumentResolver;
48 import org.springframework.ws.soap.server.endpoint.mapping.SoapActionAnnotationMethodEndpointMapping;
49
50 import org.w3c.dom.Element;
51
52
53
54
55
56
57
58 class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
59
60 private static final boolean dom4jPresent =
61 ClassUtils.isPresent("org.dom4j.Element", AnnotationDrivenBeanDefinitionParser.class.getClassLoader());
62
63 private static final boolean jaxb2Present =
64 ClassUtils.isPresent("javax.xml.bind.Binder", AnnotationDrivenBeanDefinitionParser.class.getClassLoader());
65
66 private static final boolean jdomPresent =
67 ClassUtils.isPresent("org.jdom2.Element", AnnotationDrivenBeanDefinitionParser.class.getClassLoader());
68
69 private static final boolean staxPresent = ClassUtils
70 .isPresent("javax.xml.stream.XMLInputFactory", AnnotationDrivenBeanDefinitionParser.class.getClassLoader());
71
72 private static final boolean xomPresent =
73 ClassUtils.isPresent("nu.xom.Element", AnnotationDrivenBeanDefinitionParser.class.getClassLoader());
74
75 public BeanDefinition parse(Element element, ParserContext parserContext) {
76 Object source = parserContext.extractSource(element);
77
78 CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);
79 parserContext.pushContainingComponent(compDefinition);
80
81 registerEndpointMappings(source, parserContext);
82
83 registerEndpointAdapters(element, source, parserContext);
84
85 registerEndpointExceptionResolvers(source, parserContext);
86
87 parserContext.popAndRegisterContainingComponent();
88
89 return null;
90 }
91
92 private void registerEndpointMappings(Object source, ParserContext parserContext) {
93 RootBeanDefinition payloadRootMappingDef =
94 createBeanDefinition(PayloadRootAnnotationMethodEndpointMapping.class, source);
95 payloadRootMappingDef.getPropertyValues().add("order", 0);
96 parserContext.getReaderContext().registerWithGeneratedName(payloadRootMappingDef);
97
98 RootBeanDefinition soapActionMappingDef =
99 createBeanDefinition(SoapActionAnnotationMethodEndpointMapping.class, source);
100 soapActionMappingDef.getPropertyValues().add("order", 1);
101 parserContext.getReaderContext().registerWithGeneratedName(soapActionMappingDef);
102
103 RootBeanDefinition annActionMappingDef =
104 createBeanDefinition(AnnotationActionEndpointMapping.class, source);
105 annActionMappingDef.getPropertyValues().add("order", 2);
106 parserContext.getReaderContext().registerWithGeneratedName(annActionMappingDef);
107 }
108
109 private void registerEndpointAdapters(Element element, Object source, ParserContext parserContext) {
110 RootBeanDefinition adapterDef = createBeanDefinition(DefaultMethodEndpointAdapter.class, source);
111
112 ManagedList<BeanMetadataElement> argumentResolvers = new ManagedList<BeanMetadataElement>();
113 argumentResolvers.setSource(source);
114
115 ManagedList<BeanMetadataElement> returnValueHandlers = new ManagedList<BeanMetadataElement>();
116 returnValueHandlers.setSource(source);
117
118 argumentResolvers.add(createBeanDefinition(MessageContextMethodArgumentResolver.class, source));
119 argumentResolvers.add(createBeanDefinition(XPathParamMethodArgumentResolver.class, source));
120 argumentResolvers.add(createBeanDefinition(SoapMethodArgumentResolver.class, source));
121 argumentResolvers.add(createBeanDefinition(SoapHeaderElementMethodArgumentResolver.class, source));
122
123 RuntimeBeanReference domProcessor = createBeanReference(DomPayloadMethodProcessor.class, source, parserContext);
124 argumentResolvers.add(domProcessor);
125 returnValueHandlers.add(domProcessor);
126
127 RuntimeBeanReference sourceProcessor =
128 createBeanReference(SourcePayloadMethodProcessor.class, source, parserContext);
129 argumentResolvers.add(sourceProcessor);
130 returnValueHandlers.add(sourceProcessor);
131
132 if (dom4jPresent) {
133 RuntimeBeanReference dom4jProcessor =
134 createBeanReference(Dom4jPayloadMethodProcessor.class, source, parserContext);
135 argumentResolvers.add(dom4jProcessor);
136 returnValueHandlers.add(dom4jProcessor);
137 }
138 if (jaxb2Present) {
139 RuntimeBeanReference xmlRootElementProcessor =
140 createBeanReference(XmlRootElementPayloadMethodProcessor.class, source, parserContext);
141 argumentResolvers.add(xmlRootElementProcessor);
142 returnValueHandlers.add(xmlRootElementProcessor);
143
144 RuntimeBeanReference jaxbElementProcessor =
145 createBeanReference(JaxbElementPayloadMethodProcessor.class, source, parserContext);
146 argumentResolvers.add(jaxbElementProcessor);
147 returnValueHandlers.add(jaxbElementProcessor);
148 }
149 if (jdomPresent) {
150 RuntimeBeanReference jdomProcessor =
151 createBeanReference(JDomPayloadMethodProcessor.class, source, parserContext);
152 argumentResolvers.add(jdomProcessor);
153 returnValueHandlers.add(jdomProcessor);
154 }
155 if (staxPresent) {
156 argumentResolvers.add(createBeanDefinition(StaxPayloadMethodArgumentResolver.class, source));
157 }
158 if (xomPresent) {
159 RuntimeBeanReference xomProcessor =
160 createBeanReference(XomPayloadMethodProcessor.class, source, parserContext);
161 argumentResolvers.add(xomProcessor);
162 returnValueHandlers.add(xomProcessor);
163 }
164 if (element.hasAttribute("marshaller")) {
165 RuntimeBeanReference marshallerReference = new RuntimeBeanReference(element.getAttribute("marshaller"));
166 RuntimeBeanReference unmarshallerReference;
167 if (element.hasAttribute("unmarshaller")) {
168 unmarshallerReference = new RuntimeBeanReference(element.getAttribute("unmarshaller"));
169 }
170 else {
171 unmarshallerReference = marshallerReference;
172 }
173
174 RootBeanDefinition marshallingProcessorDef =
175 createBeanDefinition(MarshallingPayloadMethodProcessor.class, source);
176 marshallingProcessorDef.getPropertyValues().add("marshaller", marshallerReference);
177 marshallingProcessorDef.getPropertyValues().add("unmarshaller", unmarshallerReference);
178 argumentResolvers.add(marshallingProcessorDef);
179 returnValueHandlers.add(marshallingProcessorDef);
180 }
181
182 adapterDef.getPropertyValues().add("methodArgumentResolvers", argumentResolvers);
183 adapterDef.getPropertyValues().add("methodReturnValueHandlers", returnValueHandlers);
184
185 parserContext.getReaderContext().registerWithGeneratedName(adapterDef);
186 }
187
188 private void registerEndpointExceptionResolvers(Object source, ParserContext parserContext) {
189 RootBeanDefinition annotationResolverDef =
190 createBeanDefinition(SoapFaultAnnotationExceptionResolver.class, source);
191 annotationResolverDef.getPropertyValues().add("order", 0);
192 parserContext.getReaderContext().registerWithGeneratedName(annotationResolverDef);
193
194 RootBeanDefinition simpleResolverDef =
195 createBeanDefinition(SimpleSoapExceptionResolver.class, source);
196 simpleResolverDef.getPropertyValues().add("order", Ordered.LOWEST_PRECEDENCE);
197 parserContext.getReaderContext().registerWithGeneratedName(simpleResolverDef);
198 }
199
200 private RuntimeBeanReference createBeanReference(Class<?> beanClass, Object source, ParserContext parserContext) {
201 RootBeanDefinition beanDefinition = createBeanDefinition(beanClass, source);
202 String beanName = parserContext.getReaderContext().registerWithGeneratedName(beanDefinition);
203 parserContext.registerComponent(new BeanComponentDefinition(beanDefinition, beanName));
204 return new RuntimeBeanReference(beanName);
205 }
206
207 private RootBeanDefinition createBeanDefinition(Class<?> beanClass, Object source) {
208 RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass);
209 beanDefinition.setSource(source);
210 beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
211 return beanDefinition;
212 }
213 }