001: /*
002: * Copyright 2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.ws.server.endpoint.adapter;
018:
019: import java.io.IOException;
020: import java.lang.reflect.Method;
021:
022: import org.springframework.beans.factory.InitializingBean;
023: import org.springframework.oxm.Marshaller;
024: import org.springframework.oxm.Unmarshaller;
025: import org.springframework.util.Assert;
026: import org.springframework.ws.WebServiceMessage;
027: import org.springframework.ws.context.MessageContext;
028: import org.springframework.ws.server.EndpointMapping;
029: import org.springframework.ws.server.endpoint.MethodEndpoint;
030: import org.springframework.ws.support.MarshallingUtils;
031:
032: /**
033: * Adapter that supports endpoint methods that use marshalling. Supports methods with the following signature:
034: * <pre>
035: * void handleMyMessage(MyUnmarshalledType request);
036: * </pre>
037: * or
038: * <pre>
039: * MyMarshalledType handleMyMessage(MyUnmarshalledType request);
040: * </pre>
041: * I.e. methods that take a single parameter that {@link Unmarshaller#supports(Class) is supported} by the {@link
042: * Unmarshaller}, and return either <code>void</code> or a type {@link Marshaller#supports(Class) supported} by the
043: * {@link Marshaller}. The method can have any name, as long as it is mapped by an {@link EndpointMapping}.
044: * <p/>
045: * This endpoint needs a <code>Marshaller</code> and <code>Unmarshaller</code>, both of which can be set using
046: * properties.
047: *
048: * @author Arjen Poutsma
049: * @see #setMarshaller(org.springframework.oxm.Marshaller)
050: * @see #setUnmarshaller(org.springframework.oxm.Unmarshaller)
051: * @since 1.0.0
052: */
053: public class MarshallingMethodEndpointAdapter extends
054: AbstractMethodEndpointAdapter implements InitializingBean {
055:
056: private Marshaller marshaller;
057:
058: private Unmarshaller unmarshaller;
059:
060: public void setMarshaller(Marshaller marshaller) {
061: this .marshaller = marshaller;
062: }
063:
064: public void setUnmarshaller(Unmarshaller unmarshaller) {
065: this .unmarshaller = unmarshaller;
066: }
067:
068: /**
069: * Creates a new <code>MarshallingMethodEndpointAdapter</code>. The {@link Marshaller} and {@link Unmarshaller} must
070: * be injected using properties.
071: *
072: * @see #setMarshaller(org.springframework.oxm.Marshaller)
073: * @see #setUnmarshaller(org.springframework.oxm.Unmarshaller)
074: */
075: public MarshallingMethodEndpointAdapter() {
076: }
077:
078: /**
079: * Creates a new <code>MarshallingMethodEndpointAdapter</code> with the given marshaller. If the given {@link
080: * Marshaller} also implements the {@link Unmarshaller} interface, it is used for both marshalling and
081: * unmarshalling. Otherwise, an exception is thrown.
082: * <p/>
083: * Note that all {@link Marshaller} implementations in Spring-WS also implement the {@link Unmarshaller} interface,
084: * so that you can safely use this constructor.
085: *
086: * @param marshaller object used as marshaller and unmarshaller
087: * @throws IllegalArgumentException when <code>marshaller</code> does not implement the {@link Unmarshaller}
088: * interface
089: */
090: public MarshallingMethodEndpointAdapter(Marshaller marshaller) {
091: Assert.notNull(marshaller, "marshaller must not be null");
092: if (!(marshaller instanceof Unmarshaller)) {
093: throw new IllegalArgumentException(
094: "Marshaller ["
095: + marshaller
096: + "] does not implement the Unmarshaller "
097: + "interface. Please set an Unmarshaller explicitely by using the "
098: + "MarshallingMethodEndpointAdapter(Marshaller, Unmarshaller) constructor.");
099: } else {
100: this .marshaller = marshaller;
101: this .unmarshaller = (Unmarshaller) marshaller;
102: }
103: }
104:
105: /**
106: * Creates a new <code>MarshallingMethodEndpointAdapter</code> with the given marshaller and unmarshaller.
107: *
108: * @param marshaller the marshaller to use
109: * @param unmarshaller the unmarshaller to use
110: */
111: public MarshallingMethodEndpointAdapter(Marshaller marshaller,
112: Unmarshaller unmarshaller) {
113: Assert.notNull(marshaller, "marshaller must not be null");
114: Assert.notNull(unmarshaller, "unmarshaller must not be null");
115: this .marshaller = marshaller;
116: this .unmarshaller = unmarshaller;
117: }
118:
119: public void afterPropertiesSet() throws Exception {
120: Assert.notNull(marshaller, "marshaller is required");
121: Assert.notNull(unmarshaller, "unmarshaller is required");
122: }
123:
124: /**
125: * Supports a method with a single, unmarshallable parameter, and that return <code>void</code> or a marshallable
126: * type.
127: *
128: * @see Marshaller#supports(Class)
129: * @see Unmarshaller#supports(Class)
130: */
131: protected boolean supportsInternal(MethodEndpoint methodEndpoint) {
132: Method method = methodEndpoint.getMethod();
133: return (Void.TYPE.isAssignableFrom(method.getReturnType()) || marshaller
134: .supports(method.getReturnType()))
135: && method.getParameterTypes().length == 1
136: && unmarshaller.supports(method.getParameterTypes()[0]);
137: }
138:
139: protected void invokeInternal(MessageContext messageContext,
140: MethodEndpoint methodEndpoint) throws Exception {
141: WebServiceMessage request = messageContext.getRequest();
142: Object requestObject = unmarshalRequest(request);
143: Object responseObject = methodEndpoint
144: .invoke(new Object[] { requestObject });
145: if (responseObject != null) {
146: WebServiceMessage response = messageContext.getResponse();
147: marshalResponse(responseObject, response);
148: }
149:
150: }
151:
152: private Object unmarshalRequest(WebServiceMessage request)
153: throws IOException {
154: Object requestObject = MarshallingUtils.unmarshal(unmarshaller,
155: request);
156: if (logger.isDebugEnabled()) {
157: logger.debug("Unmarshalled payload request to ["
158: + requestObject + "]");
159: }
160: return requestObject;
161: }
162:
163: private void marshalResponse(Object responseObject,
164: WebServiceMessage response) throws IOException {
165: if (logger.isDebugEnabled()) {
166: logger.debug("Marshalling [" + responseObject
167: + "] to response payload");
168: }
169: MarshallingUtils.marshal(marshaller, responseObject, response);
170: }
171:
172: }
|