Skip to content

Commit 02541be

Browse files
committed
SWS-220
1 parent 47760ad commit 02541be

File tree

12 files changed

+525
-67
lines changed

12 files changed

+525
-67
lines changed

core-tiger/pom.xml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
23
<parent>
34
<artifactId>spring-ws</artifactId>
45
<groupId>org.springframework.ws</groupId>
@@ -39,6 +40,10 @@
3940
<groupId>org.springframework.ws</groupId>
4041
<artifactId>spring-ws-core</artifactId>
4142
</dependency>
43+
<dependency>
44+
<groupId>org.springframework.ws</groupId>
45+
<artifactId>spring-oxm-tiger</artifactId>
46+
</dependency>
4247
<!-- Spring dependencies -->
4348
<dependency>
4449
<groupId>org.springframework</groupId>
@@ -73,4 +78,4 @@
7378
<version>2.2</version>
7479
</dependency>
7580
</dependencies>
76-
</project>
81+
</project>
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
* Copyright 2007 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.adapter;
18+
19+
import java.lang.reflect.Method;
20+
21+
import org.springframework.oxm.GenericMarshaller;
22+
import org.springframework.oxm.GenericUnmarshaller;
23+
import org.springframework.oxm.Marshaller;
24+
import org.springframework.oxm.Unmarshaller;
25+
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
26+
import org.springframework.ws.server.endpoint.MethodEndpoint;
27+
28+
/**
29+
* Subclass of {@link MarshallingMethodEndpointAdapter} that supports {@link GenericMarshaller} and {@link
30+
* GenericUnmarshaller}. More specifically, this adapter is aware of the {@link Method#getGenericParameterTypes()} and
31+
* {@link Method#getGenericReturnType()}.
32+
* <p/>
33+
* Prefer to use this adapter rather than the plain {@link MarshallingMethodEndpointAdapter} in combination with Java 5
34+
* marshallers, such as the {@link Jaxb2Marshaller}.
35+
*
36+
* @author Arjen Poutsma
37+
* @since 1.0.2
38+
*/
39+
public class GenericMarshallingMethodEndpointAdapter extends MarshallingMethodEndpointAdapter {
40+
41+
/**
42+
* Creates a new <code>GenericMarshallingMethodEndpointAdapter</code>. The {@link Marshaller} and {@link
43+
* Unmarshaller} must be injected using properties.
44+
*
45+
* @see #setMarshaller(org.springframework.oxm.Marshaller)
46+
* @see #setUnmarshaller(org.springframework.oxm.Unmarshaller)
47+
*/
48+
public GenericMarshallingMethodEndpointAdapter() {
49+
}
50+
51+
/**
52+
* Creates a new <code>GenericMarshallingMethodEndpointAdapter</code> with the given marshaller. If the given {@link
53+
* Marshaller} also implements the {@link Unmarshaller} interface, it is used for both marshalling and
54+
* unmarshalling. Otherwise, an exception is thrown.
55+
* <p/>
56+
* Note that all {@link Marshaller} implementations in Spring-WS also implement the {@link Unmarshaller} interface,
57+
* so that you can safely use this constructor.
58+
*
59+
* @param marshaller object used as marshaller and unmarshaller
60+
* @throws IllegalArgumentException when <code>marshaller</code> does not implement the {@link Unmarshaller}
61+
* interface
62+
*/
63+
public GenericMarshallingMethodEndpointAdapter(Marshaller marshaller) {
64+
super(marshaller);
65+
}
66+
67+
/**
68+
* Creates a new <code>GenericMarshallingMethodEndpointAdapter</code> with the given marshaller and unmarshaller.
69+
*
70+
* @param marshaller the marshaller to use
71+
* @param unmarshaller the unmarshaller to use
72+
*/
73+
public GenericMarshallingMethodEndpointAdapter(Marshaller marshaller, Unmarshaller unmarshaller) {
74+
super(marshaller, unmarshaller);
75+
}
76+
77+
protected boolean supportsInternal(MethodEndpoint methodEndpoint) {
78+
Method method = methodEndpoint.getMethod();
79+
return supportsReturnType(method) && supportsParameters(method);
80+
}
81+
82+
private boolean supportsReturnType(Method method) {
83+
if (Void.TYPE.equals(method.getReturnType())) {
84+
return true;
85+
}
86+
else {
87+
if (getMarshaller() instanceof GenericMarshaller) {
88+
return ((GenericMarshaller) getMarshaller()).supports(method.getGenericReturnType());
89+
}
90+
else {
91+
return getMarshaller().supports(method.getReturnType());
92+
}
93+
}
94+
}
95+
96+
private boolean supportsParameters(Method method) {
97+
if (method.getParameterTypes().length != 1) {
98+
return false;
99+
}
100+
else if (getUnmarshaller() instanceof GenericUnmarshaller) {
101+
GenericUnmarshaller genericUnmarshaller = (GenericUnmarshaller) getUnmarshaller();
102+
return genericUnmarshaller.supports(method.getGenericParameterTypes()[0]);
103+
}
104+
else {
105+
return getUnmarshaller().supports(method.getParameterTypes()[0]);
106+
}
107+
}
108+
}
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
package org.springframework.ws.server.endpoint.adapter;
2+
3+
import java.lang.reflect.Method;
4+
import javax.xml.transform.Result;
5+
import javax.xml.transform.Source;
6+
7+
import junit.framework.TestCase;
8+
import static org.easymock.EasyMock.*;
9+
import org.springframework.oxm.GenericMarshaller;
10+
import org.springframework.oxm.GenericUnmarshaller;
11+
import org.springframework.ws.WebServiceMessage;
12+
import org.springframework.ws.WebServiceMessageFactory;
13+
import org.springframework.ws.context.DefaultMessageContext;
14+
import org.springframework.ws.context.MessageContext;
15+
import org.springframework.ws.server.endpoint.MethodEndpoint;
16+
import org.springframework.xml.transform.StringResult;
17+
import org.springframework.xml.transform.StringSource;
18+
19+
public class GenericMarshallingMethodEndpointAdapterTest extends TestCase {
20+
21+
private GenericMarshallingMethodEndpointAdapter adapter;
22+
23+
private boolean noResponseInvoked;
24+
25+
private GenericMarshaller marshallerMock;
26+
27+
private GenericUnmarshaller unmarshallerMock;
28+
29+
private boolean responseInvoked;
30+
31+
protected void setUp() throws Exception {
32+
adapter = new GenericMarshallingMethodEndpointAdapter();
33+
marshallerMock = createMock(GenericMarshaller.class);
34+
adapter.setMarshaller(marshallerMock);
35+
unmarshallerMock = createMock(GenericUnmarshaller.class);
36+
adapter.setUnmarshaller(unmarshallerMock);
37+
adapter.afterPropertiesSet();
38+
}
39+
40+
public void testNoResponse() throws Exception {
41+
WebServiceMessage messageMock = createMock(WebServiceMessage.class);
42+
expect(messageMock.getPayloadSource()).andReturn(new StringSource("<request/>"));
43+
WebServiceMessageFactory factoryMock = createMock(WebServiceMessageFactory.class);
44+
MessageContext messageContext = new DefaultMessageContext(messageMock, factoryMock);
45+
46+
Method noResponse = getClass().getMethod("noResponse", MyGenericType.class);
47+
MethodEndpoint methodEndpoint = new MethodEndpoint(this, noResponse);
48+
expect(unmarshallerMock.unmarshal(isA(Source.class))).andReturn(new MyGenericType<MyType>());
49+
50+
replay(marshallerMock, unmarshallerMock, messageMock, factoryMock);
51+
52+
assertFalse("Method invoked", noResponseInvoked);
53+
adapter.invoke(messageContext, methodEndpoint);
54+
assertTrue("Method not invoked", noResponseInvoked);
55+
56+
verify(marshallerMock, unmarshallerMock, messageMock, factoryMock);
57+
}
58+
59+
public void testNoRequestPayload() throws Exception {
60+
WebServiceMessage messageMock = createMock(WebServiceMessage.class);
61+
expect(messageMock.getPayloadSource()).andReturn(null);
62+
WebServiceMessageFactory factoryMock = createMock(WebServiceMessageFactory.class);
63+
MessageContext messageContext = new DefaultMessageContext(messageMock, factoryMock);
64+
65+
Method noResponse = getClass().getMethod("noResponse", MyGenericType.class);
66+
MethodEndpoint methodEndpoint = new MethodEndpoint(this, noResponse);
67+
68+
replay(marshallerMock, unmarshallerMock, messageMock, factoryMock);
69+
70+
assertFalse("Method invoked", noResponseInvoked);
71+
adapter.invoke(messageContext, methodEndpoint);
72+
assertTrue("Method not invoked", noResponseInvoked);
73+
74+
verify(marshallerMock, unmarshallerMock, messageMock, factoryMock);
75+
}
76+
77+
public void testResponse() throws Exception {
78+
WebServiceMessage requestMock = createMock(WebServiceMessage.class);
79+
expect(requestMock.getPayloadSource()).andReturn(new StringSource("<request/>"));
80+
WebServiceMessage responseMock = createMock(WebServiceMessage.class);
81+
expect(responseMock.getPayloadResult()).andReturn(new StringResult());
82+
WebServiceMessageFactory factoryMock = createMock(WebServiceMessageFactory.class);
83+
expect(factoryMock.createWebServiceMessage()).andReturn(responseMock);
84+
MessageContext messageContext = new DefaultMessageContext(requestMock, factoryMock);
85+
86+
Method response = getClass().getMethod("response", MyGenericType.class);
87+
MethodEndpoint methodEndpoint = new MethodEndpoint(this, response);
88+
expect(unmarshallerMock.unmarshal(isA(Source.class))).andReturn(new MyGenericType<MyType>());
89+
marshallerMock.marshal(isA(MyGenericType.class), isA(Result.class));
90+
91+
replay(marshallerMock, unmarshallerMock, requestMock, responseMock, factoryMock);
92+
93+
assertFalse("Method invoked", responseInvoked);
94+
adapter.invoke(messageContext, methodEndpoint);
95+
assertTrue("Method not invoked", responseInvoked);
96+
97+
verify(marshallerMock, unmarshallerMock, requestMock, responseMock, factoryMock);
98+
}
99+
100+
public void testSupportedNoResponse() throws NoSuchMethodException {
101+
Method noResponse = getClass().getMethod("noResponse", MyGenericType.class);
102+
MethodEndpoint methodEndpoint = new MethodEndpoint(this, noResponse);
103+
expect(unmarshallerMock.supports(noResponse.getGenericParameterTypes()[0])).andReturn(true);
104+
105+
replay(marshallerMock, unmarshallerMock);
106+
107+
assertTrue("Method unsupported", adapter.supportsInternal(methodEndpoint));
108+
109+
verify(marshallerMock, unmarshallerMock);
110+
}
111+
112+
public void testSupportedResponse() throws NoSuchMethodException {
113+
Method response = getClass().getMethod("response", MyGenericType.class);
114+
MethodEndpoint methodEndpoint = new MethodEndpoint(this, response);
115+
116+
expect(unmarshallerMock.supports(response.getGenericParameterTypes()[0])).andReturn(true);
117+
expect(marshallerMock.supports(response.getGenericReturnType())).andReturn(true);
118+
119+
replay(marshallerMock, unmarshallerMock);
120+
121+
assertTrue("Method unsupported", adapter.supportsInternal(methodEndpoint));
122+
123+
verify(marshallerMock, unmarshallerMock);
124+
}
125+
126+
public void testUnsupportedMethodMultipleParams() throws NoSuchMethodException {
127+
Method unsupported = getClass().getMethod("unsupportedMultipleParams", String.class, String.class);
128+
129+
replay(marshallerMock, unmarshallerMock);
130+
131+
assertFalse("Method supported", adapter.supportsInternal(new MethodEndpoint(this, unsupported)));
132+
133+
verify(marshallerMock, unmarshallerMock);
134+
}
135+
136+
public void testUnsupportedMethodWrongParam() throws NoSuchMethodException {
137+
Method unsupported = getClass().getMethod("unsupportedWrongParam", String.class);
138+
expect(unmarshallerMock.supports(unsupported.getGenericParameterTypes()[0])).andReturn(false);
139+
expect(marshallerMock.supports(unsupported.getGenericReturnType())).andReturn(true);
140+
141+
replay(marshallerMock, unmarshallerMock);
142+
143+
assertFalse("Method supported", adapter.supportsInternal(new MethodEndpoint(this, unsupported)));
144+
145+
verify(marshallerMock, unmarshallerMock);
146+
}
147+
148+
public void testUnsupportedMethodWrongReturnType() throws NoSuchMethodException {
149+
Method unsupported = getClass().getMethod("unsupportedWrongParam", String.class);
150+
expect(marshallerMock.supports(unsupported.getGenericReturnType())).andReturn(false);
151+
152+
replay(marshallerMock, unmarshallerMock);
153+
154+
assertFalse("Method supported", adapter.supportsInternal(new MethodEndpoint(this, unsupported)));
155+
156+
verify(marshallerMock, unmarshallerMock);
157+
}
158+
159+
public void noResponse(MyGenericType<MyType> type) {
160+
noResponseInvoked = true;
161+
162+
}
163+
164+
public MyGenericType<MyType> response(MyGenericType<MyType> type) {
165+
responseInvoked = true;
166+
return type;
167+
}
168+
169+
public void unsupportedMultipleParams(String s1, String s2) {
170+
}
171+
172+
public String unsupportedWrongParam(String s) {
173+
return s;
174+
}
175+
176+
private static class MyType {
177+
178+
}
179+
180+
private static class MyGenericType<T> {
181+
182+
}
183+
184+
185+
}

core/src/main/java/org/springframework/ws/server/endpoint/MethodEndpoint.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.lang.reflect.InvocationTargetException;
2020
import java.lang.reflect.Method;
2121

22+
import org.springframework.core.JdkVersion;
2223
import org.springframework.util.Assert;
2324

2425
/**
@@ -120,6 +121,19 @@ public int hashCode() {
120121
}
121122

122123
public String toString() {
123-
return this.method.toString();
124+
if (JdkVersion.getMajorJavaVersion() <= JdkVersion.JAVA_14) {
125+
return this.method.toString();
126+
}
127+
else {
128+
return GenericToStringProvider.toString(method);
129+
}
130+
}
131+
132+
/** Inner class to avoid a static JDK 1.5 dependency for generic string generation. */
133+
private static class GenericToStringProvider {
134+
135+
public static String toString(Method method) {
136+
return method.toGenericString();
137+
}
124138
}
125139
}

0 commit comments

Comments
 (0)