001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.camel.component.spring.ws; 018 019 import java.net.URI; 020 import java.net.URISyntaxException; 021 import java.util.Map; 022 import javax.xml.transform.TransformerFactory; 023 024 import org.apache.camel.CamelContext; 025 import org.apache.camel.Endpoint; 026 import org.apache.camel.RuntimeCamelException; 027 import org.apache.camel.component.spring.ws.bean.CamelEndpointDispatcher; 028 import org.apache.camel.component.spring.ws.bean.CamelEndpointMapping; 029 import org.apache.camel.component.spring.ws.type.EndpointMappingKey; 030 import org.apache.camel.component.spring.ws.type.EndpointMappingType; 031 import org.apache.camel.converter.jaxp.XmlConverter; 032 import org.apache.camel.impl.DefaultComponent; 033 import org.apache.camel.util.CamelContextHelper; 034 import org.apache.camel.util.UnsafeUriCharactersEncoder; 035 import org.apache.commons.logging.Log; 036 import org.apache.commons.logging.LogFactory; 037 import org.springframework.ws.WebServiceMessageFactory; 038 import org.springframework.ws.client.core.WebServiceTemplate; 039 import org.springframework.ws.transport.WebServiceMessageSender; 040 import org.springframework.xml.xpath.XPathExpression; 041 import org.springframework.xml.xpath.XPathExpressionFactory; 042 043 /** 044 * Apache Camel component for working with Spring Web Services (a.k.a Spring-WS). 045 */ 046 public class SpringWebserviceComponent extends DefaultComponent { 047 private static final Log LOG = LogFactory.getLog(SpringWebserviceComponent.class); 048 049 public SpringWebserviceComponent() { 050 super(); 051 } 052 053 public SpringWebserviceComponent(CamelContext context) { 054 super(context); 055 } 056 057 @Override 058 protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception { 059 SpringWebserviceConfiguration configuration = new SpringWebserviceConfiguration(); 060 addConsumerConfiguration(remaining, parameters, configuration); 061 addProducerConfiguration(remaining, parameters, configuration); 062 addXmlConverterToConfiguration(parameters, configuration); 063 setProperties(configuration, parameters); 064 return new SpringWebserviceEndpoint(this, configuration); 065 } 066 067 private void addConsumerConfiguration(String remaining, Map<String, Object> parameters, 068 SpringWebserviceConfiguration configuration) { 069 EndpointMappingType type = EndpointMappingType.getTypeFromUriPrefix(remaining); 070 if (type != null) { 071 LOG.debug("Building Spring Web Services consumer of type " + type); 072 String lookupKey = getLookupKey(remaining, type); 073 if (EndpointMappingType.BEANNAME.equals(type)) { 074 addEndpointDispatcherToConfiguration(configuration, lookupKey); 075 } else { 076 addEndpointMappingToConfiguration(parameters, configuration); 077 } 078 if (EndpointMappingType.XPATHRESULT.equals(type)) { 079 XPathExpression expression = getXPathExpressionFromParameters(parameters); 080 configuration.setEndpointMappingKey(new EndpointMappingKey(type, lookupKey, expression)); 081 } else { 082 configuration.setEndpointMappingKey(new EndpointMappingKey(type, lookupKey, null)); 083 } 084 } 085 } 086 087 private void addProducerConfiguration(String remaining, Map<String, Object> parameters, 088 SpringWebserviceConfiguration configuration) throws URISyntaxException { 089 if (configuration.getEndpointMapping() == null && configuration.getEndpointDispatcher() == null) { 090 LOG.debug("Building Spring Web Services producer"); 091 URI webServiceEndpointUri = new URI(UnsafeUriCharactersEncoder.encode(remaining)); 092 093 // Obtain a WebServiceTemplate from the registry when specified by 094 // an option on the component, else create a new template with 095 // Spring-WS defaults 096 WebServiceTemplate webServiceTemplate = resolveAndRemoveReferenceParameter(parameters, 097 "webServiceTemplate", WebServiceTemplate.class, new WebServiceTemplate()); 098 WebServiceMessageSender messageSender = resolveAndRemoveReferenceParameter(parameters, 099 "messageSender", WebServiceMessageSender.class, null); 100 WebServiceMessageFactory messageFactory = resolveAndRemoveReferenceParameter(parameters, 101 "messageFactory", WebServiceMessageFactory.class, null); 102 103 if (webServiceTemplate.getDefaultUri() == null) { 104 webServiceTemplate.setDefaultUri(webServiceEndpointUri.toString()); 105 } 106 if (messageSender != null) { 107 webServiceTemplate.setMessageSender(messageSender); 108 } 109 if (messageFactory != null) { 110 webServiceTemplate.setMessageFactory(messageFactory); 111 } 112 configuration.setWebServiceTemplate(webServiceTemplate); 113 } 114 } 115 116 private String getLookupKey(String remaining, EndpointMappingType type) { 117 String lookupKey = remaining.substring(type.getPrefix().length()); 118 return lookupKey.startsWith("//") ? lookupKey.substring(2) : lookupKey; 119 } 120 121 private XPathExpression getXPathExpressionFromParameters(Map<String, Object> parameters) { 122 String xpathExpression = getAndRemoveParameter(parameters, "expression", String.class); 123 if (xpathExpression == null) { 124 throw new RuntimeCamelException("Expression parameter is required when using XPath endpoint mapping"); 125 } 126 XPathExpression expression = XPathExpressionFactory.createXPathExpression(xpathExpression); 127 return expression; 128 } 129 130 private void addEndpointMappingToConfiguration(Map<String, Object> parameters, 131 SpringWebserviceConfiguration configuration) { 132 // Obtain generic CamelEndpointMapping from registry 133 CamelEndpointMapping endpointMapping = resolveAndRemoveReferenceParameter(parameters, "endpointMapping", CamelEndpointMapping.class, null); 134 if (endpointMapping == null && configuration.getEndpointDispatcher() == null) { 135 throw new IllegalArgumentException("No CamelEndpointMapping found in Spring ApplicationContext." 136 + " This bean is required for Spring-WS consumer support (unless the 'spring-ws:beanname:' URI scheme is used)"); 137 } 138 configuration.setEndpointMapping(endpointMapping); 139 } 140 141 private void addEndpointDispatcherToConfiguration(SpringWebserviceConfiguration configuration, String lookupKey) { 142 // Obtain CamelEndpointDispatcher with the given name from registry 143 CamelEndpointDispatcher endpoint = CamelContextHelper.mandatoryLookup(getCamelContext(), lookupKey, CamelEndpointDispatcher.class); 144 configuration.setEndpointDispatcher(endpoint); 145 } 146 147 private void addXmlConverterToConfiguration(Map<String, Object> parameters, SpringWebserviceConfiguration configuration) { 148 XmlConverter xmlConverter = new XmlConverter(); 149 TransformerFactory transformerFactory = resolveAndRemoveReferenceParameter(parameters, "transformerFactory", TransformerFactory.class, null); 150 if (transformerFactory != null) { 151 xmlConverter.setTransformerFactory(transformerFactory); 152 } 153 configuration.setXmlConverter(xmlConverter); 154 } 155 }