Hi !
To use spring-ws with spring-integration and redirect multiple WS to one gateway I needed to match URI with an Ant pattern instead of a complete URI. I needed too to remove the context of URI.
The AbstractMapBasedEndpointMapping class doesn't allow access to the endpointMap, so I can't herit it, nor UriEndpointMapping.
The result is this class :
I replace the HashMap's by LinkedHashMap's to ensure the order (like precised in the javadocCode:package org.springframework.ws.server.endpoint.mapping; import java.net.URI; import java.net.URISyntaxException; import java.util.LinkedHashMap; import java.util.Map; import java.util.Properties; import java.util.regex.Pattern; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContextException; import org.springframework.util.AntPathMatcher; import org.springframework.util.PathMatcher; import org.springframework.util.StringUtils; import org.springframework.ws.context.MessageContext; import org.springframework.ws.transport.WebServiceConnection; import org.springframework.ws.transport.context.TransportContext; import org.springframework.ws.transport.context.TransportContextHolder; public class AntUriEndpointMapping extends AbstractEndpointMapping { private boolean lazyInitEndpoints = false; private boolean registerBeanNames = false; private PathMatcher pathMatcher = new AntPathMatcher(); private Pattern contextPattern = Pattern.compile("^/[^/]*"); private final Map<String, Object> endpointMap = new LinkedHashMap<String, Object>(); // holds mappings set via setEndpointMap and setMappings private Map<String, Object> temporaryEndpointMap = new LinkedHashMap<String, Object>(); private boolean usePath = false; private boolean omitContext = false; /** * Set whether to lazily initialize endpoints. Only applicable to singleton endpoints, as prototypes are always lazily initialized. Default is * <code>false</code>, as eager initialization allows for more efficiency through referencing the controller objects directly. * <p/> * If you want to allow your endpoints to be lazily initialized, make them "lazy-init" and set this flag to <code>true</code>. Just making them * "lazy-init" will not work, as they are initialized through the references from the endpoint mapping in this case. */ public void setLazyInitEndpoints(boolean lazyInitEndpoints) { this.lazyInitEndpoints = lazyInitEndpoints; } /** * Set whether to register bean names found in the application context. Setting this to <code>true</code> will register all beans found in the * application context under their name. Default is <code>false</code>. */ public final void setRegisterBeanNames(boolean registerBeanNames) { this.registerBeanNames = registerBeanNames; } /** * Sets a Map with keys and endpoint beans as values. The nature of the keys in the given map depends on the exact subclass used. They can be * qualified names, for instance, or mime headers. * * @throws IllegalArgumentException * if the endpoint is invalid */ public final void setEndpointMap(Map<String, Object> endpointMap) { temporaryEndpointMap.putAll(endpointMap); } /** * Maps keys to endpoint bean names. The nature of the property names depends on the exact subclass used. They can be qualified names, for * instance, or mime headers. */ public void setMappings(Properties mappings) { for (Map.Entry<Object, Object> entry : mappings.entrySet()) { if (entry.getKey() instanceof String) { temporaryEndpointMap.put((String) entry.getKey(), entry.getValue()); } } } /** * Indicates whether the path should be used instead of the full URI. Default is {@code false}. * * @since 2.1.1 */ public void setUsePath(boolean usePath) { this.usePath = usePath; } public void setOmitContext(boolean omitContext) { this.omitContext = omitContext; if (omitContext) { // omitContext=true implies usePath=true setUsePath(true); } } /** Validates the given endpoint key. Should return <code>true</code> is the given string is valid. */ protected boolean validateLookupKey(String key) { try { new URI(key); return true; } catch (URISyntaxException e) { return false; } } /** * Returns the the endpoint key for the given message context. Returns <code>null</code> if a key cannot be found. * * @return the registration key; or <code>null</code> */ protected String getLookupKeyForMessage(MessageContext messageContext) throws Exception { TransportContext transportContext = TransportContextHolder.getTransportContext(); if (transportContext != null) { WebServiceConnection connection = transportContext.getConnection(); if (connection != null) { URI connectionUri = connection.getUri(); if (usePath) { String path = connectionUri.getPath(); if (omitContext) { return contextPattern.matcher(path).replaceFirst(""); } else { return path; } } else { return connectionUri.toString(); } } } return null; } /** * 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> */ @Override 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); } /** * 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 Object lookupEndpoint(String key) { for (Map.Entry<String, Object> endpointEntry : endpointMap.entrySet()) { if (pathMatcher.match(endpointEntry.getKey(), key)) { return endpointEntry.getValue(); } } return null; } /** * Register the given endpoint instance under the registration key. * * @param key * the string representation of the registration key * @param endpoint * the endpoint instance * @throws org.springframework.beans.BeansException * if the endpoint could not be registered */ protected void registerEndpoint(String key, Object 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 (!lazyInitEndpoints && endpoint instanceof String) { String endpointName = (String) endpoint; endpoint = resolveStringEndpoint(endpointName); } 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 + "]"); } } /** * Registers annd checks the set endpoints. Checks the beans set through <code>setEndpointMap</code> and <code>setMappings</code>, and registers * the bean names found in the application context, if <code>registerBeanNames</code> is set to <code>true</code>. * * @throws ApplicationContextException * if either of the endpoints defined via <code>setEndpointMap</code> or <code>setMappings</code> is invalid * @see #setEndpointMap(java.util.Map) * @see #setMappings(java.util.Properties) * @see #setRegisterBeanNames(boolean) */ @Override protected final void initApplicationContext() throws BeansException { super.initApplicationContext(); for (String key : temporaryEndpointMap.keySet()) { Object endpoint = temporaryEndpointMap.get(key); if (!validateLookupKey(key)) { throw new ApplicationContextException("Invalid key [" + key + "] for endpoint [" + endpoint + "]"); } registerEndpoint(key, endpoint); } temporaryEndpointMap = null; if (registerBeanNames) { if (logger.isDebugEnabled()) { logger.debug("Looking for endpoint mappings in application context: [" + getApplicationContext() + "]"); } String[] beanNames = getApplicationContext().getBeanDefinitionNames(); for (String beanName : beanNames) { if (validateLookupKey(beanName)) { registerEndpoint(beanName, beanName); } String[] aliases = getApplicationContext().getAliases(beanName); for (String aliase : aliases) { if (validateLookupKey(aliase)) { registerEndpoint(aliase, beanName); } } } } } })
hope it will be usefull for someone
Gabe



)
Reply With Quote