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 }