View Javadoc

1   /*
2    * Copyright 2005-2011 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
37   * {@link Action @Action} annotation to map methods to a WS-Addressing {@code Action} header.
38   * <p/>
39   * Endpoints typically have the following form:
40   * <pre>
41   * &#64;Endpoint
42   * &#64;Address("mailto:joe@fabrikam123.example")
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 @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   * incoming 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      @Override
72      protected URI getActionForMethod(Method method) {
73          Action action = method.getAnnotation(Action.class);
74          if (action != null && StringUtils.hasText(action.value())) {
75              try {
76                  return new URI(action.value());
77              }
78              catch (URISyntaxException e) {
79                  throw new IllegalArgumentException(
80                          "Invalid Action annotation [" + action.value() + "] on [" + method + "]");
81              }
82          }
83          return null;
84      }
85  
86      /**
87       * Returns the address property of the given {@link MethodEndpoint}, by looking for the {@link Address} annotation.
88       * The value of this property should match the {@link org.springframework.ws.soap.addressing.core.MessageAddressingProperties#getTo()
89       * destination} of incoming messages. Returns <code>null</code> if the anotation is not present, thus ignoring the
90       * destination property.
91       *
92       * @param endpoint the method endpoint to return the address for
93       * @return the endpoint address; or <code>null</code> to ignore the destination property
94       */
95      @Override
96      protected URI getEndpointAddress(Object endpoint) {
97          MethodEndpoint methodEndpoint = (MethodEndpoint) endpoint;
98          Class<?> endpointClass = methodEndpoint.getMethod().getDeclaringClass();
99          Address address = AnnotationUtils.findAnnotation(endpointClass, Address.class);
100         if (address != null && StringUtils.hasText(address.value())) {
101             return getActionUri(address.value(), methodEndpoint);
102         }
103         else {
104             return null;
105         }
106     }
107 
108     @Override
109     protected URI getResponseAction(Object endpoint, MessageAddressingProperties map) {
110         MethodEndpoint methodEndpoint = (MethodEndpoint) endpoint;
111         Action action = methodEndpoint.getMethod().getAnnotation(Action.class);
112         if (action != null && StringUtils.hasText(action.output())) {
113             return getActionUri(action.output(), methodEndpoint);
114         }
115         else {
116             return super.getResponseAction(endpoint, map);
117         }
118     }
119 
120     @Override
121     protected URI getFaultAction(Object endpoint, MessageAddressingProperties map) {
122         MethodEndpoint methodEndpoint = (MethodEndpoint) endpoint;
123         Action action = methodEndpoint.getMethod().getAnnotation(Action.class);
124         if (action != null && StringUtils.hasText(action.fault())) {
125             return getActionUri(action.fault(), methodEndpoint);
126         }
127         else {
128             return super.getResponseAction(endpoint, map);
129         }
130     }
131 
132     private URI getActionUri(String action, MethodEndpoint methodEndpoint) {
133         try {
134             return new URI(action);
135         }
136         catch (URISyntaxException e) {
137             throw new IllegalArgumentException(
138                     "Invalid Action annotation [" + action + "] on [" + methodEndpoint + "]");
139         }
140     }
141 
142     public final Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
143         return bean;
144     }
145 
146     public final Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
147         if (AopUtils.getTargetClass(bean).getAnnotation(getEndpointAnnotationType()) != null) {
148             registerMethods(bean);
149         }
150         return bean;
151     }
152 }