/* * Copyright 2005-2014 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.soap.addressing.server; import java.net.URI; import java.util.HashMap; import java.util.Map; import org.springframework.beans.BeansException; import org.springframework.util.Assert; import org.springframework.ws.soap.addressing.core.MessageAddressingProperties; /** * Abstract base class for WS-Addressing {@code Action}-mapped {@link org.springframework.ws.server.EndpointMapping} * implementations. Provides infrastructure for mapping endpoints to actions. * * <p>By default, this mapping creates a {@code Action} for reply messages based on the request message, plus the * extra {@link #setOutputActionSuffix(String) suffix}, and a * By default, this mapping creates a {@code Action} * for reply messages based on the request message, plus the extra {@link #setOutputActionSuffix(String) suffix}. * * @author Arjen Poutsma * @since 1.5.0 */ public abstract class AbstractActionEndpointMapping extends AbstractAddressingEndpointMapping { /** The defaults suffix to add to the request {@code Action} for reply messages. */ public static final String DEFAULT_OUTPUT_ACTION_SUFFIX = "Response"; /** The defaults suffix to add to response {@code Action} for reply messages. */ public static final String DEFAULT_FAULT_ACTION_SUFFIX = "Fault"; // keys are action URIs, values are endpoints private final Map<URI, Object> endpointMap = new HashMap<URI, Object>(); private String outputActionSuffix = DEFAULT_OUTPUT_ACTION_SUFFIX; private String faultActionSuffix = DEFAULT_OUTPUT_ACTION_SUFFIX; /** Returns the suffix to add to request {@code Action}s for reply messages. */ public String getOutputActionSuffix() { return outputActionSuffix; } /** * Sets the suffix to add to request {@code Action}s for reply messages. * * @see #DEFAULT_OUTPUT_ACTION_SUFFIX */ public void setOutputActionSuffix(String outputActionSuffix) { Assert.hasText(outputActionSuffix, "'outputActionSuffix' must not be empty"); this.outputActionSuffix = outputActionSuffix; } /** Returns the suffix to add to request {@code Action}s for reply fault messages. */ public String getFaultActionSuffix() { return faultActionSuffix; } /** * Sets the suffix to add to request {@code Action}s for reply fault messages. * * @see #DEFAULT_FAULT_ACTION_SUFFIX */ public void setFaultActionSuffix(String faultActionSuffix) { Assert.hasText(faultActionSuffix, "'faultActionSuffix' must not be empty"); this.faultActionSuffix = faultActionSuffix; } @Override protected final Object getEndpointInternal(MessageAddressingProperties map) { URI action = map.getAction(); if (logger.isDebugEnabled()) { logger.debug("Looking up endpoint for action [" + action + "]"); } Object endpoint = lookupEndpoint(action); if (endpoint != null) { URI endpointAddress = getEndpointAddress(endpoint); if (endpointAddress == null || endpointAddress.equals(map.getTo())) { return endpoint; } } return null; } /** * Returns the address property of the given endpoint. The value of this property should match the {@link * MessageAddressingProperties#getTo() destination} of incoming messages. May return {@code null} to ignore * the destination. * * @param endpoint the endpoint to return the address for * @return the endpoint address; or {@code null} to ignore the destination property */ protected abstract URI getEndpointAddress(Object endpoint); /** * Looks up an endpoint instance for the given action. All keys are tried in order. * * @param action the action URI * @return the associated endpoint instance, or {@code null} if not found */ protected Object lookupEndpoint(URI action) { return endpointMap.get(action); } /** * Register the specified endpoint for the given action URI. * * @param action the action the bean should be mapped to * @param endpoint the endpoint instance or endpoint bean name String (a bean name will automatically be resolved * into the corresponding endpoint bean) * @throws org.springframework.beans.BeansException * if the endpoint couldn't be registered * @throws IllegalStateException if there is a conflicting endpoint registered */ protected void registerEndpoint(URI action, Object endpoint) throws BeansException, IllegalStateException { Assert.notNull(action, "Action must not be null"); Assert.notNull(endpoint, "Endpoint object must not be null"); Object resolvedEndpoint = endpoint; if (endpoint instanceof String) { String endpointName = (String) endpoint; if (getApplicationContext().isSingleton(endpointName)) { resolvedEndpoint = getApplicationContext().getBean(endpointName); } } Object mappedEndpoint = this.endpointMap.get(action); if (mappedEndpoint != null) { if (mappedEndpoint != resolvedEndpoint) { throw new IllegalStateException("Cannot map endpoint [" + endpoint + "] to action [" + action + "]: There is already endpoint [" + resolvedEndpoint + "] mapped."); } } else { this.endpointMap.put(action, resolvedEndpoint); if (logger.isDebugEnabled()) { logger.debug("Mapped Action [" + action + "] onto endpoint [" + resolvedEndpoint + "]"); } } } @Override protected URI getResponseAction(Object endpoint, MessageAddressingProperties requestMap) { URI requestAction = requestMap.getAction(); if (requestAction != null) { return URI.create(requestAction.toString() + getOutputActionSuffix()); } else { return null; } } @Override protected URI getFaultAction(Object endpoint, MessageAddressingProperties requestMap) { URI requestAction = requestMap.getAction(); if (requestAction != null) { return URI.create(requestAction.toString() + getFaultActionSuffix()); } else { return null; } } }