SWS-220
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
<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">
|
||||
<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">
|
||||
<parent>
|
||||
<artifactId>spring-ws</artifactId>
|
||||
<groupId>org.springframework.ws</groupId>
|
||||
@@ -39,6 +40,10 @@
|
||||
<groupId>org.springframework.ws</groupId>
|
||||
<artifactId>spring-ws-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ws</groupId>
|
||||
<artifactId>spring-oxm-tiger</artifactId>
|
||||
</dependency>
|
||||
<!-- Spring dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
@@ -73,4 +78,4 @@
|
||||
<version>2.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
</project>
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.server.endpoint.adapter;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.oxm.GenericMarshaller;
|
||||
import org.springframework.oxm.GenericUnmarshaller;
|
||||
import org.springframework.oxm.Marshaller;
|
||||
import org.springframework.oxm.Unmarshaller;
|
||||
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
|
||||
import org.springframework.ws.server.endpoint.MethodEndpoint;
|
||||
|
||||
/**
|
||||
* Subclass of {@link MarshallingMethodEndpointAdapter} that supports {@link GenericMarshaller} and {@link
|
||||
* GenericUnmarshaller}. More specifically, this adapter is aware of the {@link Method#getGenericParameterTypes()} and
|
||||
* {@link Method#getGenericReturnType()}.
|
||||
* <p/>
|
||||
* Prefer to use this adapter rather than the plain {@link MarshallingMethodEndpointAdapter} in combination with Java 5
|
||||
* marshallers, such as the {@link Jaxb2Marshaller}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.0.2
|
||||
*/
|
||||
public class GenericMarshallingMethodEndpointAdapter extends MarshallingMethodEndpointAdapter {
|
||||
|
||||
/**
|
||||
* Creates a new <code>GenericMarshallingMethodEndpointAdapter</code>. The {@link Marshaller} and {@link
|
||||
* Unmarshaller} must be injected using properties.
|
||||
*
|
||||
* @see #setMarshaller(org.springframework.oxm.Marshaller)
|
||||
* @see #setUnmarshaller(org.springframework.oxm.Unmarshaller)
|
||||
*/
|
||||
public GenericMarshallingMethodEndpointAdapter() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>GenericMarshallingMethodEndpointAdapter</code> with the given marshaller. If the given {@link
|
||||
* Marshaller} also implements the {@link Unmarshaller} interface, it is used for both marshalling and
|
||||
* unmarshalling. Otherwise, an exception is thrown.
|
||||
* <p/>
|
||||
* Note that all {@link Marshaller} implementations in Spring-WS also implement the {@link Unmarshaller} interface,
|
||||
* so that you can safely use this constructor.
|
||||
*
|
||||
* @param marshaller object used as marshaller and unmarshaller
|
||||
* @throws IllegalArgumentException when <code>marshaller</code> does not implement the {@link Unmarshaller}
|
||||
* interface
|
||||
*/
|
||||
public GenericMarshallingMethodEndpointAdapter(Marshaller marshaller) {
|
||||
super(marshaller);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>GenericMarshallingMethodEndpointAdapter</code> with the given marshaller and unmarshaller.
|
||||
*
|
||||
* @param marshaller the marshaller to use
|
||||
* @param unmarshaller the unmarshaller to use
|
||||
*/
|
||||
public GenericMarshallingMethodEndpointAdapter(Marshaller marshaller, Unmarshaller unmarshaller) {
|
||||
super(marshaller, unmarshaller);
|
||||
}
|
||||
|
||||
protected boolean supportsInternal(MethodEndpoint methodEndpoint) {
|
||||
Method method = methodEndpoint.getMethod();
|
||||
return supportsReturnType(method) && supportsParameters(method);
|
||||
}
|
||||
|
||||
private boolean supportsReturnType(Method method) {
|
||||
if (Void.TYPE.equals(method.getReturnType())) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if (getMarshaller() instanceof GenericMarshaller) {
|
||||
return ((GenericMarshaller) getMarshaller()).supports(method.getGenericReturnType());
|
||||
}
|
||||
else {
|
||||
return getMarshaller().supports(method.getReturnType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean supportsParameters(Method method) {
|
||||
if (method.getParameterTypes().length != 1) {
|
||||
return false;
|
||||
}
|
||||
else if (getUnmarshaller() instanceof GenericUnmarshaller) {
|
||||
GenericUnmarshaller genericUnmarshaller = (GenericUnmarshaller) getUnmarshaller();
|
||||
return genericUnmarshaller.supports(method.getGenericParameterTypes()[0]);
|
||||
}
|
||||
else {
|
||||
return getUnmarshaller().supports(method.getParameterTypes()[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
package org.springframework.ws.server.endpoint.adapter;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.Source;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import static org.easymock.EasyMock.*;
|
||||
import org.springframework.oxm.GenericMarshaller;
|
||||
import org.springframework.oxm.GenericUnmarshaller;
|
||||
import org.springframework.ws.WebServiceMessage;
|
||||
import org.springframework.ws.WebServiceMessageFactory;
|
||||
import org.springframework.ws.context.DefaultMessageContext;
|
||||
import org.springframework.ws.context.MessageContext;
|
||||
import org.springframework.ws.server.endpoint.MethodEndpoint;
|
||||
import org.springframework.xml.transform.StringResult;
|
||||
import org.springframework.xml.transform.StringSource;
|
||||
|
||||
public class GenericMarshallingMethodEndpointAdapterTest extends TestCase {
|
||||
|
||||
private GenericMarshallingMethodEndpointAdapter adapter;
|
||||
|
||||
private boolean noResponseInvoked;
|
||||
|
||||
private GenericMarshaller marshallerMock;
|
||||
|
||||
private GenericUnmarshaller unmarshallerMock;
|
||||
|
||||
private boolean responseInvoked;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
adapter = new GenericMarshallingMethodEndpointAdapter();
|
||||
marshallerMock = createMock(GenericMarshaller.class);
|
||||
adapter.setMarshaller(marshallerMock);
|
||||
unmarshallerMock = createMock(GenericUnmarshaller.class);
|
||||
adapter.setUnmarshaller(unmarshallerMock);
|
||||
adapter.afterPropertiesSet();
|
||||
}
|
||||
|
||||
public void testNoResponse() throws Exception {
|
||||
WebServiceMessage messageMock = createMock(WebServiceMessage.class);
|
||||
expect(messageMock.getPayloadSource()).andReturn(new StringSource("<request/>"));
|
||||
WebServiceMessageFactory factoryMock = createMock(WebServiceMessageFactory.class);
|
||||
MessageContext messageContext = new DefaultMessageContext(messageMock, factoryMock);
|
||||
|
||||
Method noResponse = getClass().getMethod("noResponse", MyGenericType.class);
|
||||
MethodEndpoint methodEndpoint = new MethodEndpoint(this, noResponse);
|
||||
expect(unmarshallerMock.unmarshal(isA(Source.class))).andReturn(new MyGenericType<MyType>());
|
||||
|
||||
replay(marshallerMock, unmarshallerMock, messageMock, factoryMock);
|
||||
|
||||
assertFalse("Method invoked", noResponseInvoked);
|
||||
adapter.invoke(messageContext, methodEndpoint);
|
||||
assertTrue("Method not invoked", noResponseInvoked);
|
||||
|
||||
verify(marshallerMock, unmarshallerMock, messageMock, factoryMock);
|
||||
}
|
||||
|
||||
public void testNoRequestPayload() throws Exception {
|
||||
WebServiceMessage messageMock = createMock(WebServiceMessage.class);
|
||||
expect(messageMock.getPayloadSource()).andReturn(null);
|
||||
WebServiceMessageFactory factoryMock = createMock(WebServiceMessageFactory.class);
|
||||
MessageContext messageContext = new DefaultMessageContext(messageMock, factoryMock);
|
||||
|
||||
Method noResponse = getClass().getMethod("noResponse", MyGenericType.class);
|
||||
MethodEndpoint methodEndpoint = new MethodEndpoint(this, noResponse);
|
||||
|
||||
replay(marshallerMock, unmarshallerMock, messageMock, factoryMock);
|
||||
|
||||
assertFalse("Method invoked", noResponseInvoked);
|
||||
adapter.invoke(messageContext, methodEndpoint);
|
||||
assertTrue("Method not invoked", noResponseInvoked);
|
||||
|
||||
verify(marshallerMock, unmarshallerMock, messageMock, factoryMock);
|
||||
}
|
||||
|
||||
public void testResponse() throws Exception {
|
||||
WebServiceMessage requestMock = createMock(WebServiceMessage.class);
|
||||
expect(requestMock.getPayloadSource()).andReturn(new StringSource("<request/>"));
|
||||
WebServiceMessage responseMock = createMock(WebServiceMessage.class);
|
||||
expect(responseMock.getPayloadResult()).andReturn(new StringResult());
|
||||
WebServiceMessageFactory factoryMock = createMock(WebServiceMessageFactory.class);
|
||||
expect(factoryMock.createWebServiceMessage()).andReturn(responseMock);
|
||||
MessageContext messageContext = new DefaultMessageContext(requestMock, factoryMock);
|
||||
|
||||
Method response = getClass().getMethod("response", MyGenericType.class);
|
||||
MethodEndpoint methodEndpoint = new MethodEndpoint(this, response);
|
||||
expect(unmarshallerMock.unmarshal(isA(Source.class))).andReturn(new MyGenericType<MyType>());
|
||||
marshallerMock.marshal(isA(MyGenericType.class), isA(Result.class));
|
||||
|
||||
replay(marshallerMock, unmarshallerMock, requestMock, responseMock, factoryMock);
|
||||
|
||||
assertFalse("Method invoked", responseInvoked);
|
||||
adapter.invoke(messageContext, methodEndpoint);
|
||||
assertTrue("Method not invoked", responseInvoked);
|
||||
|
||||
verify(marshallerMock, unmarshallerMock, requestMock, responseMock, factoryMock);
|
||||
}
|
||||
|
||||
public void testSupportedNoResponse() throws NoSuchMethodException {
|
||||
Method noResponse = getClass().getMethod("noResponse", MyGenericType.class);
|
||||
MethodEndpoint methodEndpoint = new MethodEndpoint(this, noResponse);
|
||||
expect(unmarshallerMock.supports(noResponse.getGenericParameterTypes()[0])).andReturn(true);
|
||||
|
||||
replay(marshallerMock, unmarshallerMock);
|
||||
|
||||
assertTrue("Method unsupported", adapter.supportsInternal(methodEndpoint));
|
||||
|
||||
verify(marshallerMock, unmarshallerMock);
|
||||
}
|
||||
|
||||
public void testSupportedResponse() throws NoSuchMethodException {
|
||||
Method response = getClass().getMethod("response", MyGenericType.class);
|
||||
MethodEndpoint methodEndpoint = new MethodEndpoint(this, response);
|
||||
|
||||
expect(unmarshallerMock.supports(response.getGenericParameterTypes()[0])).andReturn(true);
|
||||
expect(marshallerMock.supports(response.getGenericReturnType())).andReturn(true);
|
||||
|
||||
replay(marshallerMock, unmarshallerMock);
|
||||
|
||||
assertTrue("Method unsupported", adapter.supportsInternal(methodEndpoint));
|
||||
|
||||
verify(marshallerMock, unmarshallerMock);
|
||||
}
|
||||
|
||||
public void testUnsupportedMethodMultipleParams() throws NoSuchMethodException {
|
||||
Method unsupported = getClass().getMethod("unsupportedMultipleParams", String.class, String.class);
|
||||
|
||||
replay(marshallerMock, unmarshallerMock);
|
||||
|
||||
assertFalse("Method supported", adapter.supportsInternal(new MethodEndpoint(this, unsupported)));
|
||||
|
||||
verify(marshallerMock, unmarshallerMock);
|
||||
}
|
||||
|
||||
public void testUnsupportedMethodWrongParam() throws NoSuchMethodException {
|
||||
Method unsupported = getClass().getMethod("unsupportedWrongParam", String.class);
|
||||
expect(unmarshallerMock.supports(unsupported.getGenericParameterTypes()[0])).andReturn(false);
|
||||
expect(marshallerMock.supports(unsupported.getGenericReturnType())).andReturn(true);
|
||||
|
||||
replay(marshallerMock, unmarshallerMock);
|
||||
|
||||
assertFalse("Method supported", adapter.supportsInternal(new MethodEndpoint(this, unsupported)));
|
||||
|
||||
verify(marshallerMock, unmarshallerMock);
|
||||
}
|
||||
|
||||
public void testUnsupportedMethodWrongReturnType() throws NoSuchMethodException {
|
||||
Method unsupported = getClass().getMethod("unsupportedWrongParam", String.class);
|
||||
expect(marshallerMock.supports(unsupported.getGenericReturnType())).andReturn(false);
|
||||
|
||||
replay(marshallerMock, unmarshallerMock);
|
||||
|
||||
assertFalse("Method supported", adapter.supportsInternal(new MethodEndpoint(this, unsupported)));
|
||||
|
||||
verify(marshallerMock, unmarshallerMock);
|
||||
}
|
||||
|
||||
public void noResponse(MyGenericType<MyType> type) {
|
||||
noResponseInvoked = true;
|
||||
|
||||
}
|
||||
|
||||
public MyGenericType<MyType> response(MyGenericType<MyType> type) {
|
||||
responseInvoked = true;
|
||||
return type;
|
||||
}
|
||||
|
||||
public void unsupportedMultipleParams(String s1, String s2) {
|
||||
}
|
||||
|
||||
public String unsupportedWrongParam(String s) {
|
||||
return s;
|
||||
}
|
||||
|
||||
private static class MyType {
|
||||
|
||||
}
|
||||
|
||||
private static class MyGenericType<T> {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -19,6 +19,7 @@ package org.springframework.ws.server.endpoint;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.core.JdkVersion;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -120,6 +121,19 @@ public final class MethodEndpoint {
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return this.method.toString();
|
||||
if (JdkVersion.getMajorJavaVersion() <= JdkVersion.JAVA_14) {
|
||||
return this.method.toString();
|
||||
}
|
||||
else {
|
||||
return GenericToStringProvider.toString(method);
|
||||
}
|
||||
}
|
||||
|
||||
/** Inner class to avoid a static JDK 1.5 dependency for generic string generation. */
|
||||
private static class GenericToStringProvider {
|
||||
|
||||
public static String toString(Method method) {
|
||||
return method.toGenericString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,14 +56,6 @@ public class MarshallingMethodEndpointAdapter extends AbstractMethodEndpointAdap
|
||||
|
||||
private Unmarshaller unmarshaller;
|
||||
|
||||
public void setMarshaller(Marshaller marshaller) {
|
||||
this.marshaller = marshaller;
|
||||
}
|
||||
|
||||
public void setUnmarshaller(Unmarshaller unmarshaller) {
|
||||
this.unmarshaller = unmarshaller;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>MarshallingMethodEndpointAdapter</code>. The {@link Marshaller} and {@link Unmarshaller} must
|
||||
* be injected using properties.
|
||||
@@ -94,8 +86,8 @@ public class MarshallingMethodEndpointAdapter extends AbstractMethodEndpointAdap
|
||||
"MarshallingMethodEndpointAdapter(Marshaller, Unmarshaller) constructor.");
|
||||
}
|
||||
else {
|
||||
this.marshaller = marshaller;
|
||||
this.unmarshaller = (Unmarshaller) marshaller;
|
||||
this.setMarshaller(marshaller);
|
||||
this.setUnmarshaller((Unmarshaller) marshaller);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,13 +100,58 @@ public class MarshallingMethodEndpointAdapter extends AbstractMethodEndpointAdap
|
||||
public MarshallingMethodEndpointAdapter(Marshaller marshaller, Unmarshaller unmarshaller) {
|
||||
Assert.notNull(marshaller, "marshaller must not be null");
|
||||
Assert.notNull(unmarshaller, "unmarshaller must not be null");
|
||||
this.setMarshaller(marshaller);
|
||||
this.setUnmarshaller(unmarshaller);
|
||||
}
|
||||
|
||||
/** Returns the marshaller used for transforming objects into XML. */
|
||||
public Marshaller getMarshaller() {
|
||||
return marshaller;
|
||||
}
|
||||
|
||||
/** Sets the marshaller used for transforming objects into XML. */
|
||||
public final void setMarshaller(Marshaller marshaller) {
|
||||
this.marshaller = marshaller;
|
||||
}
|
||||
|
||||
/** Returns the unmarshaller used for transforming XML into objects. */
|
||||
public Unmarshaller getUnmarshaller() {
|
||||
return unmarshaller;
|
||||
}
|
||||
|
||||
/** Sets the unmarshaller used for transforming XML into objects. */
|
||||
public final void setUnmarshaller(Unmarshaller unmarshaller) {
|
||||
this.unmarshaller = unmarshaller;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(marshaller, "marshaller is required");
|
||||
Assert.notNull(unmarshaller, "unmarshaller is required");
|
||||
Assert.notNull(getMarshaller(), "marshaller is required");
|
||||
Assert.notNull(getUnmarshaller(), "unmarshaller is required");
|
||||
}
|
||||
|
||||
protected void invokeInternal(MessageContext messageContext, MethodEndpoint methodEndpoint) throws Exception {
|
||||
WebServiceMessage request = messageContext.getRequest();
|
||||
Object requestObject = unmarshalRequest(request);
|
||||
Object responseObject = methodEndpoint.invoke(new Object[]{requestObject});
|
||||
if (responseObject != null) {
|
||||
WebServiceMessage response = messageContext.getResponse();
|
||||
marshalResponse(responseObject, response);
|
||||
}
|
||||
}
|
||||
|
||||
private Object unmarshalRequest(WebServiceMessage request) throws IOException {
|
||||
Object requestObject = MarshallingUtils.unmarshal(getUnmarshaller(), request);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Unmarshalled payload request to [" + requestObject + "]");
|
||||
}
|
||||
return requestObject;
|
||||
}
|
||||
|
||||
private void marshalResponse(Object responseObject, WebServiceMessage response) throws IOException {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Marshalling [" + responseObject + "] to response payload");
|
||||
}
|
||||
MarshallingUtils.marshal(getMarshaller(), responseObject, response);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -126,34 +163,19 @@ public class MarshallingMethodEndpointAdapter extends AbstractMethodEndpointAdap
|
||||
*/
|
||||
protected boolean supportsInternal(MethodEndpoint methodEndpoint) {
|
||||
Method method = methodEndpoint.getMethod();
|
||||
return (Void.TYPE.isAssignableFrom(method.getReturnType()) || marshaller.supports(method.getReturnType())) &&
|
||||
method.getParameterTypes().length == 1 && unmarshaller.supports(method.getParameterTypes()[0]);
|
||||
return supportsReturnType(method) && supportsParameters(method);
|
||||
}
|
||||
|
||||
protected void invokeInternal(MessageContext messageContext, MethodEndpoint methodEndpoint) throws Exception {
|
||||
WebServiceMessage request = messageContext.getRequest();
|
||||
Object requestObject = unmarshalRequest(request);
|
||||
Object responseObject = methodEndpoint.invoke(new Object[]{requestObject});
|
||||
if (responseObject != null) {
|
||||
WebServiceMessage response = messageContext.getResponse();
|
||||
marshalResponse(responseObject, response);
|
||||
private boolean supportsReturnType(Method method) {
|
||||
return (Void.TYPE.equals(method.getReturnType()) || getMarshaller().supports(method.getReturnType()));
|
||||
}
|
||||
|
||||
private boolean supportsParameters(Method method) {
|
||||
if (method.getParameterTypes().length != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Object unmarshalRequest(WebServiceMessage request) throws IOException {
|
||||
Object requestObject = MarshallingUtils.unmarshal(unmarshaller, request);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Unmarshalled payload request to [" + requestObject + "]");
|
||||
else {
|
||||
return getUnmarshaller().supports(method.getParameterTypes()[0]);
|
||||
}
|
||||
return requestObject;
|
||||
}
|
||||
|
||||
private void marshalResponse(Object responseObject, WebServiceMessage response) throws IOException {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Marshalling [" + responseObject + "] to response payload");
|
||||
}
|
||||
MarshallingUtils.marshal(marshaller, responseObject, response);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -160,7 +160,8 @@ public class MarshallingMethodEndpointAdapterTest extends TestCase {
|
||||
return s;
|
||||
}
|
||||
|
||||
public static class MyType {
|
||||
private static class MyType {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,6 +17,8 @@
|
||||
package org.springframework.ws.server.endpoint.adapter;
|
||||
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.springframework.ws.MockWebServiceMessage;
|
||||
@@ -42,12 +44,12 @@ public class PayloadMethodEndpointAdapterTest extends TestCase {
|
||||
}
|
||||
|
||||
public void testSupportedNoResponse() throws NoSuchMethodException {
|
||||
MethodEndpoint methodEndpoint = new MethodEndpoint(this, "noResponse", new Class[]{Source.class});
|
||||
MethodEndpoint methodEndpoint = new MethodEndpoint(this, "noResponse", new Class[]{DOMSource.class});
|
||||
assertTrue("Method unsupported", adapter.supportsInternal(methodEndpoint));
|
||||
}
|
||||
|
||||
public void testSupportedResponse() throws NoSuchMethodException {
|
||||
MethodEndpoint methodEndpoint = new MethodEndpoint(this, "response", new Class[]{Source.class});
|
||||
MethodEndpoint methodEndpoint = new MethodEndpoint(this, "response", new Class[]{StreamSource.class});
|
||||
assertTrue("Method unsupported", adapter.supportsInternal(methodEndpoint));
|
||||
}
|
||||
|
||||
@@ -67,7 +69,7 @@ public class PayloadMethodEndpointAdapterTest extends TestCase {
|
||||
}
|
||||
|
||||
public void testNoResponse() throws Exception {
|
||||
MethodEndpoint methodEndpoint = new MethodEndpoint(this, "noResponse", new Class[]{Source.class});
|
||||
MethodEndpoint methodEndpoint = new MethodEndpoint(this, "noResponse", new Class[]{DOMSource.class});
|
||||
assertFalse("Method invoked", noResponseInvoked);
|
||||
adapter.invoke(messageContext, methodEndpoint);
|
||||
assertTrue("Method not invoked", noResponseInvoked);
|
||||
@@ -76,17 +78,17 @@ public class PayloadMethodEndpointAdapterTest extends TestCase {
|
||||
public void testResponse() throws Exception {
|
||||
WebServiceMessage request = new MockWebServiceMessage("<request/>");
|
||||
messageContext = new DefaultMessageContext(request, new MockWebServiceMessageFactory());
|
||||
MethodEndpoint methodEndpoint = new MethodEndpoint(this, "response", new Class[]{Source.class});
|
||||
MethodEndpoint methodEndpoint = new MethodEndpoint(this, "response", new Class[]{StreamSource.class});
|
||||
assertFalse("Method invoked", responseInvoked);
|
||||
adapter.invoke(messageContext, methodEndpoint);
|
||||
assertTrue("Method not invoked", responseInvoked);
|
||||
}
|
||||
|
||||
public void noResponse(Source request) {
|
||||
public void noResponse(DOMSource request) {
|
||||
noResponseInvoked = true;
|
||||
}
|
||||
|
||||
public Source response(Source request) {
|
||||
public Source response(StreamSource request) {
|
||||
responseInvoked = true;
|
||||
return request;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.oxm;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* Extension of the {@link Marshaller} interface that supports Java 5 generics. More specifically, this marshaller adds
|
||||
* support for the new {@link Type} hierarchy, returned by methods such as {@link Method#getGenericParameterTypes()} and
|
||||
* {@link Method#getGenericReturnType()}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.0.2
|
||||
*/
|
||||
public interface GenericMarshaller extends Marshaller {
|
||||
|
||||
/**
|
||||
* Indicates whether this marshaller can marshal instances of the supplied type.
|
||||
*
|
||||
* @param type the type that this marshaller is being asked if it can marshal
|
||||
* @return <code>true</code> if this marshaller can indeed marshal instances of the supplied type;
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
boolean supports(Type type);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.oxm;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* Extension of the {@link Unmarshaller} interface that supports Java 5 generics. More specifically, this unmarshaller
|
||||
* adds support for the new {@link Type} hierarchy, returned by methods such as {@link
|
||||
* Method#getGenericParameterTypes()} and {@link Method#getGenericReturnType()}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.0.2
|
||||
*/
|
||||
public interface GenericUnmarshaller extends Unmarshaller {
|
||||
|
||||
/**
|
||||
* Indicates whether this unmarshaller can unmarshal instances of the supplied type.
|
||||
*
|
||||
* @param type the type that this unmarshaller is being asked if it can marshal
|
||||
* @return <code>true</code> if this unmarshaller can indeed unmarshal to the supplied type; <code>false</code>
|
||||
* otherwise
|
||||
*/
|
||||
boolean supports(Type type);
|
||||
}
|
||||
@@ -21,11 +21,13 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.HashMap;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import javax.activation.DataHandler;
|
||||
@@ -34,9 +36,10 @@ import javax.xml.XMLConstants;
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.JAXBIntrospector;
|
||||
import javax.xml.bind.Marshaller;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
import javax.xml.bind.annotation.adapters.XmlAdapter;
|
||||
import javax.xml.bind.attachment.AttachmentMarshaller;
|
||||
import javax.xml.bind.attachment.AttachmentUnmarshaller;
|
||||
@@ -45,6 +48,8 @@ import javax.xml.transform.Source;
|
||||
import javax.xml.validation.Schema;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.oxm.GenericMarshaller;
|
||||
import org.springframework.oxm.GenericUnmarshaller;
|
||||
import org.springframework.oxm.XmlMappingException;
|
||||
import org.springframework.oxm.mime.MimeContainer;
|
||||
import org.springframework.oxm.mime.MimeMarshaller;
|
||||
@@ -77,7 +82,8 @@ import org.springframework.xml.validation.SchemaLoaderUtils;
|
||||
* @see #setAdapters(javax.xml.bind.annotation.adapters.XmlAdapter[])
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class Jaxb2Marshaller extends AbstractJaxbMarshaller implements MimeMarshaller, MimeUnmarshaller {
|
||||
public class Jaxb2Marshaller extends AbstractJaxbMarshaller
|
||||
implements MimeMarshaller, MimeUnmarshaller, GenericMarshaller, GenericUnmarshaller {
|
||||
|
||||
private Resource[] schemaResources;
|
||||
|
||||
@@ -97,8 +103,6 @@ public class Jaxb2Marshaller extends AbstractJaxbMarshaller implements MimeMarsh
|
||||
|
||||
private boolean mtomEnabled = false;
|
||||
|
||||
private Map<Class, Boolean> supportedClasses = new HashMap<Class, Boolean>();
|
||||
|
||||
/**
|
||||
* Sets the <code>XmlAdapter</code>s to be registered with the JAXB <code>Marshaller</code> and
|
||||
* <code>Unmarshaller</code>
|
||||
@@ -163,28 +167,56 @@ public class Jaxb2Marshaller extends AbstractJaxbMarshaller implements MimeMarsh
|
||||
this.unmarshallerListener = unmarshallerListener;
|
||||
}
|
||||
|
||||
public boolean supports(Class clazz) {
|
||||
if (JAXBElement.class.isAssignableFrom(clazz)) {
|
||||
return true;
|
||||
public boolean supports(Type type) {
|
||||
if (type instanceof Class) {
|
||||
return supportsInternal((Class) type, true);
|
||||
}
|
||||
else if (!supportedClasses.containsKey(clazz)) {
|
||||
boolean supported = false;
|
||||
Object instance = null;
|
||||
try {
|
||||
instance = clazz.newInstance();
|
||||
else if (type instanceof ParameterizedType) {
|
||||
ParameterizedType parameterizedType = (ParameterizedType) type;
|
||||
if (JAXBElement.class.equals(parameterizedType.getRawType())) {
|
||||
Type[] typeArguments = parameterizedType.getActualTypeArguments();
|
||||
for (int i = 0; i < typeArguments.length; i++) {
|
||||
if (typeArguments[i] instanceof Class) {
|
||||
if (!supportsInternal((Class) typeArguments[i], false)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!supports(typeArguments[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (InstantiationException e) {
|
||||
// not supported
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
// not supported
|
||||
}
|
||||
JAXBIntrospector introspector = getJaxbContext().createJAXBIntrospector();
|
||||
supported = introspector.isElement(instance);
|
||||
supportedClasses.put(clazz, supported);
|
||||
}
|
||||
return supportedClasses.get(clazz);
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean supports(Class clazz) {
|
||||
return supportsInternal(clazz, true);
|
||||
}
|
||||
|
||||
private boolean supportsInternal(Class<?> clazz, boolean checkForXmlRootElement) {
|
||||
if (checkForXmlRootElement && clazz.getAnnotation(XmlRootElement.class) == null) {
|
||||
return false;
|
||||
}
|
||||
if (clazz.getAnnotation(XmlType.class) == null) {
|
||||
return false;
|
||||
}
|
||||
if (StringUtils.hasLength(getContextPath())) {
|
||||
String className = ClassUtils.getQualifiedName(clazz);
|
||||
int lastDotIndex = className.lastIndexOf('.');
|
||||
if (lastDotIndex == -1) {
|
||||
return false;
|
||||
}
|
||||
String packageName = className.substring(0, lastDotIndex);
|
||||
return getContextPath().startsWith(packageName);
|
||||
}
|
||||
else if (!ObjectUtils.isEmpty(classesToBeBound)) {
|
||||
return Arrays.asList(classesToBeBound).contains(clazz);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* JAXBContext
|
||||
*/
|
||||
|
||||
@@ -18,10 +18,12 @@ package org.springframework.oxm.jaxb;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.StringWriter;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import javax.activation.DataHandler;
|
||||
import javax.activation.FileDataSource;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.stream.XMLEventWriter;
|
||||
@@ -39,6 +41,7 @@ import org.springframework.core.io.Resource;
|
||||
import org.springframework.oxm.XmlMappingException;
|
||||
import org.springframework.oxm.jaxb2.FlightType;
|
||||
import org.springframework.oxm.jaxb2.Flights;
|
||||
import org.springframework.oxm.jaxb2.ObjectFactory;
|
||||
import org.springframework.oxm.mime.MimeContainer;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.xml.transform.StaxResult;
|
||||
@@ -192,8 +195,16 @@ public class Jaxb2MarshallerTest extends XMLTestCase {
|
||||
}
|
||||
|
||||
public void testSupports() throws Exception {
|
||||
assertTrue("Jaxb2Marshaller does not support Flights", marshaller.supports(Flights.class));
|
||||
assertTrue("Jaxb2Marshaller does not support JAXBElement", marshaller.supports(JAXBElement.class));
|
||||
Method createFlights = ObjectFactory.class.getDeclaredMethod("createFlights");
|
||||
assertTrue("Jaxb2Marshaller does not support Flights",
|
||||
marshaller.supports(createFlights.getGenericReturnType()));
|
||||
Method createFlight = ObjectFactory.class.getDeclaredMethod("createFlight", FlightType.class);
|
||||
assertTrue("Jaxb2Marshaller does not support JAXBElement<FlightsType>",
|
||||
marshaller.supports(createFlight.getGenericReturnType()));
|
||||
assertFalse("Jaxb2Marshaller supports non-parameterized JAXBElement", marshaller.supports(JAXBElement.class));
|
||||
JAXBElement<Jaxb2MarshallerTest> testElement =
|
||||
new JAXBElement<Jaxb2MarshallerTest>(new QName("something"), Jaxb2MarshallerTest.class, null, this);
|
||||
assertFalse("Jaxb2Marshaller supports wrong JAXBElement", marshaller.supports(testElement.getClass()));
|
||||
}
|
||||
|
||||
public void testMarshalAttachments() throws Exception {
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd">
|
||||
|
||||
<!-- ===================== ENDPOINTS ===================================== -->
|
||||
@@ -103,7 +101,7 @@
|
||||
MarshallingMethodEndpointAdapter.
|
||||
-->
|
||||
|
||||
<bean class="org.springframework.ws.server.endpoint.adapter.MarshallingMethodEndpointAdapter">
|
||||
<bean class="org.springframework.ws.server.endpoint.adapter.GenericMarshallingMethodEndpointAdapter">
|
||||
<description>
|
||||
This adapter allows for methods that need and returns marshalled objects. The MarshallingEndpoint
|
||||
uses JAXB 2 objects.
|
||||
|
||||
Reference in New Issue
Block a user