1 /*
2 * Copyright 2005-2010 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.server.endpoint.mapping;
18
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.List;
22 import java.util.Map;
23
24 import org.springframework.beans.BeansException;
25 import org.springframework.beans.factory.BeanFactoryUtils;
26 import org.springframework.context.support.ApplicationObjectSupport;
27 import org.springframework.core.Ordered;
28 import org.springframework.ws.context.MessageContext;
29 import org.springframework.ws.server.EndpointInterceptor;
30 import org.springframework.ws.server.EndpointInvocationChain;
31 import org.springframework.ws.server.EndpointMapping;
32 import org.springframework.ws.server.SmartEndpointInterceptor;
33
34 /**
35 * Abstract base class for EndpointMapping implementations. Supports a default endpoint, and endpoint interceptors.
36 *
37 * @author Arjen Poutsma
38 * @see #getEndpointInternal(org.springframework.ws.context.MessageContext)
39 * @see org.springframework.ws.server.EndpointInterceptor
40 * @since 1.0.0
41 */
42 public abstract class AbstractEndpointMapping extends ApplicationObjectSupport implements EndpointMapping, Ordered {
43
44 private int order = Integer.MAX_VALUE; // default: same as non-Ordered
45
46 private Object defaultEndpoint;
47
48 private EndpointInterceptor[] interceptors;
49
50 private SmartEndpointInterceptor[] smartInterceptors;
51
52 /**
53 * Returns the the endpoint interceptors to apply to all endpoints mapped by this endpoint mapping.
54 *
55 * @return array of endpoint interceptors, or <code>null</code> if none
56 */
57 public EndpointInterceptor[] getInterceptors() {
58 return interceptors;
59 }
60
61 /**
62 * Sets the endpoint interceptors to apply to all endpoints mapped by this endpoint mapping.
63 *
64 * @param interceptors array of endpoint interceptors, or <code>null</code> if none
65 */
66 public final void setInterceptors(EndpointInterceptor[] interceptors) {
67 this.interceptors = interceptors;
68 }
69
70 public final int getOrder() {
71 return order;
72 }
73
74 /**
75 * Specify the order value for this mapping.
76 * <p/>
77 * Default value is {@link Integer#MAX_VALUE}, meaning that it's non-ordered.
78 *
79 * @see org.springframework.core.Ordered#getOrder()
80 */
81 public final void setOrder(int order) {
82 this.order = order;
83 }
84
85 /**
86 * Initializes the interceptors.
87 *
88 * @see #initInterceptors()
89 */
90 @Override
91 protected void initApplicationContext() throws BeansException {
92 initInterceptors();
93 }
94
95 /**
96 * Initialize the specified interceptors, adapting them where necessary.
97 *
98 * @see #setInterceptors
99 */
100 protected void initInterceptors() {
101 Map<String, SmartEndpointInterceptor> smartInterceptors = BeanFactoryUtils
102 .beansOfTypeIncludingAncestors(getApplicationContext(), SmartEndpointInterceptor.class, true, false);
103 if (!smartInterceptors.isEmpty()) {
104 this.smartInterceptors =
105 smartInterceptors.values().toArray(new SmartEndpointInterceptor[smartInterceptors.size()]);
106 }
107 }
108
109 /**
110 * Look up an endpoint for the given message context, falling back to the default endpoint if no specific one is
111 * found.
112 *
113 * @return the looked up endpoint instance, or the default endpoint
114 * @see #getEndpointInternal(org.springframework.ws.context.MessageContext)
115 */
116 public final EndpointInvocationChain getEndpoint(MessageContext messageContext) throws Exception {
117 Object endpoint = getEndpointInternal(messageContext);
118 if (endpoint == null) {
119 endpoint = defaultEndpoint;
120 }
121 if (endpoint == null) {
122 return null;
123 }
124 if (endpoint instanceof String) {
125 String endpointName = (String) endpoint;
126 endpoint = resolveStringEndpoint(endpointName);
127 if (endpoint == null) {
128 return null;
129 }
130 }
131
132 List<EndpointInterceptor> interceptors = new ArrayList<EndpointInterceptor>();
133 if (this.interceptors != null) {
134 interceptors.addAll(Arrays.asList(this.interceptors));
135 }
136
137 if (this.smartInterceptors != null) {
138 for (SmartEndpointInterceptor smartInterceptor : smartInterceptors) {
139 if (smartInterceptor.shouldIntercept(messageContext, endpoint)) {
140 interceptors.add(smartInterceptor);
141 }
142 }
143 }
144
145 return createEndpointInvocationChain(messageContext, endpoint,
146 interceptors.toArray(new EndpointInterceptor[interceptors.size()]));
147 }
148
149 /**
150 * Creates a new <code>EndpointInvocationChain</code> based on the given message context, endpoint, and
151 * interceptors. Default implementation creates a simple <code>EndpointInvocationChain</code> based on the set
152 * interceptors.
153 *
154 * @param endpoint the endpoint
155 * @param interceptors the endpoint interceptors
156 * @return the created invocation chain
157 * @see #setInterceptors(org.springframework.ws.server.EndpointInterceptor[])
158 */
159 protected EndpointInvocationChain createEndpointInvocationChain(MessageContext messageContext,
160 Object endpoint,
161 EndpointInterceptor[] interceptors) {
162 return new EndpointInvocationChain(endpoint, interceptors);
163 }
164
165 /**
166 * Returns the default endpoint for this endpoint mapping.
167 *
168 * @return the default endpoint mapping, or null if none
169 */
170 protected final Object getDefaultEndpoint() {
171 return defaultEndpoint;
172 }
173
174 /**
175 * Sets the default endpoint for this endpoint mapping. This endpoint will be returned if no specific mapping was
176 * found.
177 * <p/>
178 * Default is <code>null</code>, indicating no default endpoint.
179 *
180 * @param defaultEndpoint the default endpoint, or null if none
181 */
182 public final void setDefaultEndpoint(Object defaultEndpoint) {
183 this.defaultEndpoint = defaultEndpoint;
184 }
185
186 /**
187 * Resolves an endpoint string. If the given string can is a bean name, it is resolved using the application
188 * context.
189 *
190 * @param endpointName the endpoint name
191 * @return the resolved endpoint, or <code>null</code> if the name could not be resolved
192 */
193 protected Object resolveStringEndpoint(String endpointName) {
194 if (getApplicationContext().containsBean(endpointName)) {
195 return getApplicationContext().getBean(endpointName);
196 }
197 else {
198 return null;
199 }
200 }
201
202 /**
203 * Lookup an endpoint for the given request, returning <code>null</code> if no specific one is found. This template
204 * method is called by getEndpoint, a <code>null</code> return value will lead to the default handler, if one is
205 * set.
206 * <p/>
207 * The returned endpoint can be a string, in which case it is resolved as a bean name. Also, it can take the form
208 * <code>beanName#method</code>, in which case the method is resolved.
209 *
210 * @return the looked up endpoint instance, or null
211 * @throws Exception if there is an error
212 */
213 protected abstract Object getEndpointInternal(MessageContext messageContext) throws Exception;
214 }