This project has retired. For details please refer to its Attic page.
WSDL2UDDI xref
View Javadoc
1   /*
2    * Copyright 2001-2011 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   */
17  package org.apache.juddi.v3.client.mapping.wsdl;
18  
19  import org.apache.juddi.v3.client.mapping.Common2UDDI;
20  import java.net.MalformedURLException;
21  import java.net.URL;
22  import java.rmi.RemoteException;
23  import java.util.ArrayList;
24  import java.util.HashSet;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.Properties;
28  import java.util.Set;
29  
30  import javax.wsdl.Binding;
31  import javax.wsdl.Definition;
32  import javax.wsdl.Port;
33  import javax.wsdl.PortType;
34  import javax.wsdl.Service;
35  import javax.wsdl.WSDLException;
36  import javax.wsdl.extensions.http.HTTPAddress;
37  import javax.wsdl.extensions.http.HTTPBinding;
38  import javax.wsdl.extensions.soap.SOAPAddress;
39  import javax.wsdl.extensions.soap.SOAPBinding;
40  import javax.wsdl.extensions.soap12.SOAP12Address;
41  import javax.wsdl.extensions.soap12.SOAP12Binding;
42  import javax.xml.namespace.QName;
43  
44  import org.apache.commons.configuration.ConfigurationException;
45  import org.apache.commons.logging.Log;
46  import org.apache.commons.logging.LogFactory;
47  import org.apache.juddi.api_v3.AccessPointType;
48  import org.apache.juddi.jaxb.PrintUDDI;
49  import org.apache.juddi.v3.client.config.Property;
50  import org.apache.juddi.v3.client.config.UDDIClerk;
51  import org.apache.juddi.v3.client.config.UDDIClient;
52  import org.apache.juddi.v3.client.config.UDDIKeyConvention;
53  import org.apache.juddi.v3.client.mapping.ServiceRegistrationResponse;
54  import org.apache.juddi.v3.client.mapping.URLLocalizer;
55  import org.apache.juddi.v3.client.mapping.wadl.WADL2UDDI;
56  import org.apache.juddi.v3.client.transport.TransportException;
57  import org.uddi.api_v3.AccessPoint;
58  import org.uddi.api_v3.BindingTemplate;
59  import org.uddi.api_v3.BindingTemplates;
60  import org.uddi.api_v3.BusinessService;
61  import org.uddi.api_v3.BusinessServices;
62  import org.uddi.api_v3.CategoryBag;
63  import org.uddi.api_v3.FindTModel;
64  import org.uddi.api_v3.InstanceDetails;
65  import org.uddi.api_v3.KeyedReference;
66  import org.uddi.api_v3.Name;
67  import org.uddi.api_v3.OverviewDoc;
68  import org.uddi.api_v3.OverviewURL;
69  import org.uddi.api_v3.TModel;
70  import org.uddi.api_v3.TModelDetail;
71  import org.uddi.api_v3.TModelInstanceDetails;
72  import org.uddi.api_v3.TModelInstanceInfo;
73  import org.w3c.dom.Element;
74  
75  /**
76   * This class implements the OASIS <a
77   * href="http://www.oasis-open.org/committees/uddi-spec/doc/tn/uddi-spec-tc-tn-wsdl-v202-20040631.htm">
78   * 'Using WSDL in a UDDI Registry, Version 2.0.2'</a> technote. This class
79   * creates a detailed mapping of WSDL 1.1 artifacts to the UDDI V3 data model.
80   * <ul> <th>Section 2.4 in the technote</th> <li>2.4.1 wsdl:portType ->
81   * uddi:tModel - {@link #createWSDLPortTypeTModels(String, Map)}</li> <li>2.4.2
82   * wsdl:binding -> uddi:tModel -
83   * {@link #createWSDLBindingTModels(String, Map)}</li> <li>TODO: 2.4.3
84   * wsdl:service -> uddi:businessService</li> <li>TODO: 2.4.4 wsdl:port ->
85   * uddi:bindingTemplate</li> <li>TODO: 2.4.5 wsdl:port Address Extensions ->
86   * uddi:bindingTemplate</li> </ul>
87   *
88   * @see WADL2UDDI
89   * @see BPEL2UDDI
90   * @author Kurt T Stam
91   * @since 3.1.5
92   */
93  public class WSDL2UDDI {
94  
95          private static final Log log = LogFactory.getLog(WSDL2UDDI.class);
96          private String keyDomainURI;
97          private String businessKey;
98          private String lang;
99          private UDDIClerk clerk = null;
100         private Properties properties = null;
101         private URLLocalizer urlLocalizer;
102 
103         /**
104          * Required Properties are: businessName, for example: 'Apache'
105          * nodeName, for example: 'uddi.example.org_80' keyDomain, for example:
106          * juddi.apache.org
107          *
108          * Optional Properties are: lang: for example: 'nl'
109          *
110          * @param clerk - can be null if register/unregister methods are not
111          * used.
112          * @param urlLocalizer - A reference to an custom
113          * @param properties - required values keyDomain, businessKey, nodeName
114          * @throws ConfigurationException
115          */
116         public WSDL2UDDI(UDDIClerk clerk, URLLocalizer urlLocalizer, Properties properties) throws ConfigurationException {
117                 super();
118                 if (properties == null) {
119                         throw new IllegalArgumentException("properties");
120                 }
121                 this.clerk = clerk;
122                 this.urlLocalizer = urlLocalizer;
123                 this.properties = properties;
124 
125                 if (clerk != null) {
126                         if (!properties.containsKey("keyDomain")) {
127                                 throw new ConfigurationException("Property keyDomain is a required property when using WSDL2UDDI.");
128                         }
129                         if (!properties.containsKey("businessKey") && !properties.containsKey("businessName")) {
130                                 throw new ConfigurationException("Either property businessKey, or businessName, is a required property when using WSDL2UDDI.");
131                         }
132                         if (!properties.containsKey("nodeName")) {
133                                 if (properties.containsKey("serverName") && properties.containsKey("serverPort")) {
134                                         String nodeName = properties.getProperty("serverName") + "_" + properties.getProperty("serverPort");
135                                         properties.setProperty("nodeName", nodeName);
136                                 } else {
137                                         throw new ConfigurationException("Property nodeName is not defined and is a required property when using WSDL2UDDI.");
138                                 }
139                         }
140                 }
141 
142                 //Obtaining values from the properties
143                 this.keyDomainURI = "uddi:" + properties.getProperty("keyDomain") + ":";
144                 if (properties.contains(Property.BUSINESS_KEY)) {
145                         this.businessKey = properties.getProperty(Property.BUSINESS_KEY);
146                 } else {
147                         //using the BusinessKey Template, and the businessName to construct the key 
148                         this.businessKey = UDDIKeyConvention.getBusinessKey(properties);
149                 }
150                 this.lang = properties.getProperty(Property.LANG, Property.DEFAULT_LANG);
151         }
152 
153         public BusinessServices registerBusinessServices(Definition wsdlDefinition) throws RemoteException, ConfigurationException, TransportException, WSDLException, MalformedURLException {
154 
155                 BusinessServices businessServices = new BusinessServices();
156 
157                 for (Object serviceName : wsdlDefinition.getAllServices().keySet()) {
158                         QName serviceQName = (QName) serviceName;
159                         Service service = wsdlDefinition.getService(serviceQName);
160                         BusinessService businessService = null;
161                         //add service
162                         URL serviceUrl = null;
163                         if (service.getPorts() != null && service.getPorts().size() > 0) {
164                                 for (Object portName : service.getPorts().keySet()) {
165                                         businessService = registerBusinessService(serviceQName, (String) portName, serviceUrl, wsdlDefinition).getBusinessService();
166                                 }
167                         }
168                         if (businessService != null) {
169                                 businessServices.getBusinessService().add(businessService);
170                         }
171                 }
172 
173                 return businessServices;
174 
175         }
176 
177         @SuppressWarnings("unchecked")
178         public ServiceRegistrationResponse registerBusinessService(QName serviceQName, String portName, URL serviceUrl, Definition wsdlDefinition) throws RemoteException, ConfigurationException, TransportException, WSDLException, MalformedURLException {
179 
180                 String genericWSDLURL = wsdlDefinition.getDocumentBaseURI();   //TODO maybe point to repository version
181                 ServiceRegistrationResponse response = new ServiceRegistrationResponse();
182                 String serviceKey = UDDIKeyConvention.getServiceKey(properties, serviceQName.getLocalPart());
183                 BusinessService businessService = lookupService(serviceKey);
184                 if (businessService == null) {
185                         List<TModel> tModels = new ArrayList<TModel>();
186                         // Create the PortType tModels
187                         Map<QName, PortType> portTypes = (Map<QName, PortType>) wsdlDefinition.getAllPortTypes();
188                         tModels.addAll(createWSDLPortTypeTModels(genericWSDLURL, portTypes));
189                         // Create the Binding tModels
190                         Map<QName, Binding> bindings = (Map<QName, Binding>) wsdlDefinition.getAllBindings();
191                         tModels.addAll(createWSDLBindingTModels(genericWSDLURL, bindings));
192                         // Register these tModels
193                         for (TModel tModel : tModels) {
194                                 clerk.register(tModel);
195                         }
196                         // Service
197                         businessService = createBusinessService(serviceQName, wsdlDefinition);
198                         // Register this Service
199                         clerk.register(businessService);
200                 }
201                 //Add the BindingTemplate to this Service
202                 BindingTemplate binding = createWSDLBinding(serviceQName, portName, serviceUrl, wsdlDefinition);
203                 // Register BindingTemplate
204                 if (binding.getAccessPoint() != null) {
205                         clerk.register(binding);
206                         if (businessService.getBindingTemplates() == null) {
207                                 businessService.setBindingTemplates(new BindingTemplates());
208                         }
209                         businessService.getBindingTemplates().getBindingTemplate().add(binding);
210                         response.setBindingKey(binding.getBindingKey());
211                 }
212                 response.setBusinessService(businessService);
213                 return response;
214         }
215 
216         public String[] unRegisterBusinessServices(Definition wsdlDefinition) throws RemoteException, ConfigurationException, TransportException, MalformedURLException {
217 
218                 String[] businessServices = new String[wsdlDefinition.getAllServices().size()];
219                 int i = 0;
220                 for (Object serviceName : wsdlDefinition.getAllServices().keySet()) {
221                         QName serviceQName = (QName) serviceName;
222                         Service service = wsdlDefinition.getService(serviceQName);
223                         //unregister service
224                         URL serviceUrl = null;
225                         if (service.getPorts() != null && service.getPorts().size() > 0) {
226                                 for (Object portName : service.getPorts().keySet()) {
227                                         //construct the accessURL
228                                         serviceUrl = new URL(getBindingURL((Port) service.getPorts().get(portName)));
229                                         businessServices[i++] = unRegisterBusinessService(serviceQName, (String) portName, serviceUrl);
230                                 }
231                         }
232                 }
233                 return businessServices;
234         }
235 
236         public String unRegisterBusinessService(QName serviceName, String portName, URL serviceUrl) throws RemoteException, ConfigurationException, TransportException {
237 
238                 String serviceKey = UDDIKeyConvention.getServiceKey(properties, serviceName.getLocalPart());
239                 BusinessService service = lookupService(serviceKey);
240                 boolean isRemoveServiceIfNoTemplates = true;
241                 String bindingKey = UDDIKeyConvention.getBindingKey(properties, serviceName, portName, serviceUrl);
242                 //check if this bindingKey is in the service's binding templates
243                 for (BindingTemplate bindingTemplate : service.getBindingTemplates().getBindingTemplate()) {
244                         if (bindingKey.equals(bindingTemplate.getBindingKey())) {
245                                 clerk.unRegisterBinding(bindingKey);
246                                 //if this is the last binding for this service, and 
247                                 if (service.getBindingTemplates().getBindingTemplate().size() == 1 && isRemoveServiceIfNoTemplates) {
248                                         clerk.unRegisterService(serviceKey);
249                                         if (bindingTemplate.getTModelInstanceDetails() != null
250                                                 && bindingTemplate.getTModelInstanceDetails().getTModelInstanceInfo() != null) {
251                                                 for (TModelInstanceInfo tModelInstanceInfo : bindingTemplate.getTModelInstanceDetails().getTModelInstanceInfo()) {
252                                                         String tModelKey = tModelInstanceInfo.getTModelKey();
253                                                         TModelDetail tModelDetail = clerk.getTModelDetail(tModelKey);
254                                                         //delete all tModels assuming they are the portType and Binding tModels.
255                                                         if (tModelDetail.getTModel() != null && tModelDetail.getTModel().size() > 0) {
256                                                                 for (TModel tModel : tModelDetail.getTModel()) {
257                                                                         if (!tModel.getTModelKey().startsWith("uddi:uddi.org:")) {
258                                                                                 clerk.unRegisterTModel(tModel.getTModelKey());
259                                                                         } else {
260                                                                                 log.info("Skipping the removal of " + tModel.getTModelKey() + " because it starts with uddi.org");
261                                                                         }
262                                                                 }
263                                                         }
264                                                 }
265                                         }
266                                 }
267                         }
268                 }
269                 return serviceKey;
270         }
271 
272         public String getKeyDomainURI() {
273                 return keyDomainURI;
274         }
275 
276         public void setKeyDomain(String keyDomainURI) {
277                 this.keyDomainURI = keyDomainURI;
278         }
279 
280         public String getLang() {
281                 return lang;
282         }
283 
284         public void setLang(String lang) {
285                 this.lang = lang;
286         }
287 
288         /**
289          * <h3>2.4.2 wsdl:binding -> uddi:tModel</h3>
290          *
291          * <p>
292          * A wsdl:binding MUST be modeled as a uddi:tModel. The minimum
293          * information that must be captured about a binding is its entity type,
294          * its local name, its namespace, the location of the WSDL document that
295          * defines the binding, the portType that it implements, its protocol,
296          * and, optionally, the transport information. Capturing the entity type
297          * enables users to search for tModels that represent binding artifacts.
298          * Capturing the local name, namespace, and WSDL location enables users
299          * to locate the definition of the specified binding artifact. The link
300          * to the portType enables users to search for bindings that implement a
301          * particular portType.</p>
302          *
303          * <p>
304          * A wsdl:binding corresponds to a WSDL service interface definition as
305          * defined by the mapping in the Version 1 Best Practice. To maintain
306          * compatibility with the previous mapping, the binding must also be
307          * characterized as type "wsdlSpec".</p>
308          *
309          * <p>
310          * The wsdl:binding information is captured as follows:</p>
311          *
312          * <p>
313          * The uddi:name element of the tModel MUST be the value of the name
314          * attribute of the wsdl:binding.</p>
315          *
316          * <p>
317          * The tModel MUST contain a categoryBag, and the categoryBag MUST
318          * contain at least the following keyedReference elements:</p> <ol> <li>
319          * A keyedReference with a tModelKey of the WSDL Entity Type category
320          * system and a keyValue of "binding".</li> <li> A keyedReference with a
321          * tModelKey of the WSDL portType Reference category system and a
322          * keyValue of the tModelKey that models the wsdl:portType to which the
323          * wsdl:binding relates.</li> <li> A keyedReference with a tModelKey of
324          * the UDDI Types category system and a keyValue of "wsdlSpec" for
325          * backward compatibility[1].</li> <li> One or two keyedReferences as
326          * required to capture the protocol and optionally the transport
327          * information refer to the next section.</li> </ol>
328          *
329          * <p>
330          * If the wsdl:binding has a targetNamespace then the categoryBag MUST
331          * also contain an additional keyedReference with a tModelKey of the XML
332          * Namespace category system and a keyValue of the target namespace of
333          * the wsdl:definitions element that contains the wsdl:binding. If the
334          * targetNamespace is absent from the binding, a categoryBag MUST NOT
335          * contain a keyedReference to the XML Namespace category system.</p>
336          *
337          * <p>
338          * The tModel MUST contain an overviewDoc with an overviewURL containing
339          * the location of the WSDL document that describes the
340          * wsdl:binding.</p>
341          *
342          * <h4>2.4.2.1 wsdl:binding Extensions</h4>
343          *
344          * <p>
345          * Information about the protocol and transport, if applicable,
346          * specified in an extension to the wsdl:binding is used to categorize
347          * the binding tModel as described in the following sections. This
348          * information is specified using two of the category systems defined in
349          * this Technical Note:</p> <ol> <li> Protocol Categorization</li> <li>
350          * Transport Categorization</li> </ol>
351          * <p>
352          * The valid values for the Protocol Categorization category system are
353          * tModelKeys of tModels that are categorized as protocol tModels.
354          * Similarly, the valid values for the Transport Categorization category
355          * system are tModelKeys of tModels that are categorized as transport
356          * tModels.</p>
357          * <p>
358          * The reason for having these two categorization schemes that take
359          * tModel keys as values is to allow other standard or proprietary
360          * protocols and transports to be defined and used in the same way as
361          * the standard SOAP and HTTP protocols and transport.</p>
362          *
363          * <h4>2.4.2.1.1 soap:binding</h4>
364          *
365          * <p>
366          * If the wsdl:binding contains a soap:binding extensibility element
367          * from the http://schemas.xmlsoap.org/wsdl/soap/ namespace then the
368          * categoryBag MUST include a keyedReference with a tModelKey of the
369          * Protocol Categorization category system and a keyValue of the
370          * tModelKey of the SOAP Protocol tModel.</p>
371          *
372          * <p>
373          * If the value of the transport attribute of the soap:binding element
374          * is http://schemas.xmlsoap.org/soap/http then the categoryBag MUST
375          * include a keyedReference with a tModelKey of the Transport
376          * Categorization category system and a keyValue of the tModelKey of the
377          * HTTP Transport tModel.</p>
378          *
379          * <p>
380          * If the value of the transport attribute is anything else, then the
381          * bindingTemplate MUST include an additional keyedReference with a
382          * tModelKey of the Transport Categorization category system and a
383          * keyValue of the tModelKey of an appropriate transport tModel.</p>
384          *
385          * <h4>2.4.2.1.2 http:binding</h4>
386          *
387          * <p>
388          * If the wsdl:binding contains an http:binding extensibility element
389          * from the http://schemas.xmlsoap.org/wsdl/http/ namespace then the
390          * categoryBag MUST include a keyedReference with a tModelKey of the
391          * Protocol Categorization category system and a keyValue of the
392          * tModelKey of the HTTP Protocol tModel.</p>
393          *
394          * <p>
395          * Note that this is a different tModel from the HTTP Transport tModel,
396          * and in this case there is no separate transport tModel, and therefore
397          * no keyedReference in the categoryBag from the Transport
398          * Categorization category system.</p>
399          *
400          * <h4>2.4.2.1.3 Other wsdl:binding Extensions</h4>
401          *
402          * <p>
403          * Other wsdl:binding extensibility elements are handled in a similar
404          * fashion. It is assumed that vendors who provide other bindings will
405          * provide the appropriate protocol and transport tModels.</p>
406          *
407          * Example Code
408          * <pre>
409          * URL url = new URL("http://graphical.weather.gov/xml/SOAP_server/ndfdXMLserver.php?wsdl");
410          * String domain = url.getHost();
411          * ReadWSDL rw = new ReadWSDL();
412          * Definition wsdlDefinition = rw.readWSDL(url);
413          * properties.put("keyDomain", domain);
414          * properties.put("businessName", domain);
415          * properties.put("serverName", url.getHost());
416          * properties.put("serverPort", url.getPort());
417          * wsdlURL = wsdlDefinition.getDocumentBaseURI();
418          * WSDL2UDDI wsdl2UDDI = new WSDL2UDDI(null, new URLLocalizerDefaultImpl(), properties);
419          * Map allBindings = wsdlDefinition.getAllBindings();
420          * Set<TModel> createWSDLBindingTModels = wsdl2UDDI.createWSDLBindingTModels(url.toString(), allBindings);
421          * </pre>
422          *
423          * @param wsdlURL
424          * @param bindings Map
425          * @return set of WSDL Binding tModels
426          * @throws WSDLException
427          */
428         public Set<TModel> createWSDLBindingTModels(String wsdlURL, Map<QName, Binding> bindings) throws WSDLException {
429 
430                 Set<TModel> tModels = new HashSet<TModel>();
431                 //Register a tModel for each portType
432                 for (QName qName : bindings.keySet()) {
433                         String localpart = qName.getLocalPart();
434                         String namespace = qName.getNamespaceURI();
435                         // Build the tModel
436                         TModel tModel = new TModel();
437                         // Set the Key
438                         tModel.setTModelKey(keyDomainURI + localpart);
439                         // Set the Name
440                         Name name = new Name();
441                         name.setLang(lang);
442                         name.setValue(localpart);
443                         tModel.setName(name);
444                         // Set the OverviewURL
445                         OverviewURL overviewURL = new OverviewURL();
446                         overviewURL.setUseType(AccessPointType.WSDL_DEPLOYMENT.toString());
447                         overviewURL.setValue(wsdlURL);
448                         OverviewDoc overviewDoc = new OverviewDoc();
449                         overviewDoc.setOverviewURL(overviewURL);
450                         tModel.getOverviewDoc().add(overviewDoc);
451                         // Set the categoryBag
452                         CategoryBag categoryBag = new CategoryBag();
453 
454                         if (namespace != null && !"".equals(namespace)) {
455                                 // A keyedReference with a tModelKey of the WSDL Entity Type category system and a keyValue of "binding".
456                                 KeyedReference namespaceReference = newKeyedReference(
457                                         "uddi:uddi.org:xml:namespace", "uddi-org:xml:namespace", namespace);
458                                 categoryBag.getKeyedReference().add(namespaceReference);
459                         }
460 
461                         // A keyedReference with a tModelKey of the WSDL Entity Type category system and a keyValue of "binding".
462                         KeyedReference typesReference = newKeyedReference(
463                                 "uddi:uddi.org:wsdl:types", "uddi-org:wsdl:types", "binding");
464                         categoryBag.getKeyedReference().add(typesReference);
465 
466             // A keyedReference with a tModelKey of the WSDL portType Reference category system and a keyValue 
467                         // of the tModelKey that models the wsdl:portType to which the wsdl:binding relates.
468                         Binding binding = bindings.get(qName);
469                         String portTypeKey = keyDomainURI + binding.getPortType().getQName().getLocalPart();
470                         KeyedReference namespaceReference = newKeyedReference(
471                                 "uddi:uddi.org:wsdl:porttypereference", "uddi-org:wsdl:portTypeReference",
472                                 portTypeKey);
473                         categoryBag.getKeyedReference().add(namespaceReference);
474 
475             //  A keyedReference with a tModelKey of the UDDI Types category system and a keyValue of 
476                         // "wsdlSpec" for backward compatibility.
477                         KeyedReference typesReferenceBackwardsCompatible = newKeyedReference(
478                                 "uddi:uddi.org:categorization:types", "uddi-org:types", "wsdlSpec");
479                         categoryBag.getKeyedReference().add(typesReferenceBackwardsCompatible);
480 
481                         // One or two keyedReferences as required to capture the protocol
482                         for (Object object : binding.getExtensibilityElements()) {
483                                 SOAPBinding sb = null;
484                                 SOAP12Binding sb12 = null;
485                                 HTTPBinding hb = null;
486 
487                                 try {
488                                         hb = (HTTPBinding) object;
489                                 } catch (Exception x) {
490                                 }
491                                 try {
492                                         sb = (SOAPBinding) object;
493                                 } catch (Exception x) {
494                                 }
495                                 try {
496                                         sb12 = (SOAP12Binding) object;
497                                 } catch (Exception x) {
498                                 }
499                                 if (sb != null) {
500                     // If the wsdl:binding contains a soap:binding extensibility element from the 
501                                         // 'http://schemas.xmlsoap.org/wsdl/soap/' namespace then the categoryBag MUST 
502                                         //include a keyedReference with a tModelKey of the Protocol Categorization 
503                                         // category system and a keyValue of the tModelKey of the SOAP Protocol tModel.
504                                         SOAPBinding soapBinding = sb;
505                                         KeyedReference soapProtocol = newKeyedReference(
506                                                 "uddi:uddi.org:wsdl:categorization:protocol", "uddi-org:protocol:soap", "uddi:uddi.org:protocol:soap");
507                                         categoryBag.getKeyedReference().add(soapProtocol);
508                     // If the value of the transport attribute of the soap:binding element 
509                                         // is 'http://schemas.xmlsoap.org/soap/http' then the categoryBag MUST 
510                                         // include a keyedReference with a tModelKey of the Transport Categorization 
511                                         // category system and a keyValue of the tModelKey of the HTTP Transport tModel.
512                                         if ("http://schemas.xmlsoap.org/soap/http".equals(soapBinding.getTransportURI())) {
513                                                 KeyedReference httpTransport = newKeyedReference(
514                                                         "uddi:uddi.org:wsdl:categorization:transport", "uddi-org:http", "uddi:uddi.org:transport:http");
515                                                 categoryBag.getKeyedReference().add(httpTransport);
516                                         } else if (soapBinding.getTransportURI() != null) {
517                         // TODO If the value of the transport attribute is anything else, 
518                                                 // then the bindingTemplate MUST include an additional keyedReference with a tModelKey 
519                                                 // of the Transport Categorization category system and a keyValue of the tModelKey of 
520                                                 // an appropriate transport tModel.
521                                                 log.warn("not implemented, binding transport is " + soapBinding.getTransportURI());
522                                         }
523 
524                                 } else if (hb != null) {
525 
526                     // If the wsdl:binding contains an http:binding extensibility element from the 
527                                         // http://schemas.xmlsoap.org/wsdl/http/ namespace then the categoryBag MUST 
528                                         // include a keyedReference with a tModelKey of the Protocol Categorization 
529                                         // category system and a keyValue of the tModelKey of the HTTP Protocol tModel.
530                                         KeyedReference soapProtocol = newKeyedReference(
531                                                 "uddi:uddi.org:wsdl:categorization:protocol", "uddi-org:protocol:http", "uddi:uddi.org:protocol:http");
532                                         categoryBag.getKeyedReference().add(soapProtocol);
533                                 } else if (sb12 != null) {
534                     // If the wsdl:binding contains a soap:binding extensibility element from the 
535                                         // 'http://schemas.xmlsoap.org/wsdl/soap/' namespace then the categoryBag MUST 
536                                         //include a keyedReference with a tModelKey of the Protocol Categorization 
537                                         // category system and a keyValue of the tModelKey of the SOAP Protocol tModel.
538 
539                                         KeyedReference soapProtocol = newKeyedReference(
540                                                 "uddi:uddi.org:wsdl:categorization:protocol", "uddi-org:protocol:soap", "uddi:uddi.org:protocol:soap");
541                                         categoryBag.getKeyedReference().add(soapProtocol);
542                     // If the value of the transport attribute of the soap:binding element 
543                                         // is 'http://schemas.xmlsoap.org/soap/http' then the categoryBag MUST 
544                                         // include a keyedReference with a tModelKey of the Transport Categorization 
545                                         // category system and a keyValue of the tModelKey of the HTTP Transport tModel.
546                                         if ("http://schemas.xmlsoap.org/soap/http".equals(sb12.getTransportURI())) {
547                                                 KeyedReference httpTransport = newKeyedReference(
548                                                         "uddi:uddi.org:wsdl:categorization:transport", "uddi-org:http", "uddi:uddi.org:transport:http");
549                                                 categoryBag.getKeyedReference().add(httpTransport);
550                                         } else if (sb12.getTransportURI() != null) {
551                         // TODO If the value of the transport attribute is anything else, 
552                                                 // then the bindingTemplate MUST include an additional keyedReference with a tModelKey 
553                                                 // of the Transport Categorization category system and a keyValue of the tModelKey of 
554                                                 // an appropriate transport tModel.
555                                                 log.warn("not implemented, binding transport is " + sb12.getTransportURI());
556                                         }
557 
558                                 } else {
559                                         log.warn("Unrecongnized binding type: " + object.getClass().getCanonicalName() + ". Generated"
560                                                 + "binding tModel may be missing the required (according to WSDL2UDDI spec) "
561                                                 + "uddi:uddi.org:wsdl:categorization:protocol keyedReference.");
562 
563                                 }
564                         }
565 
566                         tModel.setCategoryBag(categoryBag);
567                         tModels.add(tModel);
568                 }
569                 return tModels;
570         }
571 
572         /**
573          * <h3>2.4.1 wsdl:portType -> uddi:tModel</h3>
574          *
575          * <p>
576          * A wsdl:portType MUST be modeled as a uddi:tModel.</p>
577          *
578          * <p>
579          * The minimum information that must be captured about a portType is its
580          * entity type, its local name, its namespace, and the location of the
581          * WSDL document that defines the portType. Capturing the entity type
582          * enables users to search for tModels that represent portType
583          * artifacts. Capturing the local name, namespace, and WSDL location
584          * enables users to locate the definition of the specified portType
585          * artifact.</p>
586          *
587          * <p>
588          * The wsdl:portType information is captured as follows:</p>
589          *
590          * <p>
591          * The uddi:name element of the tModel MUST be the value of the name
592          * attribute of the wsdl:portType.</p>
593          *
594          * <p>
595          * The tModel MUST contain a categoryBag, and the categoryBag MUST
596          * contain a keyedReference with a tModelKey of the WSDL Entity Type
597          * category system and a keyValue of "portType".</p>
598          *
599          * <p>
600          * If the wsdl:portType has a targetNamespace then the categoryBag MUST
601          * also contain an additional keyedReference with a tModelKey of the XML
602          * Namespace category system and a keyValue of the target namespace of
603          * the wsdl:definitions element that contains the wsdl:portType. If the
604          * targetNamespace is absent from the portType, a categoryBag MUST NOT
605          * contain a keyedReference to the XML Namespace category system.</p>
606          *
607          * <p>
608          * The tModel MUST contain an overviewDoc with an overviewURL containing
609          * the location of the WSDL document that describes the
610          * wsdl:portType.</p>
611          * Example Code
612          * <pre>
613          * URL url = new URL("http://graphical.weather.gov/xml/SOAP_server/ndfdXMLserver.php?wsdl");
614          * String domain = url.getHost();
615          * ReadWSDL rw = new ReadWSDL();
616          * Definition wsdlDefinition = rw.readWSDL(url);
617          * properties.put("keyDomain", domain);
618          * properties.put("businessName", domain);
619          * properties.put("serverName", url.getHost());
620          * properties.put("serverPort", url.getPort());
621          * wsdlURL = wsdlDefinition.getDocumentBaseURI();
622          * WSDL2UDDI wsdl2UDDI = new WSDL2UDDI(null, new URLLocalizerDefaultImpl(), properties);
623          * Map<QName, PortType> portTypes = (Map<QName, PortType>) wsdlDefinition.getAllPortTypes();
624          * Set<TModel> portTypeTModels = wsdl2UDDI.createWSDLPortTypeTModels(wsdlURL, portTypes);
625          * </pre>
626          *
627          * @param wsdlURL This is used to set the Overview URL
628          * @param portTypes Map
629          * @return set of WSDL PortType tModels
630          * @throws WSDLException
631          */
632         public Set<TModel> createWSDLPortTypeTModels(String wsdlURL, Map<QName, PortType> portTypes) throws WSDLException {
633                 Set<TModel> tModels = new HashSet<TModel>();
634                 // Create a tModel for each portType
635                 for (QName qName : portTypes.keySet()) {
636                         // Build the tModel
637                         TModel tModel = new TModel();
638                         String localpart = qName.getLocalPart();
639                         String namespace = qName.getNamespaceURI();
640                         // Set the Key
641                         tModel.setTModelKey(keyDomainURI + localpart);
642             // Set the Name. The uddi:name element of the tModel MUST be the value of
643                         // the name attribute of the wsdl:portType.
644                         Name name = new Name();
645                         name.setLang(lang);
646                         name.setValue(localpart);
647                         tModel.setName(name);
648             // Set the OverviewURL. The tModel MUST contain an overviewDoc with an 
649                         // overviewURL containing the location of the WSDL document that 
650                         // describes the wsdl:portType.
651                         OverviewURL overviewURL = new OverviewURL();
652                         overviewURL.setUseType(AccessPointType.WSDL_DEPLOYMENT.toString());
653                         overviewURL.setValue(wsdlURL);
654                         OverviewDoc overviewDoc = new OverviewDoc();
655                         overviewDoc.setOverviewURL(overviewURL);
656                         tModel.getOverviewDoc().add(overviewDoc);
657                         // Create the categoryBag, The tModel MUST contain a categoryBag
658                         CategoryBag categoryBag = new CategoryBag();
659 
660             // the categoryBag MUST contain a keyedReference with a tModelKey of the WSDL 
661                         // Entity Type category system and a keyValue of "portType".
662                         KeyedReference typesReference = newKeyedReference(
663                                 "uddi:uddi.org:wsdl:types", "uddi-org:wsdl:types", "portType");
664                         categoryBag.getKeyedReference().add(typesReference);
665 
666             // If the wsdl:portType has a targetNamespace then the categoryBag MUST also contain an 
667                         // additional keyedReference with a tModelKey of the XML Namespace category system and a 
668                         // keyValue of the target namespace of the wsdl:definitions element that contains the 
669                         // wsdl:portType. If the targetNamespace is absent from the portType, a categoryBag 
670                         // MUST NOT contain a keyedReference to the XML Namespace category system.
671                         if (namespace != null && !"".equals(namespace)) {
672                                 KeyedReference namespaceReference = newKeyedReference(
673                                         "uddi:uddi.org:xml:namespace", "uddi-org:xml:namespace", namespace);
674                                 categoryBag.getKeyedReference().add(namespaceReference);
675                         }
676 
677                         tModel.setCategoryBag(categoryBag);
678                         tModels.add(tModel);
679                 }
680                 return tModels;
681         }
682 
683         protected static KeyedReference newKeyedReference(String tModelKey, String keyName, String value) {
684                 KeyedReference typesReference = new KeyedReference();
685                 typesReference.setTModelKey(tModelKey);
686                 typesReference.setKeyName(keyName);
687                 typesReference.setKeyValue(value);
688                 return typesReference;
689         }
690 
691         /**
692          * Builds a finder to find the binding tModels for a portType.
693          *
694          * @param portType
695          * @param namespace
696          * @return tModel info
697          */
698         public static FindTModel createFindBindingTModelForPortType(String portType, String namespace) {
699 
700                 FindTModel findTModel = new FindTModel();
701                 CategoryBag categoryBag = new CategoryBag();
702 
703                 if (namespace != null && namespace.length() != 0) {
704                         KeyedReference namespaceReference = newKeyedReference(
705                                 "uddi:uddi.org:xml:namespace", "uddi-org:xml:namespace", namespace);
706                         categoryBag.getKeyedReference().add(namespaceReference);
707                 }
708                 KeyedReference bindingReference = newKeyedReference(
709                         "uddi:uddi.org:wsdl:types", "uddi-org:wsdl:types", "binding");
710                 categoryBag.getKeyedReference().add(bindingReference);
711 
712                 KeyedReference portTypeReference = newKeyedReference(
713                         "uddi:uddi.org:wsdl:porttypereference", "uddi-org:wsdl:portTypeReference", portType);
714                 categoryBag.getKeyedReference().add(portTypeReference);
715 
716                 findTModel.setCategoryBag(categoryBag);
717 
718                 if (log.isDebugEnabled()) {
719                         log.debug(new PrintUDDI<FindTModel>().print(findTModel));
720                 }
721                 return findTModel;
722         }
723 
724         /**
725          * Builds a finder to find the portType tModels for a portType.
726          *
727          * @param portTypeName
728          * @param namespace
729          * @return tModel info
730          */
731         public static FindTModel createFindPortTypeTModelForPortType(String portTypeName, String namespace) {
732 
733                 FindTModel findTModel = new FindTModel();
734                 Name name = new Name();
735                 name.setLang("en");
736                 name.setValue(portTypeName);
737                 findTModel.setName(name);
738 
739                 CategoryBag categoryBag = new CategoryBag();
740                 if (namespace != null && namespace.length() != 0) {
741                         KeyedReference namespaceReference = newKeyedReference(
742                                 "uddi:uddi.org:xml:namespace", "uddi-org:xml:namespace", namespace);
743                         categoryBag.getKeyedReference().add(namespaceReference);
744                 }
745                 KeyedReference bindingReference = newKeyedReference(
746                         "uddi:uddi.org:wsdl:types", "uddi-org:wsdl:types", "portType");
747                 categoryBag.getKeyedReference().add(bindingReference);
748 
749                 findTModel.setCategoryBag(categoryBag);
750 
751                 if (log.isDebugEnabled()) {
752                         log.debug(new PrintUDDI<FindTModel>().print(findTModel));
753                 }
754                 return findTModel;
755         }
756 
757         /**
758          * Perform a lookup by serviceKey, and will return null if not found.
759          *
760          * @param serviceKey
761          * @return business service
762          * @throws RemoteException
763          * @throws ConfigurationException
764          * @throws TransportException
765          */
766         private BusinessService lookupService(String serviceKey) throws RemoteException, ConfigurationException, TransportException {
767 
768                 //Checking if this serviceKey already exist
769                 BusinessService service = clerk.getServiceDetail(serviceKey);
770                 return service;
771         }
772 
773         /**
774          * Creates a business service based off of a WSDL definition<Br>No
775          * changes are made to the UDDI endpoints using this method
776          * <br>
777          * Example Code:
778          * <pre>
779          * URL url = new URL("http://graphical.weather.gov/xml/SOAP_server/ndfdXMLserver.php?wsdl");
780          * String domain = url.getHost();
781          * ReadWSDL rw = new ReadWSDL();
782          * Definition wsdlDefinition = rw.readWSDL(url);
783          * properties.put("keyDomain", domain);
784          * properties.put("businessName", domain);
785          * properties.put("serverName", url.getHost());
786          * properties.put("serverPort", url.getPort());
787          * wsdlURL = wsdlDefinition.getDocumentBaseURI();
788          * WSDL2UDDI wsdl2UDDI = new WSDL2UDDI(null, new URLLocalizerDefaultImpl(), properties);
789          * BusinessServices businessServices = wsdl2UDDI.createBusinessServices(wsdlDefinition);
790          * </pre>
791          *
792          * @param wsdlDefinition must not be null
793          * @return a business service
794          * @throws MalformedURLException
795          * @throws IllegalArgumentException if the wsdlDefinition is null
796          */
797         public BusinessServices createBusinessServices(Definition wsdlDefinition) throws MalformedURLException {
798                 if (wsdlDefinition == null) {
799                         throw new IllegalArgumentException();
800                 }
801                 BusinessServices businessServices = new BusinessServices();
802                 for (Object serviceName : wsdlDefinition.getAllServices().keySet()) {
803                         QName serviceQName = (QName) serviceName;
804                         Service service = wsdlDefinition.getService(serviceQName);
805                         BusinessService businessService = createBusinessService(serviceQName, wsdlDefinition);
806             //service.getExtensibilityElements().
807                         //add the bindingTemplates
808                         URL serviceUrl = null;
809                         if (service.getPorts() != null && service.getPorts().size() > 0) {
810                                 businessService.setBindingTemplates(new BindingTemplates());
811                                 for (Object portName : service.getPorts().keySet()) {
812                                         BindingTemplate bindingTemplate = createWSDLBinding(serviceQName, (String) portName, serviceUrl, wsdlDefinition);
813                                         businessService.getBindingTemplates().getBindingTemplate().add(bindingTemplate);
814                                 }
815                         }
816                         businessServices.getBusinessService().add(businessService);
817                 }
818 
819                 return businessServices;
820         }
821 
822         /**
823          * Creates a UDDI Business Service.
824          *
825          * @param serviceQName
826          * @param wsdlDefinition
827          * @return a business service
828          */
829         protected BusinessService createBusinessService(QName serviceQName, Definition wsdlDefinition) {
830 
831                 log.debug("Constructing Service UDDI Information for " + serviceQName);
832                 BusinessService service = new BusinessService();
833                 // BusinessKey
834                 service.setBusinessKey(businessKey);
835                 // ServiceKey
836                 service.setServiceKey(UDDIKeyConvention.getServiceKey(properties, serviceQName.getLocalPart()));
837                 // Description
838                 String serviceDescription = properties.getProperty(Property.SERVICE_DESCRIPTION, Property.DEFAULT_SERVICE_DESCRIPTION);
839                 // Override with the service description from the WSDL if present
840                 if (wsdlDefinition.getService(serviceQName) != null) {
841                         Element docElement = wsdlDefinition.getService(serviceQName).getDocumentationElement();
842                         if (docElement != null && docElement.getTextContent() != null) {
843                                 serviceDescription = docElement.getTextContent();
844                         }
845                 }
846 
847                 service.getDescription().addAll(Common2UDDI.mapDescription(serviceDescription, lang));
848 
849                 // Service name
850                 Name sName = new Name();
851                 sName.setLang(lang);
852                 sName.setValue(serviceQName.getLocalPart());
853                 service.getName().add(sName);
854 
855                 CategoryBag categoryBag = new CategoryBag();
856 
857                 String namespace = serviceQName.getNamespaceURI();
858                 if (namespace != null && namespace.length() != 0) {
859                         KeyedReference namespaceReference = newKeyedReference(
860                                 "uddi:uddi.org:xml:namespace", "uddi-org:xml:namespace", namespace);
861                         categoryBag.getKeyedReference().add(namespaceReference);
862                 }
863 
864                 KeyedReference serviceReference = newKeyedReference(
865                         "uddi:uddi.org:wsdl:types", "uddi-org:wsdl:types", "service");
866                 categoryBag.getKeyedReference().add(serviceReference);
867 
868                 KeyedReference localNameReference = newKeyedReference(
869                         "uddi:uddi.org:xml:localname", "uddi-org:xml:localName", serviceQName.getLocalPart());
870                 categoryBag.getKeyedReference().add(localNameReference);
871 
872                 service.setCategoryBag(categoryBag);
873 
874                 return service;
875         }
876 
877         protected BindingTemplate createWSDLBinding(QName serviceQName, String portName, URL serviceUrl, Definition wsdlDefinition) throws MalformedURLException {
878 
879                 BindingTemplate bindingTemplate = new BindingTemplate();
880                 // Set BusinessService Key
881                 bindingTemplate.setServiceKey(UDDIKeyConvention.getServiceKey(properties, serviceQName.getLocalPart()));
882 
883                 if (serviceUrl != null) {
884                         // Set AccessPoint
885                         AccessPoint accessPoint = new AccessPoint();
886                         accessPoint.setUseType(AccessPointType.END_POINT.toString());
887                         accessPoint.setValue(urlLocalizer.rewrite(serviceUrl));
888                         bindingTemplate.setAccessPoint(accessPoint);
889                         // Set Binding Key
890                         String bindingKey = UDDIKeyConvention.getBindingKey(properties, serviceQName, portName, serviceUrl);
891                         bindingTemplate.setBindingKey(bindingKey);
892                 }
893 
894                 Service service = wsdlDefinition.getService(serviceQName);
895                 if (service != null) {
896                         TModelInstanceDetails tModelInstanceDetails = new TModelInstanceDetails();
897 
898                         Port port = service.getPort(portName);
899                         if (port != null) {
900                                 if (serviceUrl == null) {
901                                         for (Object element : port.getExtensibilityElements()) {
902                                                 String location = null;
903                                                 if (element instanceof SOAPAddress) {
904                                                         SOAPAddress address = (SOAPAddress) element;
905                                                         location = urlLocalizer.rewrite(new URL(address.getLocationURI()));
906                                                 } else if (element instanceof HTTPAddress) {
907                                                         HTTPAddress address = (HTTPAddress) element;
908                                                         urlLocalizer.rewrite(new URL(location = address.getLocationURI()));
909                                                 } else if (element instanceof SOAP12Address) {
910                                                         SOAP12Address address = (SOAP12Address) element;
911                                                         location = urlLocalizer.rewrite(new URL(address.getLocationURI()));
912                                                 }
913                                                 if (location != null) {
914                                                         try {
915                                                                 URL locationURI = new URL(location);
916                                                                 AccessPoint accessPoint = new AccessPoint();
917                                                                 accessPoint.setUseType(AccessPointType.END_POINT.toString());
918                                                                 accessPoint.setValue(urlLocalizer.rewrite(locationURI));
919                                                                 bindingTemplate.setAccessPoint(accessPoint);
920                                                                 // Set Binding Key
921                                                                 String bindingKey = UDDIKeyConvention.getBindingKey(properties, serviceQName, portName, locationURI);
922                                                                 bindingTemplate.setBindingKey(bindingKey);
923                                                                 break;
924                                                         } catch (MalformedURLException e) {
925                                                                 log.error(e.getMessage());
926                                                         }
927                                                 }
928                                         }
929 
930                                 }
931                                 Binding binding = port.getBinding();
932                                 // Set the Binding Description
933                                 String bindingDescription = properties.getProperty(Property.BINDING_DESCRIPTION, Property.DEFAULT_BINDING_DESCRIPTION);
934                                 // Override with the service description from the WSDL if present
935                                 Element docElement = binding.getDocumentationElement();
936                                 if (docElement != null && docElement.getTextContent() != null) {
937                                         bindingDescription = docElement.getTextContent();
938                                 }
939 
940                                 bindingTemplate.getDescription().addAll(Common2UDDI.mapDescription(bindingDescription, lang));
941 
942                                 // reference wsdl:binding tModel
943                                 TModelInstanceInfo tModelInstanceInfoBinding = new TModelInstanceInfo();
944                                 tModelInstanceInfoBinding.setTModelKey(keyDomainURI + binding.getQName().getLocalPart());
945                                 InstanceDetails instanceDetails = new InstanceDetails();
946                                 instanceDetails.setInstanceParms(portName);
947                                 tModelInstanceInfoBinding.setInstanceDetails(instanceDetails);
948 
949                                 tModelInstanceInfoBinding.getDescription().addAll(Common2UDDI.mapDescription("The wsdl:binding that this wsdl:port implements. " + bindingDescription
950                                         + " The instanceParms specifies the port local name.", lang));
951                                 tModelInstanceDetails.getTModelInstanceInfo().add(tModelInstanceInfoBinding);
952 
953                                 // reference wsdl:portType tModel
954                                 PortType portType = binding.getPortType();
955                                 TModelInstanceInfo tModelInstanceInfoPortType = new TModelInstanceInfo();
956                                 tModelInstanceInfoPortType.setTModelKey(keyDomainURI + portType.getQName().getLocalPart());
957                                 String portTypeDescription = "";
958                                 docElement = portType.getDocumentationElement();
959                                 if (docElement != null && docElement.getTextContent() != null) {
960                                         portTypeDescription = docElement.getTextContent();
961                                 }
962 
963                                 tModelInstanceInfoPortType.getDescription().addAll(Common2UDDI.mapDescription("The wsdl:portType that this wsdl:port implements." + portTypeDescription, lang));
964                                 tModelInstanceDetails.getTModelInstanceInfo().add(tModelInstanceInfoPortType);
965 
966                                 bindingTemplate.setTModelInstanceDetails(tModelInstanceDetails);
967                         } else {
968                                 log.error("Could not find Port with portName: " + portName);
969                         }
970                 } else {
971                         log.error("Could not find Service with serviceName: " + serviceQName.getLocalPart());
972                 }
973 
974                 return UDDIClient.addSOAPtModels(bindingTemplate);
975         }
976 
977         /**
978          * Obtains the accessUrl from the WSDL
979          *
980          * @param port
981          * @return a string url
982          * @throws MalformedURLException
983          */
984         private String getBindingURL(Port port) throws MalformedURLException {
985 
986                 String bindingUrl = null;
987                 for (Object element : port.getExtensibilityElements()) {
988                         if (element instanceof SOAPAddress) {
989                                 SOAPAddress address = (SOAPAddress) element;
990                                 URL locationURI = new URL(address.getLocationURI());
991                                 if (locationURI != null) {
992                                         bindingUrl = urlLocalizer.rewrite(locationURI);
993                                         break;
994                                 }
995                         }
996                 }
997                 return bindingUrl;
998         }
999 }