/** * Copyright 2015 Nortal 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 com.nortal.jroad.wsdl; import java.util.Properties; import javax.annotation.Resource; import javax.wsdl.Definition; import javax.wsdl.Message; import javax.wsdl.Part; import javax.wsdl.WSDLException; import javax.wsdl.extensions.schema.Schema; import javax.xml.namespace.QName; import javax.xml.transform.Source; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.StringUtils; import org.springframework.ws.wsdl.wsdl11.ProviderBasedWsdl4jDefinition; import org.springframework.ws.wsdl.wsdl11.Wsdl11Definition; import org.springframework.ws.wsdl.wsdl11.provider.InliningXsdSchemaTypesProvider; import org.springframework.ws.wsdl.wsdl11.provider.SuffixBasedMessagesProvider; import org.springframework.xml.xsd.XsdSchema; import org.springframework.xml.xsd.XsdSchemaCollection; import org.w3c.dom.Element; import com.nortal.jroad.mapping.XTeeEndpointMapping; import com.nortal.jroad.model.XTeeHeader; /** * Generates WSDL for X-Road services from a schema, much like Spring's WSDL generator it delegates to * <code>InliningXsdSchemaTypesProvider</code>, <code>DefaultMessagesProvider</code>, * <code>SuffixBasedPortTypesProvider</code>, <code>ProviderBasedWsdl4jDefinition</code> and {@link XTeeSoapProvider} * underneath. * * @author Dmitri Danilkin * @author Lauri Lättemäe (lauri.lattemae@nortal.com) - protocol 4.0 */ public class XTeeWsdlDefinition implements Wsdl11Definition, InitializingBean { private final InliningXsdSchemaTypesProvider typesProvider = new InliningXsdSchemaTypesProvider(); private final SuffixBasedMessagesProvider messagesProvider = new XTeeMessagesProvider(); private final XTeePortTypesProvider portTypesProvider = new XTeePortTypesProvider(); private final XTeeSoapProvider soapProvider = new XTeeSoapProvider(); private final ProviderBasedWsdl4jDefinition delegate = new ProviderBasedWsdl4jDefinition(); private String serviceName; @Resource(name = "xteeDatabase") private String xRoadDatabase; private String xRoadTargetNamespace; @Resource private XTeeEndpointMapping xRoadEndpointMapping; public static final String XROAD_HEADER = "requestheader"; public static final String XROAD_NAMESPACE = "http://x-road.eu/xsd/xroad.xsd"; public static final String XROAD_PREFIX = "xrd"; public static final String XROAD_IDEN_NAMESPACE = "http://x-road.eu/xsd/identifiers"; public XTeeWsdlDefinition() { delegate.setTypesProvider(typesProvider); delegate.setMessagesProvider(messagesProvider); delegate.setPortTypesProvider(portTypesProvider); delegate.setBindingsProvider(soapProvider); delegate.setServicesProvider(soapProvider); } /** * Sets the single XSD schema to inline. Either this property, or {@link #setSchemaCollection(XsdSchemaCollection) * schemaCollection} must be set. */ public void setSchema(final XsdSchema schema) { typesProvider.setSchema(schema); } /** * Sets the XSD schema collection to inline. Either this property, or {@link #setSchema(XsdSchema) schema} must be * set. */ public void setSchemaCollection(XsdSchemaCollection schemaCollection) { typesProvider.setSchemaCollection(schemaCollection); } /** Sets the port type name used for this definition. Required. */ public void setPortTypeName(String portTypeName) { portTypesProvider.setPortTypeName(portTypeName); } /** Sets the suffix used to detect request elements in the schema. */ private void setRequestSuffix(String requestSuffix) { portTypesProvider.setRequestSuffix(requestSuffix); messagesProvider.setRequestSuffix(requestSuffix); } /** Sets the suffix used to detect response elements in the schema. */ private void setResponseSuffix(String responseSuffix) { portTypesProvider.setResponseSuffix(responseSuffix); messagesProvider.setResponseSuffix(responseSuffix); } /** Sets the suffix used to detect fault elements in the schema. */ public void setFaultSuffix(String faultSuffix) { portTypesProvider.setFaultSuffix(faultSuffix); messagesProvider.setFaultSuffix(faultSuffix); } public void setUse(String use) { soapProvider.setUse(use); } /** * Sets the SOAP Actions for this binding. Keys are {@link javax.wsdl.BindingOperation#getName() binding operation * names}; values are {@link javax.wsdl.extensions.soap.SOAPOperation#getSoapActionURI() SOAP Action URIs}. * * @param soapActions the soap */ public void setSoapActions(Properties soapActions) { soapProvider.setSoapActions(soapActions); } /** Sets the service name. */ public void setServiceName(String serviceName) { soapProvider.setServiceName(serviceName); this.serviceName = serviceName; } public void afterPropertiesSet() throws Exception { soapProvider.setLocationUri("http://SECURITY_SERVER/cgi-bin/consumer_proxy"); soapProvider.setXRoadDatabase(xRoadDatabase); soapProvider.setXRoadEndpointMapping(xRoadEndpointMapping); portTypesProvider.setXRoadEndpointMapping(xRoadEndpointMapping); setRequestSuffix(SuffixBasedMessagesProvider.DEFAULT_REQUEST_SUFFIX); setResponseSuffix(SuffixBasedMessagesProvider.DEFAULT_RESPONSE_SUFFIX); String targetNamespace = StringUtils.hasText(xRoadTargetNamespace) ? xRoadTargetNamespace : "http://" + xRoadDatabase + ".x-road.eu"; delegate.setTargetNamespace(targetNamespace); if (!StringUtils.hasText(delegate.getTargetNamespace()) && typesProvider.getSchemaCollection() != null && typesProvider.getSchemaCollection().getXsdSchemas().length > 0) { XsdSchema schema = typesProvider.getSchemaCollection().getXsdSchemas()[0]; delegate.setTargetNamespace(schema.getTargetNamespace()); } if (!StringUtils.hasText(serviceName) && StringUtils.hasText(portTypesProvider.getPortTypeName())) { soapProvider.setServiceName(portTypesProvider.getPortTypeName() + "Service"); } delegate.afterPropertiesSet(); addXRoadExtensions(delegate.getDefinition()); } public Source getSource() { return delegate.getSource(); } public Definition getDefinition() { return delegate.getDefinition(); } private void addXRoadExtensions(Definition definition) throws WSDLException { definition.addNamespace(XROAD_PREFIX, XROAD_NAMESPACE); Message message = definition.createMessage(); message.setQName(new QName(definition.getTargetNamespace(), XROAD_HEADER)); addXroadHeaderPart(definition, message, XTeeHeader.CLIENT); addXroadHeaderPart(definition, message, XTeeHeader.SERVICE); addXroadHeaderPart(definition, message, XTeeHeader.ID); addXroadHeaderPart(definition, message, XTeeHeader.USER_ID); addXroadHeaderPart(definition, message, XTeeHeader.PROTOCOL_VERSION); message.setUndefined(false); definition.addMessage(message); // Add XRoad schema import to the first schema for (Object ex : definition.getTypes().getExtensibilityElements()) { if (ex instanceof Schema) { Schema schema = (Schema) ex; Element xRoadImport = schema.getElement().getOwnerDocument().createElement(schema.getElement().getPrefix() == null ? "import" : schema.getElement().getPrefix() + ":import"); xRoadImport.setAttribute("namespace", XROAD_NAMESPACE); xRoadImport.setAttribute("schemaLocation", XROAD_NAMESPACE); schema.getElement().insertBefore(xRoadImport, schema.getElement().getFirstChild()); break; } } } private void addXroadHeaderPart(Definition definition, Message message, QName partName) { Part part = definition.createPart(); part.setElementName(partName); part.setName(partName.getLocalPart()); message.addPart(part); } public void setxRoadTargetNamespace(String xRoadTargetNamespace) { this.xRoadTargetNamespace = xRoadTargetNamespace; } }