/*
* Copyright 2001-2011 The Apache Software Foundation.
*
* 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.apache.juddi.v3.client.mapping.wsdl;
import org.apache.juddi.v3.client.mapping.Common2UDDI;
import java.net.MalformedURLException;
import java.net.URL;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javax.wsdl.Binding;
import javax.wsdl.Definition;
import javax.wsdl.Port;
import javax.wsdl.PortType;
import javax.wsdl.Service;
import javax.wsdl.WSDLException;
import javax.wsdl.extensions.http.HTTPAddress;
import javax.wsdl.extensions.http.HTTPBinding;
import javax.wsdl.extensions.soap.SOAPAddress;
import javax.wsdl.extensions.soap.SOAPBinding;
import javax.wsdl.extensions.soap12.SOAP12Address;
import javax.wsdl.extensions.soap12.SOAP12Binding;
import javax.xml.namespace.QName;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.juddi.api_v3.AccessPointType;
import org.apache.juddi.jaxb.PrintUDDI;
import org.apache.juddi.v3.client.config.Property;
import org.apache.juddi.v3.client.config.UDDIClerk;
import org.apache.juddi.v3.client.config.UDDIClient;
import org.apache.juddi.v3.client.config.UDDIKeyConvention;
import org.apache.juddi.v3.client.mapping.ServiceRegistrationResponse;
import org.apache.juddi.v3.client.mapping.URLLocalizer;
import org.apache.juddi.v3.client.mapping.wadl.WADL2UDDI;
import org.apache.juddi.v3.client.transport.TransportException;
import org.uddi.api_v3.AccessPoint;
import org.uddi.api_v3.BindingTemplate;
import org.uddi.api_v3.BindingTemplates;
import org.uddi.api_v3.BusinessService;
import org.uddi.api_v3.BusinessServices;
import org.uddi.api_v3.CategoryBag;
import org.uddi.api_v3.FindTModel;
import org.uddi.api_v3.InstanceDetails;
import org.uddi.api_v3.KeyedReference;
import org.uddi.api_v3.Name;
import org.uddi.api_v3.OverviewDoc;
import org.uddi.api_v3.OverviewURL;
import org.uddi.api_v3.TModel;
import org.uddi.api_v3.TModelDetail;
import org.uddi.api_v3.TModelInstanceDetails;
import org.uddi.api_v3.TModelInstanceInfo;
import org.w3c.dom.Element;
/**
* This class implements the OASIS <a
* href="http://www.oasis-open.org/committees/uddi-spec/doc/tn/uddi-spec-tc-tn-wsdl-v202-20040631.htm">
* 'Using WSDL in a UDDI Registry, Version 2.0.2'</a> technote. This class
* creates a detailed mapping of WSDL 1.1 artifacts to the UDDI V3 data model.
* <ul> <th>Section 2.4 in the technote</th> <li>2.4.1 wsdl:portType ->
* uddi:tModel - {@link #createWSDLPortTypeTModels(String, Map)}</li> <li>2.4.2
* wsdl:binding -> uddi:tModel -
* {@link #createWSDLBindingTModels(String, Map)}</li> <li>TODO: 2.4.3
* wsdl:service -> uddi:businessService</li> <li>TODO: 2.4.4 wsdl:port ->
* uddi:bindingTemplate</li> <li>TODO: 2.4.5 wsdl:port Address Extensions ->
* uddi:bindingTemplate</li> </ul>
*
* @see WADL2UDDI
* @see BPEL2UDDI
* @author Kurt T Stam
* @since 3.1.5
*/
public class WSDL2UDDI {
private static final Log log = LogFactory.getLog(WSDL2UDDI.class);
private String keyDomainURI;
private String businessKey;
private String lang;
private UDDIClerk clerk = null; private Properties properties = null;
private URLLocalizer urlLocalizer;
/**
* Required Properties are: businessName, for example: 'Apache'
* nodeName, for example: 'uddi.example.org_80' keyDomain, for example:
* juddi.apache.org
*
* Optional Properties are: lang: for example: 'nl'
*
* @param clerk - can be null if register/unregister methods are not
* used.
* @param urlLocalizer - A reference to an custom
* @param properties - required values keyDomain, businessKey, nodeName
* @throws ConfigurationException
*/
public WSDL2UDDI(UDDIClerk clerk, URLLocalizer urlLocalizer, Properties properties) throws ConfigurationException {
super(); if (properties == null) { throw new IllegalArgumentException("properties");
}
this.clerk = clerk; this.urlLocalizer = urlLocalizer; this.properties = properties; if (clerk != null) { if (!properties.containsKey("keyDomain")) { throw new ConfigurationException("Property keyDomain is a required property when using WSDL2UDDI.");
}
if (!properties.containsKey("businessKey") && !properties.containsKey("businessName")) { throw new ConfigurationException("Either property businessKey, or businessName, is a required property when using WSDL2UDDI.");
}
if (!properties.containsKey("nodeName")) { if (properties.containsKey("serverName") && properties.containsKey("serverPort")) { String nodeName = properties.getProperty("serverName") + "_" + properties.getProperty("serverPort"); properties.setProperty("nodeName", nodeName); } else { throw new ConfigurationException("Property nodeName is not defined and is a required property when using WSDL2UDDI.");
}
}
}
//Obtaining values from the properties
this.keyDomainURI = "uddi:" + properties.getProperty("keyDomain") + ":"; if (properties.contains(Property.BUSINESS_KEY)) { this.businessKey = properties.getProperty(Property.BUSINESS_KEY);
} else {
//using the BusinessKey Template, and the businessName to construct the key
this.businessKey = UDDIKeyConvention.getBusinessKey(properties);
}
this.lang = properties.getProperty(Property.LANG, Property.DEFAULT_LANG); }
public BusinessServices registerBusinessServices(Definition wsdlDefinition) throws RemoteException, ConfigurationException, TransportException, WSDLException, MalformedURLException {
BusinessServices businessServices = new BusinessServices(); for (Object serviceName : wsdlDefinition.getAllServices().keySet()) { QName serviceQName = (QName) serviceName; Service service = wsdlDefinition.getService(serviceQName); BusinessService businessService = null;
//add service
URL serviceUrl = null; if (service.getPorts() != null && service.getPorts().size() > 0) { for (Object portName : service.getPorts().keySet()) { businessService = registerBusinessService(serviceQName, (String) portName, serviceUrl, wsdlDefinition).getBusinessService(); }
}
if (businessService != null) { businessServices.getBusinessService().add(businessService);
}
} return businessServices;
}
@SuppressWarnings("unchecked")
public ServiceRegistrationResponse registerBusinessService(QName serviceQName, String portName, URL serviceUrl, Definition wsdlDefinition) throws RemoteException, ConfigurationException, TransportException, WSDLException, MalformedURLException {
String genericWSDLURL = wsdlDefinition.getDocumentBaseURI(); //TODO maybe point to repository version ServiceRegistrationResponse response = new ServiceRegistrationResponse(); String serviceKey = UDDIKeyConvention.getServiceKey(properties, serviceQName.getLocalPart()); BusinessService businessService = lookupService(serviceKey); if (businessService == null) { List<TModel> tModels = new ArrayList<TModel>();
// Create the PortType tModels
Map<QName, PortType> portTypes = (Map<QName, PortType>) wsdlDefinition.getAllPortTypes(); tModels.addAll(createWSDLPortTypeTModels(genericWSDLURL, portTypes));
// Create the Binding tModels
Map<QName, Binding> bindings = (Map<QName, Binding>) wsdlDefinition.getAllBindings(); tModels.addAll(createWSDLBindingTModels(genericWSDLURL, bindings));
// Register these tModels
for (TModel tModel : tModels) { clerk.register(tModel); }
// Service
businessService = createBusinessService(serviceQName, wsdlDefinition);
// Register this Service
clerk.register(businessService);
}
//Add the BindingTemplate to this Service
BindingTemplate binding = createWSDLBinding(serviceQName, portName, serviceUrl, wsdlDefinition);
// Register BindingTemplate
if (binding.getAccessPoint() != null) { clerk.register(binding); if (businessService.getBindingTemplates() == null) { businessService.setBindingTemplates(new BindingTemplates());
}
businessService.getBindingTemplates().getBindingTemplate().add(binding); response.setBindingKey(binding.getBindingKey());
}
response.setBusinessService(businessService); return response;
}
public String[] unRegisterBusinessServices(Definition wsdlDefinition) throws RemoteException, ConfigurationException, TransportException, MalformedURLException {
String[] businessServices = new String[wsdlDefinition.getAllServices().size()]; int i = 0; for (Object serviceName : wsdlDefinition.getAllServices().keySet()) { QName serviceQName = (QName) serviceName; Service service = wsdlDefinition.getService(serviceQName);
//unregister service
URL serviceUrl = null; if (service.getPorts() != null && service.getPorts().size() > 0) { for (Object portName : service.getPorts().keySet()) {
//construct the accessURL
serviceUrl = new URL(getBindingURL((Port) service.getPorts().get(portName))); businessServices[i++] = unRegisterBusinessService(serviceQName, (String) portName, serviceUrl); }
}
} return businessServices;
}
public String unRegisterBusinessService(QName serviceName, String portName, URL serviceUrl) throws RemoteException, ConfigurationException, TransportException {
String serviceKey = UDDIKeyConvention.getServiceKey(properties, serviceName.getLocalPart()); BusinessService service = lookupService(serviceKey); boolean isRemoveServiceIfNoTemplates = true; String bindingKey = UDDIKeyConvention.getBindingKey(properties, serviceName, portName, serviceUrl);
//check if this bindingKey is in the service's binding templates
for (BindingTemplate bindingTemplate : service.getBindingTemplates().getBindingTemplate()) { if (bindingKey.equals(bindingTemplate.getBindingKey())) { clerk.unRegisterBinding(bindingKey);
//if this is the last binding for this service, and
if (service.getBindingTemplates().getBindingTemplate().size() == 1 && isRemoveServiceIfNoTemplates) { clerk.unRegisterService(serviceKey); if (bindingTemplate.getTModelInstanceDetails() != null && bindingTemplate.getTModelInstanceDetails().getTModelInstanceInfo() != null) { for (TModelInstanceInfo tModelInstanceInfo : bindingTemplate.getTModelInstanceDetails().getTModelInstanceInfo()) { String tModelKey = tModelInstanceInfo.getTModelKey(); TModelDetail tModelDetail = clerk.getTModelDetail(tModelKey);
//delete all tModels assuming they are the portType and Binding tModels.
if (tModelDetail.getTModel() != null && tModelDetail.getTModel().size() > 0) { for (TModel tModel : tModelDetail.getTModel()) { if (!tModel.getTModelKey().startsWith("uddi:uddi.org:")) { clerk.unRegisterTModel(tModel.getTModelKey());
} else {
log.info("Skipping the removal of " + tModel.getTModelKey() + " because it starts with uddi.org");
}
}
}
}
}
}
}
} return serviceKey;
}
public String getKeyDomainURI() {
return keyDomainURI;
}
public void setKeyDomain(String keyDomainURI) {
this.keyDomainURI = keyDomainURI; }
public String getLang() {
return lang;
}
public void setLang(String lang) {
this.lang = lang; }
/**
* <h3>2.4.2 wsdl:binding -> uddi:tModel</h3>
*
* <p>
* A wsdl:binding MUST be modeled as a uddi:tModel. The minimum
* information that must be captured about a binding is its entity type,
* its local name, its namespace, the location of the WSDL document that
* defines the binding, the portType that it implements, its protocol,
* and, optionally, the transport information. Capturing the entity type
* enables users to search for tModels that represent binding artifacts.
* Capturing the local name, namespace, and WSDL location enables users
* to locate the definition of the specified binding artifact. The link
* to the portType enables users to search for bindings that implement a
* particular portType.</p>
*
* <p>
* A wsdl:binding corresponds to a WSDL service interface definition as
* defined by the mapping in the Version 1 Best Practice. To maintain
* compatibility with the previous mapping, the binding must also be
* characterized as type "wsdlSpec".</p>
*
* <p>
* The wsdl:binding information is captured as follows:</p>
*
* <p>
* The uddi:name element of the tModel MUST be the value of the name
* attribute of the wsdl:binding.</p>
*
* <p>
* The tModel MUST contain a categoryBag, and the categoryBag MUST
* contain at least the following keyedReference elements:</p> <ol> <li>
* A keyedReference with a tModelKey of the WSDL Entity Type category
* system and a keyValue of "binding".</li> <li> A keyedReference with a
* tModelKey of the WSDL portType Reference category system and a
* keyValue of the tModelKey that models the wsdl:portType to which the
* wsdl:binding relates.</li> <li> A keyedReference with a tModelKey of
* the UDDI Types category system and a keyValue of "wsdlSpec" for
* backward compatibility[1].</li> <li> One or two keyedReferences as
* required to capture the protocol and optionally the transport
* information refer to the next section.</li> </ol>
*
* <p>
* If the wsdl:binding has a targetNamespace then the categoryBag MUST
* also contain an additional keyedReference with a tModelKey of the XML
* Namespace category system and a keyValue of the target namespace of
* the wsdl:definitions element that contains the wsdl:binding. If the
* targetNamespace is absent from the binding, a categoryBag MUST NOT
* contain a keyedReference to the XML Namespace category system.</p>
*
* <p>
* The tModel MUST contain an overviewDoc with an overviewURL containing
* the location of the WSDL document that describes the
* wsdl:binding.</p>
*
* <h4>2.4.2.1 wsdl:binding Extensions</h4>
*
* <p>
* Information about the protocol and transport, if applicable,
* specified in an extension to the wsdl:binding is used to categorize
* the binding tModel as described in the following sections. This
* information is specified using two of the category systems defined in
* this Technical Note:</p> <ol> <li> Protocol Categorization</li> <li>
* Transport Categorization</li> </ol>
* <p>
* The valid values for the Protocol Categorization category system are
* tModelKeys of tModels that are categorized as protocol tModels.
* Similarly, the valid values for the Transport Categorization category
* system are tModelKeys of tModels that are categorized as transport
* tModels.</p>
* <p>
* The reason for having these two categorization schemes that take
* tModel keys as values is to allow other standard or proprietary
* protocols and transports to be defined and used in the same way as
* the standard SOAP and HTTP protocols and transport.</p>
*
* <h4>2.4.2.1.1 soap:binding</h4>
*
* <p>
* If the wsdl:binding contains a soap:binding extensibility element
* from the http://schemas.xmlsoap.org/wsdl/soap/ namespace then the
* categoryBag MUST include a keyedReference with a tModelKey of the
* Protocol Categorization category system and a keyValue of the
* tModelKey of the SOAP Protocol tModel.</p>
*
* <p>
* If the value of the transport attribute of the soap:binding element
* is http://schemas.xmlsoap.org/soap/http then the categoryBag MUST
* include a keyedReference with a tModelKey of the Transport
* Categorization category system and a keyValue of the tModelKey of the
* HTTP Transport tModel.</p>
*
* <p>
* If the value of the transport attribute is anything else, then the
* bindingTemplate MUST include an additional keyedReference with a
* tModelKey of the Transport Categorization category system and a
* keyValue of the tModelKey of an appropriate transport tModel.</p>
*
* <h4>2.4.2.1.2 http:binding</h4>
*
* <p>
* If the wsdl:binding contains an http:binding extensibility element
* from the http://schemas.xmlsoap.org/wsdl/http/ namespace then the
* categoryBag MUST include a keyedReference with a tModelKey of the
* Protocol Categorization category system and a keyValue of the
* tModelKey of the HTTP Protocol tModel.</p>
*
* <p>
* Note that this is a different tModel from the HTTP Transport tModel,
* and in this case there is no separate transport tModel, and therefore
* no keyedReference in the categoryBag from the Transport
* Categorization category system.</p>
*
* <h4>2.4.2.1.3 Other wsdl:binding Extensions</h4>
*
* <p>
* Other wsdl:binding extensibility elements are handled in a similar
* fashion. It is assumed that vendors who provide other bindings will
* provide the appropriate protocol and transport tModels.</p>
*
* Example Code
* <pre>
* URL url = new URL("http://graphical.weather.gov/xml/SOAP_server/ndfdXMLserver.php?wsdl");
* String domain = url.getHost();
* ReadWSDL rw = new ReadWSDL();
* Definition wsdlDefinition = rw.readWSDL(url);
* properties.put("keyDomain", domain);
* properties.put("businessName", domain);
* properties.put("serverName", url.getHost());
* properties.put("serverPort", url.getPort());
* wsdlURL = wsdlDefinition.getDocumentBaseURI();
* WSDL2UDDI wsdl2UDDI = new WSDL2UDDI(null, new URLLocalizerDefaultImpl(), properties);
* Map allBindings = wsdlDefinition.getAllBindings();
* Set<TModel> createWSDLBindingTModels = wsdl2UDDI.createWSDLBindingTModels(url.toString(), allBindings);
* </pre>
*
* @param wsdlURL
* @param bindings Map
* @return set of WSDL Binding tModels
* @throws WSDLException
*/
public Set<TModel> createWSDLBindingTModels(String wsdlURL, Map<QName, Binding> bindings) throws WSDLException {
Set<TModel> tModels = new HashSet<TModel>();
//Register a tModel for each portType
for (QName qName : bindings.keySet()) { String localpart = qName.getLocalPart(); String namespace = qName.getNamespaceURI();
// Build the tModel
TModel tModel = new TModel();
// Set the Key
tModel.setTModelKey(keyDomainURI + localpart);
// Set the Name
Name name = new Name(); name.setLang(lang); name.setValue(localpart); tModel.setName(name);
// Set the OverviewURL
OverviewURL overviewURL = new OverviewURL(); overviewURL.setUseType(AccessPointType.WSDL_DEPLOYMENT.toString()); overviewURL.setValue(wsdlURL); OverviewDoc overviewDoc = new OverviewDoc(); overviewDoc.setOverviewURL(overviewURL); tModel.getOverviewDoc().add(overviewDoc);
// Set the categoryBag
CategoryBag categoryBag = new CategoryBag(); if (namespace != null && !"".equals(namespace)) {
// A keyedReference with a tModelKey of the WSDL Entity Type category system and a keyValue of "binding".
KeyedReference namespaceReference = newKeyedReference(
"uddi:uddi.org:xml:namespace", "uddi-org:xml:namespace", namespace);
categoryBag.getKeyedReference().add(namespaceReference);
}
// A keyedReference with a tModelKey of the WSDL Entity Type category system and a keyValue of "binding".
KeyedReference typesReference = newKeyedReference(
"uddi:uddi.org:wsdl:types", "uddi-org:wsdl:types", "binding");
categoryBag.getKeyedReference().add(typesReference);
// A keyedReference with a tModelKey of the WSDL portType Reference category system and a keyValue
// of the tModelKey that models the wsdl:portType to which the wsdl:binding relates.
Binding binding = bindings.get(qName); String portTypeKey = keyDomainURI + binding.getPortType().getQName().getLocalPart(); KeyedReference namespaceReference = newKeyedReference(
"uddi:uddi.org:wsdl:porttypereference", "uddi-org:wsdl:portTypeReference",
portTypeKey);
categoryBag.getKeyedReference().add(namespaceReference);
// A keyedReference with a tModelKey of the UDDI Types category system and a keyValue of
// "wsdlSpec" for backward compatibility.
KeyedReference typesReferenceBackwardsCompatible = newKeyedReference(
"uddi:uddi.org:categorization:types", "uddi-org:types", "wsdlSpec");
categoryBag.getKeyedReference().add(typesReferenceBackwardsCompatible);
// One or two keyedReferences as required to capture the protocol
for (Object object : binding.getExtensibilityElements()) { SOAPBinding sb = null; SOAP12Binding sb12 = null; HTTPBinding hb = null;
try {
hb = (HTTPBinding) object; } catch (Exception x) { }
try {
sb = (SOAPBinding) object; } catch (Exception x) { }
try {
sb12 = (SOAP12Binding) object; } catch (Exception x) { } if (sb != null) {
// If the wsdl:binding contains a soap:binding extensibility element from the
// 'http://schemas.xmlsoap.org/wsdl/soap/' namespace then the categoryBag MUST
//include a keyedReference with a tModelKey of the Protocol Categorization
// category system and a keyValue of the tModelKey of the SOAP Protocol tModel.
SOAPBinding soapBinding = sb; KeyedReference soapProtocol = newKeyedReference(
"uddi:uddi.org:wsdl:categorization:protocol", "uddi-org:protocol:soap", "uddi:uddi.org:protocol:soap");
categoryBag.getKeyedReference().add(soapProtocol);
// If the value of the transport attribute of the soap:binding element
// is 'http://schemas.xmlsoap.org/soap/http' then the categoryBag MUST
// include a keyedReference with a tModelKey of the Transport Categorization
// category system and a keyValue of the tModelKey of the HTTP Transport tModel.
if ("http://schemas.xmlsoap.org/soap/http".equals(soapBinding.getTransportURI())) { KeyedReference httpTransport = newKeyedReference(
"uddi:uddi.org:wsdl:categorization:transport", "uddi-org:http", "uddi:uddi.org:transport:http");
categoryBag.getKeyedReference().add(httpTransport); } else if (soapBinding.getTransportURI() != null) {
// TODO If the value of the transport attribute is anything else,
// then the bindingTemplate MUST include an additional keyedReference with a tModelKey
// of the Transport Categorization category system and a keyValue of the tModelKey of
// an appropriate transport tModel.
log.warn("not implemented, binding transport is " + soapBinding.getTransportURI());
}
} else if (hb != null) {
// If the wsdl:binding contains an http:binding extensibility element from the
// http://schemas.xmlsoap.org/wsdl/http/ namespace then the categoryBag MUST
// include a keyedReference with a tModelKey of the Protocol Categorization
// category system and a keyValue of the tModelKey of the HTTP Protocol tModel.
KeyedReference soapProtocol = newKeyedReference(
"uddi:uddi.org:wsdl:categorization:protocol", "uddi-org:protocol:http", "uddi:uddi.org:protocol:http");
categoryBag.getKeyedReference().add(soapProtocol); } else if (sb12 != null) {
// If the wsdl:binding contains a soap:binding extensibility element from the
// 'http://schemas.xmlsoap.org/wsdl/soap/' namespace then the categoryBag MUST
//include a keyedReference with a tModelKey of the Protocol Categorization
// category system and a keyValue of the tModelKey of the SOAP Protocol tModel.
KeyedReference soapProtocol = newKeyedReference(
"uddi:uddi.org:wsdl:categorization:protocol", "uddi-org:protocol:soap", "uddi:uddi.org:protocol:soap");
categoryBag.getKeyedReference().add(soapProtocol);
// If the value of the transport attribute of the soap:binding element
// is 'http://schemas.xmlsoap.org/soap/http' then the categoryBag MUST
// include a keyedReference with a tModelKey of the Transport Categorization
// category system and a keyValue of the tModelKey of the HTTP Transport tModel.
if ("http://schemas.xmlsoap.org/soap/http".equals(sb12.getTransportURI())) { KeyedReference httpTransport = newKeyedReference(
"uddi:uddi.org:wsdl:categorization:transport", "uddi-org:http", "uddi:uddi.org:transport:http");
categoryBag.getKeyedReference().add(httpTransport); } else if (sb12.getTransportURI() != null) {
// TODO If the value of the transport attribute is anything else,
// then the bindingTemplate MUST include an additional keyedReference with a tModelKey
// of the Transport Categorization category system and a keyValue of the tModelKey of
// an appropriate transport tModel.
log.warn("not implemented, binding transport is " + sb12.getTransportURI());
}
} else { log.warn("Unrecongnized binding type: " + object.getClass().getCanonicalName() + ". Generated"
+ "binding tModel may be missing the required (according to WSDL2UDDI spec) "
+ "uddi:uddi.org:wsdl:categorization:protocol keyedReference.");
}
} tModel.setCategoryBag(categoryBag); tModels.add(tModel); } return tModels;
}
/**
* <h3>2.4.1 wsdl:portType -> uddi:tModel</h3>
*
* <p>
* A wsdl:portType MUST be modeled as a uddi:tModel.</p>
*
* <p>
* The minimum information that must be captured about a portType is its
* entity type, its local name, its namespace, and the location of the
* WSDL document that defines the portType. Capturing the entity type
* enables users to search for tModels that represent portType
* artifacts. Capturing the local name, namespace, and WSDL location
* enables users to locate the definition of the specified portType
* artifact.</p>
*
* <p>
* The wsdl:portType information is captured as follows:</p>
*
* <p>
* The uddi:name element of the tModel MUST be the value of the name
* attribute of the wsdl:portType.</p>
*
* <p>
* The tModel MUST contain a categoryBag, and the categoryBag MUST
* contain a keyedReference with a tModelKey of the WSDL Entity Type
* category system and a keyValue of "portType".</p>
*
* <p>
* If the wsdl:portType has a targetNamespace then the categoryBag MUST
* also contain an additional keyedReference with a tModelKey of the XML
* Namespace category system and a keyValue of the target namespace of
* the wsdl:definitions element that contains the wsdl:portType. If the
* targetNamespace is absent from the portType, a categoryBag MUST NOT
* contain a keyedReference to the XML Namespace category system.</p>
*
* <p>
* The tModel MUST contain an overviewDoc with an overviewURL containing
* the location of the WSDL document that describes the
* wsdl:portType.</p>
* Example Code
* <pre>
* URL url = new URL("http://graphical.weather.gov/xml/SOAP_server/ndfdXMLserver.php?wsdl");
* String domain = url.getHost();
* ReadWSDL rw = new ReadWSDL();
* Definition wsdlDefinition = rw.readWSDL(url);
* properties.put("keyDomain", domain);
* properties.put("businessName", domain);
* properties.put("serverName", url.getHost());
* properties.put("serverPort", url.getPort());
* wsdlURL = wsdlDefinition.getDocumentBaseURI();
* WSDL2UDDI wsdl2UDDI = new WSDL2UDDI(null, new URLLocalizerDefaultImpl(), properties);
* Map<QName, PortType> portTypes = (Map<QName, PortType>) wsdlDefinition.getAllPortTypes();
* Set<TModel> portTypeTModels = wsdl2UDDI.createWSDLPortTypeTModels(wsdlURL, portTypes);
* </pre>
*
* @param wsdlURL This is used to set the Overview URL
* @param portTypes Map
* @return set of WSDL PortType tModels
* @throws WSDLException
*/
public Set<TModel> createWSDLPortTypeTModels(String wsdlURL, Map<QName, PortType> portTypes) throws WSDLException {
Set<TModel> tModels = new HashSet<TModel>();
// Create a tModel for each portType
for (QName qName : portTypes.keySet()) {
// Build the tModel
TModel tModel = new TModel(); String localpart = qName.getLocalPart(); String namespace = qName.getNamespaceURI();
// Set the Key
tModel.setTModelKey(keyDomainURI + localpart);
// Set the Name. The uddi:name element of the tModel MUST be the value of
// the name attribute of the wsdl:portType.
Name name = new Name(); name.setLang(lang); name.setValue(localpart); tModel.setName(name);
// Set the OverviewURL. The tModel MUST contain an overviewDoc with an
// overviewURL containing the location of the WSDL document that
// describes the wsdl:portType.
OverviewURL overviewURL = new OverviewURL(); overviewURL.setUseType(AccessPointType.WSDL_DEPLOYMENT.toString()); overviewURL.setValue(wsdlURL); OverviewDoc overviewDoc = new OverviewDoc(); overviewDoc.setOverviewURL(overviewURL); tModel.getOverviewDoc().add(overviewDoc);
// Create the categoryBag, The tModel MUST contain a categoryBag
CategoryBag categoryBag = new CategoryBag();
// the categoryBag MUST contain a keyedReference with a tModelKey of the WSDL
// Entity Type category system and a keyValue of "portType".
KeyedReference typesReference = newKeyedReference(
"uddi:uddi.org:wsdl:types", "uddi-org:wsdl:types", "portType");
categoryBag.getKeyedReference().add(typesReference);
// If the wsdl:portType has a targetNamespace then the categoryBag MUST also contain an
// additional keyedReference with a tModelKey of the XML Namespace category system and a
// keyValue of the target namespace of the wsdl:definitions element that contains the
// wsdl:portType. If the targetNamespace is absent from the portType, a categoryBag
// MUST NOT contain a keyedReference to the XML Namespace category system.
if (namespace != null && !"".equals(namespace)) { KeyedReference namespaceReference = newKeyedReference(
"uddi:uddi.org:xml:namespace", "uddi-org:xml:namespace", namespace);
categoryBag.getKeyedReference().add(namespaceReference);
}
tModel.setCategoryBag(categoryBag); tModels.add(tModel); } return tModels;
}
protected static KeyedReference newKeyedReference(String tModelKey, String keyName, String value) {
KeyedReference typesReference = new KeyedReference(); typesReference.setTModelKey(tModelKey); typesReference.setKeyName(keyName); typesReference.setKeyValue(value); return typesReference;
}
/**
* Builds a finder to find the binding tModels for a portType.
*
* @param portType
* @param namespace
* @return tModel info
*/
public static FindTModel createFindBindingTModelForPortType(String portType, String namespace) {
FindTModel findTModel = new FindTModel(); CategoryBag categoryBag = new CategoryBag(); if (namespace != null && namespace.length() != 0) { KeyedReference namespaceReference = newKeyedReference(
"uddi:uddi.org:xml:namespace", "uddi-org:xml:namespace", namespace);
categoryBag.getKeyedReference().add(namespaceReference);
}
KeyedReference bindingReference = newKeyedReference(
"uddi:uddi.org:wsdl:types", "uddi-org:wsdl:types", "binding");
categoryBag.getKeyedReference().add(bindingReference); KeyedReference portTypeReference = newKeyedReference(
"uddi:uddi.org:wsdl:porttypereference", "uddi-org:wsdl:portTypeReference", portType);
categoryBag.getKeyedReference().add(portTypeReference); findTModel.setCategoryBag(categoryBag); if (log.isDebugEnabled()) { log.debug(new PrintUDDI<FindTModel>().print(findTModel));
}
return findTModel;
}
/**
* Builds a finder to find the portType tModels for a portType.
*
* @param portTypeName
* @param namespace
* @return tModel info
*/
public static FindTModel createFindPortTypeTModelForPortType(String portTypeName, String namespace) {
FindTModel findTModel = new FindTModel(); Name name = new Name(); name.setLang("en"); name.setValue(portTypeName); findTModel.setName(name); CategoryBag categoryBag = new CategoryBag(); if (namespace != null && namespace.length() != 0) { KeyedReference namespaceReference = newKeyedReference(
"uddi:uddi.org:xml:namespace", "uddi-org:xml:namespace", namespace);
categoryBag.getKeyedReference().add(namespaceReference);
}
KeyedReference bindingReference = newKeyedReference(
"uddi:uddi.org:wsdl:types", "uddi-org:wsdl:types", "portType");
categoryBag.getKeyedReference().add(bindingReference); findTModel.setCategoryBag(categoryBag); if (log.isDebugEnabled()) { log.debug(new PrintUDDI<FindTModel>().print(findTModel));
}
return findTModel;
}
/**
* Perform a lookup by serviceKey, and will return null if not found.
*
* @param serviceKey
* @return business service
* @throws RemoteException
* @throws ConfigurationException
* @throws TransportException
*/
private BusinessService lookupService(String serviceKey) throws RemoteException, ConfigurationException, TransportException {
//Checking if this serviceKey already exist
BusinessService service = clerk.getServiceDetail(serviceKey); return service;
}
/**
* Creates a business service based off of a WSDL definition<Br>No
* changes are made to the UDDI endpoints using this method
* <br>
* Example Code:
* <pre>
* URL url = new URL("http://graphical.weather.gov/xml/SOAP_server/ndfdXMLserver.php?wsdl");
* String domain = url.getHost();
* ReadWSDL rw = new ReadWSDL();
* Definition wsdlDefinition = rw.readWSDL(url);
* properties.put("keyDomain", domain);
* properties.put("businessName", domain);
* properties.put("serverName", url.getHost());
* properties.put("serverPort", url.getPort());
* wsdlURL = wsdlDefinition.getDocumentBaseURI();
* WSDL2UDDI wsdl2UDDI = new WSDL2UDDI(null, new URLLocalizerDefaultImpl(), properties);
* BusinessServices businessServices = wsdl2UDDI.createBusinessServices(wsdlDefinition);
* </pre>
*
* @param wsdlDefinition must not be null
* @return a business service
* @throws MalformedURLException
* @throws IllegalArgumentException if the wsdlDefinition is null
*/
public BusinessServices createBusinessServices(Definition wsdlDefinition) throws MalformedURLException {
if (wsdlDefinition == null) { throw new IllegalArgumentException();
}
BusinessServices businessServices = new BusinessServices(); for (Object serviceName : wsdlDefinition.getAllServices().keySet()) { QName serviceQName = (QName) serviceName; Service service = wsdlDefinition.getService(serviceQName); BusinessService businessService = createBusinessService(serviceQName, wsdlDefinition);
//service.getExtensibilityElements().
//add the bindingTemplates
URL serviceUrl = null; if (service.getPorts() != null && service.getPorts().size() > 0) { businessService.setBindingTemplates(new BindingTemplates()); for (Object portName : service.getPorts().keySet()) { BindingTemplate bindingTemplate = createWSDLBinding(serviceQName, (String) portName, serviceUrl, wsdlDefinition); businessService.getBindingTemplates().getBindingTemplate().add(bindingTemplate); }
}
businessServices.getBusinessService().add(businessService); } return businessServices;
}
/**
* Creates a UDDI Business Service.
*
* @param serviceQName
* @param wsdlDefinition
* @return a business service
*/
protected BusinessService createBusinessService(QName serviceQName, Definition wsdlDefinition) {
log.debug("Constructing Service UDDI Information for " + serviceQName); BusinessService service = new BusinessService();
// BusinessKey
service.setBusinessKey(businessKey);
// ServiceKey
service.setServiceKey(UDDIKeyConvention.getServiceKey(properties, serviceQName.getLocalPart()));
// Description
String serviceDescription = properties.getProperty(Property.SERVICE_DESCRIPTION, Property.DEFAULT_SERVICE_DESCRIPTION);
// Override with the service description from the WSDL if present
if (wsdlDefinition.getService(serviceQName) != null) { Element docElement = wsdlDefinition.getService(serviceQName).getDocumentationElement(); if (docElement != null && docElement.getTextContent() != null) { serviceDescription = docElement.getTextContent();
}
}
service.getDescription().addAll(Common2UDDI.mapDescription(serviceDescription, lang));
// Service name
Name sName = new Name(); sName.setLang(lang); sName.setValue(serviceQName.getLocalPart()); service.getName().add(sName); CategoryBag categoryBag = new CategoryBag(); String namespace = serviceQName.getNamespaceURI(); if (namespace != null && namespace.length() != 0) { KeyedReference namespaceReference = newKeyedReference(
"uddi:uddi.org:xml:namespace", "uddi-org:xml:namespace", namespace);
categoryBag.getKeyedReference().add(namespaceReference);
}
KeyedReference serviceReference = newKeyedReference(
"uddi:uddi.org:wsdl:types", "uddi-org:wsdl:types", "service");
categoryBag.getKeyedReference().add(serviceReference); KeyedReference localNameReference = newKeyedReference( "uddi:uddi.org:xml:localname", "uddi-org:xml:localName", serviceQName.getLocalPart()); categoryBag.getKeyedReference().add(localNameReference); service.setCategoryBag(categoryBag); return service;
}
protected BindingTemplate createWSDLBinding(QName serviceQName, String portName, URL serviceUrl, Definition wsdlDefinition) throws MalformedURLException {
BindingTemplate bindingTemplate = new BindingTemplate();
// Set BusinessService Key
bindingTemplate.setServiceKey(UDDIKeyConvention.getServiceKey(properties, serviceQName.getLocalPart())); if (serviceUrl != null) {
// Set AccessPoint
AccessPoint accessPoint = new AccessPoint(); accessPoint.setUseType(AccessPointType.END_POINT.toString()); accessPoint.setValue(urlLocalizer.rewrite(serviceUrl)); bindingTemplate.setAccessPoint(accessPoint);
// Set Binding Key
String bindingKey = UDDIKeyConvention.getBindingKey(properties, serviceQName, portName, serviceUrl); bindingTemplate.setBindingKey(bindingKey);
}
Service service = wsdlDefinition.getService(serviceQName); if (service != null) { TModelInstanceDetails tModelInstanceDetails = new TModelInstanceDetails(); Port port = service.getPort(portName); if (port != null) { if (serviceUrl == null) { for (Object element : port.getExtensibilityElements()) { String location = null; if (element instanceof SOAPAddress) { SOAPAddress address = (SOAPAddress) element; location = urlLocalizer.rewrite(new URL(address.getLocationURI())); } else if (element instanceof HTTPAddress) { HTTPAddress address = (HTTPAddress) element; urlLocalizer.rewrite(new URL(location = address.getLocationURI())); } else if (element instanceof SOAP12Address) { SOAP12Address address = (SOAP12Address) element; location = urlLocalizer.rewrite(new URL(address.getLocationURI()));
}
if (location != null) {
try {
URL locationURI = new URL(location); AccessPoint accessPoint = new AccessPoint(); accessPoint.setUseType(AccessPointType.END_POINT.toString()); accessPoint.setValue(urlLocalizer.rewrite(locationURI)); bindingTemplate.setAccessPoint(accessPoint);
// Set Binding Key
String bindingKey = UDDIKeyConvention.getBindingKey(properties, serviceQName, portName, locationURI); bindingTemplate.setBindingKey(bindingKey); break; } catch (MalformedURLException e) { log.error(e.getMessage());
}
}
}
}
Binding binding = port.getBinding();
// Set the Binding Description
String bindingDescription = properties.getProperty(Property.BINDING_DESCRIPTION, Property.DEFAULT_BINDING_DESCRIPTION);
// Override with the service description from the WSDL if present
Element docElement = binding.getDocumentationElement(); if (docElement != null && docElement.getTextContent() != null) { bindingDescription = docElement.getTextContent();
}
bindingTemplate.getDescription().addAll(Common2UDDI.mapDescription(bindingDescription, lang));
// reference wsdl:binding tModel
TModelInstanceInfo tModelInstanceInfoBinding = new TModelInstanceInfo(); tModelInstanceInfoBinding.setTModelKey(keyDomainURI + binding.getQName().getLocalPart()); InstanceDetails instanceDetails = new InstanceDetails(); instanceDetails.setInstanceParms(portName); tModelInstanceInfoBinding.setInstanceDetails(instanceDetails); tModelInstanceInfoBinding.getDescription().addAll(Common2UDDI.mapDescription("The wsdl:binding that this wsdl:port implements. " + bindingDescription
+ " The instanceParms specifies the port local name.", lang));
tModelInstanceDetails.getTModelInstanceInfo().add(tModelInstanceInfoBinding);
// reference wsdl:portType tModel
PortType portType = binding.getPortType(); TModelInstanceInfo tModelInstanceInfoPortType = new TModelInstanceInfo(); tModelInstanceInfoPortType.setTModelKey(keyDomainURI + portType.getQName().getLocalPart()); String portTypeDescription = ""; docElement = portType.getDocumentationElement(); if (docElement != null && docElement.getTextContent() != null) { portTypeDescription = docElement.getTextContent();
}
tModelInstanceInfoPortType.getDescription().addAll(Common2UDDI.mapDescription("The wsdl:portType that this wsdl:port implements." + portTypeDescription, lang)); tModelInstanceDetails.getTModelInstanceInfo().add(tModelInstanceInfoPortType); bindingTemplate.setTModelInstanceDetails(tModelInstanceDetails); } else { log.error("Could not find Port with portName: " + portName);
}
} else { log.error("Could not find Service with serviceName: " + serviceQName.getLocalPart());
}
return UDDIClient.addSOAPtModels(bindingTemplate);
}
/**
* Obtains the accessUrl from the WSDL
*
* @param port
* @return a string url
* @throws MalformedURLException
*/
private String getBindingURL(Port port) throws MalformedURLException {
String bindingUrl = null; for (Object element : port.getExtensibilityElements()) { if (element instanceof SOAPAddress) { SOAPAddress address = (SOAPAddress) element; URL locationURI = new URL(address.getLocationURI()); if (locationURI != null) { bindingUrl = urlLocalizer.rewrite(locationURI); break;
}
}
} return bindingUrl;
}
}