Moved MethodEndpoint functionality to core-tiger module. (Fixed #SWS-20)
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Represents a bean method that will be invoked as part of an incoming Web service message.
|
||||
* <p/>
|
||||
* Consists of a {@link Method}, and a bean {@link Object}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public final class MethodEndpoint {
|
||||
|
||||
private Object bean;
|
||||
|
||||
private Method method;
|
||||
|
||||
/**
|
||||
* Constructs a new method endpoint with the given bean and method.
|
||||
*
|
||||
* @param bean the object bean
|
||||
* @param method the method
|
||||
*/
|
||||
public MethodEndpoint(Object bean, Method method) {
|
||||
Assert.notNull(bean, "bean must not be null");
|
||||
Assert.notNull(method, "method must not be null");
|
||||
this.bean = bean;
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new method endpoint with the given bean, method name and parameters.
|
||||
*
|
||||
* @param bean the object bean
|
||||
* @param methodName the method name
|
||||
* @param parameterTypes the method parameter types
|
||||
*/
|
||||
public MethodEndpoint(Object bean, String methodName, Class[] parameterTypes) throws NoSuchMethodException {
|
||||
Assert.notNull(bean, "bean must not be null");
|
||||
Assert.notNull(methodName, "method must not be null");
|
||||
this.bean = bean;
|
||||
method = bean.getClass().getMethod(methodName, parameterTypes);
|
||||
}
|
||||
|
||||
/** Returns the object bean for this method endpoint. */
|
||||
public Object getBean() {
|
||||
return bean;
|
||||
}
|
||||
|
||||
/** Returns the method for this method endpoint. */
|
||||
public Method getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes this method endpoint with the given arguments.
|
||||
*
|
||||
* @param args the arguments
|
||||
* @return the invocation result
|
||||
* @throws IllegalAccessException when there is insufficient access to invoke the method
|
||||
* @throws InvocationTargetException when the method invocation results in an exception
|
||||
*/
|
||||
public Object invoke(Object[] args) throws IllegalAccessException, InvocationTargetException {
|
||||
return method.invoke(bean, args);
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o != null && o instanceof MethodEndpoint) {
|
||||
MethodEndpoint other = (MethodEndpoint) o;
|
||||
return bean.equals(other.bean) && method.equals(other.method);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return 31 * bean.hashCode() + method.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return method.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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 org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.ws.context.MessageContext;
|
||||
import org.springframework.ws.server.EndpointAdapter;
|
||||
import org.springframework.ws.server.endpoint.MethodEndpoint;
|
||||
import org.springframework.xml.transform.TransformerObjectSupport;
|
||||
|
||||
/**
|
||||
* Abstract base class for {@link EndpointAdapter} implementations that support {@link MethodEndpoint}s. Contains
|
||||
* template methods for handling these method endpoints.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public abstract class AbstractMethodEndpointAdapter extends TransformerObjectSupport implements EndpointAdapter {
|
||||
|
||||
/** Logger available to subclasses. */
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
/**
|
||||
* Delegates to {@link #supportsInternal(org.springframework.ws.server.endpoint.MethodEndpoint)}.
|
||||
*
|
||||
* @param endpoint endpoint object to check
|
||||
* @return whether or not this adapter can adapt the given endpoint
|
||||
*/
|
||||
public final boolean supports(Object endpoint) {
|
||||
return endpoint instanceof MethodEndpoint && supportsInternal((MethodEndpoint) endpoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link #invokeInternal(org.springframework.ws.context.MessageContext,MethodEndpoint)}.
|
||||
*
|
||||
* @param messageContext the current message context
|
||||
* @param endpoint the endpoint to use. This object must have previously been passed to the
|
||||
* <code>supportsInternal</code> method of this interface, which must have returned
|
||||
* <code>true</code>
|
||||
* @throws Exception in case of errors
|
||||
*/
|
||||
public final void invoke(MessageContext messageContext, Object endpoint) throws Exception {
|
||||
invokeInternal(messageContext, (MethodEndpoint) endpoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a method endpoint, return whether or not this adapter can support it.
|
||||
*
|
||||
* @param methodEndpoint method endpoint to check
|
||||
* @return whether or not this adapter can adapt the given method
|
||||
*/
|
||||
protected abstract boolean supportsInternal(MethodEndpoint methodEndpoint);
|
||||
|
||||
/**
|
||||
* Use the given method endpoint to handle the request.
|
||||
*
|
||||
* @param messageContext the current message context
|
||||
* @param methodEndpoint the method endpoint to use
|
||||
* @throws Exception in case of errors
|
||||
*/
|
||||
protected abstract void invokeInternal(MessageContext messageContext, MethodEndpoint methodEndpoint)
|
||||
throws Exception;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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.mapping;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContextException;
|
||||
import org.springframework.core.JdkVersion;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.ws.context.MessageContext;
|
||||
import org.springframework.ws.server.endpoint.MethodEndpoint;
|
||||
|
||||
/**
|
||||
* Abstract base class for {@link MethodEndpoint} mappings.
|
||||
* <p/>
|
||||
* Subclasses typically implement {@link org.springframework.beans.factory.config.BeanPostProcessor} to look for beans
|
||||
* that qualify as enpoint. The methods of this bean are then registered under a specific key with {@link
|
||||
* #registerEndpoint(String,MethodEndpoint)}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public abstract class AbstractMethodEndpointMapping extends AbstractEndpointMapping {
|
||||
|
||||
/** Keys are Strings, values are {@link MethodEndpoint}s. */
|
||||
private final Map endpointMap = new HashMap();
|
||||
|
||||
/**
|
||||
* Lookup an endpoint for the given message. The extraction of the endpoint key is delegated to the concrete
|
||||
* subclass.
|
||||
*
|
||||
* @return the looked up endpoint, or <code>null</code>
|
||||
* @see #getLookupKeyForMessage(MessageContext)
|
||||
*/
|
||||
protected Object getEndpointInternal(MessageContext messageContext) throws Exception {
|
||||
String key = getLookupKeyForMessage(messageContext);
|
||||
if (!StringUtils.hasLength(key)) {
|
||||
return null;
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Looking up endpoint for [" + key + "]");
|
||||
}
|
||||
return lookupEndpoint(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the the endpoint keys for the given message context.
|
||||
*
|
||||
* @return the registration keys
|
||||
*/
|
||||
protected abstract String getLookupKeyForMessage(MessageContext messageContext) throws Exception;
|
||||
|
||||
/**
|
||||
* Looks up an endpoint instance for the given keys. All keys are tried in order.
|
||||
*
|
||||
* @param key key the beans are mapped to
|
||||
* @return the associated endpoint instance, or <code>null</code> if not found
|
||||
*/
|
||||
protected MethodEndpoint lookupEndpoint(String key) {
|
||||
return (MethodEndpoint) endpointMap.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the given endpoint instance under the key.
|
||||
*
|
||||
* @param key the lookup key
|
||||
* @param endpoint the method endpoint instance
|
||||
* @throws BeansException if the endpoint could not be registered
|
||||
*/
|
||||
protected void registerEndpoint(String key, MethodEndpoint endpoint) throws BeansException {
|
||||
Object mappedEndpoint = endpointMap.get(key);
|
||||
if (mappedEndpoint != null) {
|
||||
throw new ApplicationContextException("Cannot map endpoint [" + endpoint + "] on registration key [" + key +
|
||||
"]: there's already endpoint [" + mappedEndpoint + "] mapped");
|
||||
}
|
||||
if (endpoint == null) {
|
||||
throw new ApplicationContextException("Could not find endpoint for key [" + key + "]");
|
||||
}
|
||||
endpointMap.put(key, endpoint);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Mapped key [" + key + "] onto endpoint [" + endpoint + "]");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that registers the methods of the given bean. This method iterates over the methods of the bean,
|
||||
* and calls {@link #getLookupKeyForMethod(Method)} for each. If this returns a string, the method is registered
|
||||
* using {@link #registerEndpoint(String,MethodEndpoint)}.
|
||||
*
|
||||
* @see #getLookupKeyForMethod(Method)
|
||||
*/
|
||||
protected void registerMethods(Object endpoint) {
|
||||
Method[] methods = getEndpointClass(endpoint).getMethods();
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
if (JdkVersion.isAtLeastJava15() && methods[i].isSynthetic() ||
|
||||
methods[i].getDeclaringClass().equals(Object.class)) {
|
||||
continue;
|
||||
}
|
||||
String key = getLookupKeyForMethod(methods[i]);
|
||||
if (StringUtils.hasLength(key)) {
|
||||
registerEndpoint(key, new MethodEndpoint(endpoint, methods[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the the endpoint keys for the given method. Returns <code>null</code> if the method is not to be
|
||||
* registered, which is the default.
|
||||
*
|
||||
* @param method the method
|
||||
* @return a registration key, or <code>null</code> if the method is not to be registered
|
||||
*/
|
||||
protected String getLookupKeyForMethod(Method method) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the class or interface to use for method reflection.
|
||||
* <p/>
|
||||
* Default implementation returns the target class for a CGLIB proxy, and the class of the given bean else (for a
|
||||
* JDK proxy or a plain bean class).
|
||||
*
|
||||
* @param endpoint the bean instance (might be an AOP proxy)
|
||||
* @return the bean class to expose
|
||||
*/
|
||||
protected Class getEndpointClass(Object endpoint) {
|
||||
if (AopUtils.isCglibProxy(endpoint)) {
|
||||
return endpoint.getClass().getSuperclass();
|
||||
}
|
||||
return endpoint.getClass();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,13 +17,11 @@
|
||||
package org.springframework.ws.server.endpoint.mapping;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMResult;
|
||||
|
||||
import org.springframework.ws.WebServiceMessage;
|
||||
import org.springframework.ws.context.MessageContext;
|
||||
import org.springframework.xml.dom.DomUtils;
|
||||
import org.springframework.xml.namespace.QNameUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
@@ -56,15 +54,10 @@ public class PayloadRootQNameEndpointMapping extends AbstractQNameEndpointMappin
|
||||
}
|
||||
|
||||
protected QName resolveQName(MessageContext messageContext) throws TransformerException {
|
||||
Element payloadElement = getMessagePayloadElement(messageContext.getRequest());
|
||||
Element payloadElement =
|
||||
DomUtils.getRootElement(messageContext.getRequest().getPayloadSource(), transformerFactory);
|
||||
return QNameUtils.getQNameForNode(payloadElement);
|
||||
}
|
||||
|
||||
private Element getMessagePayloadElement(WebServiceMessage message) throws TransformerException {
|
||||
Transformer transformer = transformerFactory.newTransformer();
|
||||
DOMResult domResult = new DOMResult();
|
||||
transformer.transform(message.getPayloadSource(), domResult);
|
||||
return (Element) domResult.getNode().getFirstChild();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ import org.springframework.ws.transport.WebServiceConnection;
|
||||
* Commons HttpClient</a> to execute POST requests.
|
||||
* <p/>
|
||||
* Allows to use a preconfigured HttpClient instance, potentially with authentication, HTTP connection pooling, etc.
|
||||
* Also designed for easy subclassing, customizing specific template methods.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @see org.springframework.ws.transport.http.HttpUrlConnectionMessageSender
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class MethodEndpointTest extends TestCase {
|
||||
|
||||
private MethodEndpoint endpoint;
|
||||
|
||||
private boolean myMethodInvoked;
|
||||
|
||||
private Method method;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
myMethodInvoked = false;
|
||||
method = getClass().getMethod("myMethod", new Class[]{String.class});
|
||||
endpoint = new MethodEndpoint(this, method);
|
||||
}
|
||||
|
||||
public void testGetters() throws Exception {
|
||||
assertEquals("Invalid bean", this, endpoint.getBean());
|
||||
assertEquals("Invalid bean", method, endpoint.getMethod());
|
||||
}
|
||||
|
||||
public void testInvoke() throws Exception {
|
||||
assertFalse("Method invoked before invocation", myMethodInvoked);
|
||||
endpoint.invoke(new Object[]{"arg"});
|
||||
assertTrue("Method invoked before invocation", myMethodInvoked);
|
||||
}
|
||||
|
||||
public void testEquals() throws Exception {
|
||||
assertEquals("Not equal", endpoint, endpoint);
|
||||
assertEquals("Not equal", new MethodEndpoint(this, method), endpoint);
|
||||
Method otherMethod = getClass().getMethod("testEquals", new Class[0]);
|
||||
assertFalse("Equal", new MethodEndpoint(this, otherMethod).equals(endpoint));
|
||||
}
|
||||
|
||||
public void testHashCode() throws Exception {
|
||||
assertEquals("Not equal", new MethodEndpoint(this, method).hashCode(), endpoint.hashCode());
|
||||
Method otherMethod = getClass().getMethod("testEquals", new Class[0]);
|
||||
assertFalse("Equal", new MethodEndpoint(this, otherMethod).hashCode() == endpoint.hashCode());
|
||||
}
|
||||
|
||||
public void myMethod(String arg) {
|
||||
assertEquals("Invalid argument", "arg", arg);
|
||||
myMethodInvoked = true;
|
||||
}
|
||||
|
||||
public void testToString() throws Exception {
|
||||
assertNotNull("Na valid toString", endpoint.toString());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user