View Javadoc

1   /*
2    * Copyright 2008 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.ws.soap.addressing.server;
18  
19  import java.lang.annotation.Annotation;
20  import java.lang.reflect.Method;
21  import java.net.URI;
22  import java.net.URISyntaxException;
23  
24  import org.springframework.aop.support.AopUtils;
25  import org.springframework.beans.BeansException;
26  import org.springframework.beans.factory.config.BeanPostProcessor;
27  import org.springframework.core.annotation.AnnotationUtils;
28  import org.springframework.util.StringUtils;
29  import org.springframework.ws.server.endpoint.MethodEndpoint;
30  import org.springframework.ws.server.endpoint.annotation.Endpoint;
31  import org.springframework.ws.soap.addressing.core.MessageAddressingProperties;
32  import org.springframework.ws.soap.addressing.server.annotation.Action;
33  import org.springframework.ws.soap.addressing.server.annotation.Address;
34  
35  /**
36   * Implementation of the {@link org.springframework.ws.server.EndpointMapping} interface that uses the {@link Action}
37   * annotation to map methods to a WS-Addressing <code>Action</code> header.
38   * <p/>
39   * Endpoints typically have the following form:
40   * <pre>
41   * &#64;Endpoint
42   * &#64;Address("mailto:[email protected]")
43   * public class MyEndpoint{
44   *    &#64;Action("http://fabrikam123.example/mail/Delete")
45   *    public Source doSomethingWithRequest() {
46   *       ...
47   *    }
48   * }
49   * </pre>
50   * <p/>
51   * If set, the {@link Address} annotation on the endpoint class should be equal to the {@link
52   * org.springframework.ws.soap.addressing.core.MessageAddressingProperties#getTo() destination} property of the
53   * incominging message.
54   *
55   * @author Arjen Poutsma
56   * @see Action
57   * @see Address
58   * @since 1.5.0
59   */
60  public class AnnotationActionEndpointMapping extends AbstractActionMethodEndpointMapping implements BeanPostProcessor {
61  
62      /** Returns the 'endpoint' annotation type. Default is {@link Endpoint}. */
63      protected Class<? extends Annotation> getEndpointAnnotationType() {
64          return Endpoint.class;
65      }
66  
67      /**
68       * Returns the action value for the specified method. Default implementation looks for the {@link Action} annotation
69       * value.
70       */
71      protected URI getActionForMethod(Method method) {
72          Action action = method.getAnnotation(Action.class);
73          if (action != null && StringUtils.hasText(action.value())) {
74              try {
75                  return new URI(action.value());
76              }
77              catch (URISyntaxException e) {
78                  throw new IllegalArgumentException(
79                          "Invalid Action annotation [" + action.value() + "] on [" + method + "]");
80              }
81          }
82          return null;
83      }
84  
85      /**
86       * Returns the address property of the given {@link MethodEndpoint}, by looking for the {@link Address} annotation.
87       * The value of this property should match the {@link org.springframework.ws.soap.addressing.core.MessageAddressingProperties#getTo()
88       * destination} of incoming messages. Returns <code>null</code> if the anotation is not present, thus ignoring the
89       * destination property.
90       *
91       * @param endpoint the method endpoint to return the address for
92       * @return the endpoint address; or <code>null</code> to ignore the destination property
93       */
94      protected URI getEndpointAddress(Object endpoint) {
95          MethodEndpoint methodEndpoint = (MethodEndpoint) endpoint;
96          Class endpointClass = methodEndpoint.getMethod().getDeclaringClass();
97          Address address = AnnotationUtils.findAnnotation(endpointClass, Address.class);
98          if (address != null && StringUtils.hasText(address.value())) {
99              return getActionUri(address.value(), methodEndpoint);
100         }
101         else {
102             return null;
103         }
104     }
105 
106     protected URI getResponseAction(Object endpoint, MessageAddressingProperties map) {
107         MethodEndpoint methodEndpoint = (MethodEndpoint) endpoint;
108         Action action = methodEndpoint.getMethod().getAnnotation(Action.class);
109         if (action != null && StringUtils.hasText(action.output())) {
110             return getActionUri(action.output(), methodEndpoint);
111         }
112         else {
113             return super.getResponseAction(endpoint, map);
114         }
115     }
116 
117     protected URI getFaultAction(Object endpoint, MessageAddressingProperties map) {
118         MethodEndpoint methodEndpoint = (MethodEndpoint) endpoint;
119         Action action = methodEndpoint.getMethod().getAnnotation(Action.class);
120         if (action != null && StringUtils.hasText(action.fault())) {
121             return getActionUri(action.fault(), methodEndpoint);
122         }
123         else {
124             return super.getResponseAction(endpoint, map);
125         }
126     }
127 
128     private URI getActionUri(String action, MethodEndpoint methodEndpoint) {
129         try {
130             return new URI(action);
131         }
132         catch (URISyntaxException e) {
133             throw new IllegalArgumentException(
134                     "Invalid Action annotation [" + action + "] on [" + methodEndpoint + "]");
135         }
136     }
137 
138     public final Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
139         return bean;
140     }
141 
142     public final Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
143         if (AopUtils.getTargetClass(bean).getAnnotation(getEndpointAnnotationType()) != null) {
144             registerMethods(bean);
145         }
146         return bean;
147     }
148 }