| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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.apache.camel.component.spring.ws.bean; |
| |
| import java.net.URI; |
| import java.util.Map; |
| import java.util.concurrent.ConcurrentHashMap; |
| |
| import org.apache.camel.RuntimeCamelException; |
| import org.apache.camel.component.spring.ws.SpringWebserviceConsumer; |
| import org.apache.camel.component.spring.ws.SpringWebserviceEndpoint; |
| import org.apache.camel.component.spring.ws.type.EndpointMappingKey; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| import org.springframework.util.Assert; |
| import org.springframework.ws.server.endpoint.MessageEndpoint; |
| import org.springframework.ws.soap.addressing.core.MessageAddressingProperties; |
| import org.springframework.ws.soap.addressing.messageid.MessageIdStrategy; |
| import org.springframework.ws.soap.addressing.server.AbstractAddressingEndpointMapping; |
| import org.springframework.ws.soap.addressing.server.AnnotationActionEndpointMapping; |
| import org.springframework.ws.transport.WebServiceMessageSender; |
| |
| /** |
| * Provides support for full WS-Addressing. Supported are faultAction and |
| * response action. For more details look at @see |
| * {@link AbstractAddressingEndpointMapping}. Implementation of the |
| * {@link org.springframework.ws.server.EndpointMapping} consumer interface that |
| * uses the camel uri to map to a WS-Addressing {@code Action} header. |
| * <p/> |
| */ |
| public class WSACamelEndpointMapping extends AbstractAddressingEndpointMapping implements CamelSpringWSEndpointMapping { |
| |
| private static final Logger LOG = LoggerFactory.getLogger(WSACamelEndpointMapping.class); |
| |
| private Map<EndpointMappingKey, MessageEndpoint> endpoints = new ConcurrentHashMap<>(); |
| |
| private String outputActionSuffix = AnnotationActionEndpointMapping.DEFAULT_OUTPUT_ACTION_SUFFIX; |
| |
| private String faultActionSuffix = AnnotationActionEndpointMapping.DEFAULT_OUTPUT_ACTION_SUFFIX; |
| |
| @Override |
| protected Object getEndpointInternal(MessageAddressingProperties map) { |
| // search the endpoint with compositeKeyFirst |
| for (EndpointMappingKey key : endpoints.keySet()) { |
| String compositeOrSimpleKey = null; |
| switch (key.getType()) { |
| case ACTION: |
| compositeOrSimpleKey = getActionCompositeLookupKey(map); |
| break; |
| case TO: |
| compositeOrSimpleKey = getToCompositeLookupKey(map); |
| break; |
| default: |
| throw new RuntimeCamelException( |
| "Invalid mapping type specified. Supported types are: spring-ws:action:<WS-Addressing Action>(optional:<WS-Addressing To>?<params...>\n)" |
| + "spring-ws:to:<WS-Addressing To>(optional:<WS-Addressing Action>?<params...>)"); |
| } |
| // lookup for specific endpoint |
| if (compositeOrSimpleKey != null && key.getLookupKey().equals(compositeOrSimpleKey)) { |
| LOG.debug("Found mapping for key {}", key); |
| return endpoints.get(key); |
| } |
| } |
| |
| // look up for the simple key |
| for (EndpointMappingKey key : endpoints.keySet()) { |
| String simpleKey = null; |
| switch (key.getType()) { |
| case ACTION: |
| if (map.getAction() != null) { |
| simpleKey = map.getAction().toString(); |
| } |
| break; |
| case TO: |
| if (map.getTo() != null) { |
| simpleKey = map.getTo().toString(); |
| } |
| break; |
| default: |
| throw new RuntimeCamelException( |
| "Invalid mapping type specified. Supported types are: spring-ws:action:<WS-Addressing Action>(optional:<WS-Addressing To>?<params...>\n)" |
| + "spring-ws:to:<WS-Addressing To>(optional:<WS-Addressing Action>?<params...>)"); |
| } |
| // look up for less specific endpoint |
| if (simpleKey != null && key.getLookupKey().equals(simpleKey)) { |
| LOG.debug("Found mapping for key {}", key); |
| return endpoints.get(key); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Generate a lookupKey for a given WS-Addressing message using action |
| * property. The possible combination are: |
| * <ul> |
| * <li>wsaAction</li> |
| * <li>wsaAction:wsaGetTo</li> |
| * </ul> |
| * |
| * @param map |
| * @return |
| */ |
| protected String getActionCompositeLookupKey(MessageAddressingProperties map) { |
| String key = ""; |
| if (map.getAction() != null) { |
| key = map.getAction().toString(); |
| } |
| if (map.getTo() != null) { |
| if (!key.isEmpty()) { |
| key += ":"; |
| } |
| key += map.getTo().toString(); |
| } |
| return key; |
| } |
| |
| /** |
| * Generate a lookupKey for a given WS-Addressing message using getTo |
| * property. The possible combination are: |
| * <ul> |
| * <li>wsaGetTo</li> |
| * <li>wsaGetTo:wsaAction</li> |
| * </ul> |
| * |
| * @param map |
| * @return |
| */ |
| protected String getToCompositeLookupKey(MessageAddressingProperties map) { |
| String key = ""; |
| if (map.getTo() != null) { |
| key = map.getTo().toString(); |
| } |
| if (map.getAction() != null) { |
| if (!key.isEmpty()) { |
| key += ":"; |
| } |
| key += map.getAction().toString(); |
| } |
| return key; |
| } |
| |
| /** |
| * Return output camel uri param or default action or null |
| */ |
| @Override |
| protected URI getResponseAction(Object endpoint, MessageAddressingProperties requestMap) { |
| SpringWebserviceEndpoint camelEndpoint = getSpringWebserviceEndpoint(endpoint); |
| |
| URI actionUri = camelEndpoint.getConfiguration().getOutputAction(); |
| if (actionUri == null) { |
| actionUri = getDefaultResponseAction(camelEndpoint, requestMap); |
| } |
| return actionUri; |
| } |
| |
| /** |
| * Configure message sender for wsa:replyTo from a camel route definition. |
| * The route definition has priority over this endpoint. |
| */ |
| @Override |
| protected WebServiceMessageSender[] getMessageSenders(Object endpoint) { |
| SpringWebserviceEndpoint camelEndpoint = getSpringWebserviceEndpoint(endpoint); |
| |
| if (camelEndpoint.getConfiguration().getMessageSender() != null) { |
| return new WebServiceMessageSender[] {camelEndpoint.getConfiguration().getMessageSender()}; |
| } |
| |
| return super.getMessageSenders(endpoint); |
| } |
| |
| /** |
| * Configure message id strategy for wsa:replyTo The route definition has |
| * priority over this endpoint. |
| */ |
| @Override |
| protected MessageIdStrategy getMessageIdStrategy(Object endpoint) { |
| SpringWebserviceEndpoint camelEndpoint = getSpringWebserviceEndpoint(endpoint); |
| |
| if (camelEndpoint.getConfiguration().getMessageIdStrategy() != null) { |
| return camelEndpoint.getConfiguration().getMessageIdStrategy(); |
| } |
| |
| return super.getMessageIdStrategy(endpoint); |
| } |
| |
| /** |
| * return fault came uri param or default fault action or null |
| */ |
| @Override |
| protected URI getFaultAction(Object endpoint, MessageAddressingProperties requestMap) { |
| SpringWebserviceEndpoint camelEndpoint = getSpringWebserviceEndpoint(endpoint); |
| |
| URI actionUri = camelEndpoint.getConfiguration().getFaultAction(); |
| if (actionUri == null) { |
| actionUri = getDefaultFaultAction(camelEndpoint, requestMap); |
| } |
| return actionUri; |
| |
| } |
| |
| private SpringWebserviceEndpoint getSpringWebserviceEndpoint(Object endpoint) { |
| Assert.isInstanceOf(SpringWebserviceConsumer.class, endpoint, "Endpoint needs to be an instance of SpringWebserviceConsumer"); |
| |
| SpringWebserviceConsumer springWebserviceConsumer = (SpringWebserviceConsumer)endpoint; |
| return (SpringWebserviceEndpoint)springWebserviceConsumer.getEndpoint(); |
| } |
| |
| protected URI getDefaultResponseAction(Object endpoint, MessageAddressingProperties requestMap) { |
| URI requestAction = requestMap.getAction(); |
| if (requestAction != null) { |
| return URI.create(requestAction.toString() + getOutputActionSuffix()); |
| } else { |
| return null; |
| } |
| } |
| |
| protected URI getDefaultFaultAction(Object endpoint, MessageAddressingProperties requestMap) { |
| URI requestAction = requestMap.getAction(); |
| if (requestAction != null) { |
| return URI.create(requestAction.toString() + getFaultActionSuffix()); |
| } else { |
| return null; |
| } |
| } |
| |
| @Override |
| public void addConsumer(EndpointMappingKey key, MessageEndpoint endpoint) { |
| endpoints.put(key, endpoint); |
| } |
| |
| @Override |
| public void removeConsumer(Object key) { |
| endpoints.remove(key); |
| } |
| |
| /** |
| * Returns the suffix to add to request <code>Action</code>s for reply |
| * messages. |
| */ |
| public String getOutputActionSuffix() { |
| return outputActionSuffix; |
| } |
| |
| /** |
| * Sets the suffix to add to request <code>Action</code>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</code>s for reply fault |
| * messages. |
| */ |
| public String getFaultActionSuffix() { |
| return faultActionSuffix; |
| } |
| |
| /** |
| * Sets the suffix to add to request <code>Action</code>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; |
| } |
| |
| } |