View Javadoc
1   /*
2    * Copyright 2013 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  package org.apache.juddi.v3.client.subscription;
17  
18  import java.net.MalformedURLException;
19  import java.net.URL;
20  import java.net.UnknownHostException;
21  import java.rmi.RemoteException;
22  import java.rmi.UnexpectedException;
23  import java.util.ArrayList;
24  import java.util.List;
25  import java.util.Random;
26  import java.util.UUID;
27  
28  import javax.jws.WebService;
29  import javax.xml.bind.annotation.XmlSeeAlso;
30  import javax.xml.ws.Endpoint;
31  
32  import org.apache.commons.configuration.ConfigurationException;
33  import org.apache.commons.logging.Log;
34  import org.apache.commons.logging.LogFactory;
35  import org.apache.juddi.v3.client.config.UDDIClerk;
36  import org.apache.juddi.v3.client.config.UDDIClient;
37  import org.apache.juddi.v3.client.cryptor.DigSigUtil;
38  import org.apache.juddi.v3.client.transport.Transport;
39  import org.apache.juddi.v3.client.transport.TransportException;
40  import org.uddi.api_v3.AccessPoint;
41  import org.uddi.api_v3.BindingDetail;
42  import org.uddi.api_v3.BindingTemplate;
43  import org.uddi.api_v3.BusinessDetail;
44  import org.uddi.api_v3.DeleteBinding;
45  import org.uddi.api_v3.DispositionReport;
46  import org.uddi.api_v3.GetBindingDetail;
47  import org.uddi.api_v3.GetBusinessDetail;
48  import org.uddi.api_v3.GetServiceDetail;
49  import org.uddi.api_v3.Result;
50  import org.uddi.api_v3.SaveBinding;
51  import org.uddi.api_v3.ServiceDetail;
52  import org.uddi.api_v3.TModelInstanceDetails;
53  import org.uddi.api_v3.TModelInstanceInfo;
54  import org.uddi.subr_v3.NotifySubscriptionListener;
55  import org.uddi.v3_service.DispositionReportFaultMessage;
56  import org.uddi.v3_service.UDDIInquiryPortType;
57  import org.uddi.v3_service.UDDIPublicationPortType;
58  
59  /**
60   * WebService which implements the UDDI v3 SubscriptionListener API. This
61   * service will be called by the UDDI registry when any change to a Service or
62   * BindingTemplate call in to it.
63   * <h1>Usage scenario</h1>
64   * Use this call for when you need to be notified from a UDDI server that either
65   * a UDDI entity was created, changed, or deleted via the UDDI Subscription web
66   * service. This class will start up an embedded Jetty server (built into the
67   * JRE). You can then register your code to be notified of any inbound messages
68   * received from the UDDI server asynchronously. Here's some sample code.
69   * <pre>
70   * UDDIClient c = new UDDIClient("META-INF/uddiclient.xml");
71   * UDDIClerk clerk = c.getClerk("default");
72   * TModel createKeyGenator = UDDIClerk.createKeyGenator("uddi:org.apache.juddi:test:keygenerator", "Test domain", "en");
73   * clerk.register(createKeyGenator);
74   * BindingTemplate start = SubscriptionCallbackListener.start(c, "default");
75   * //keep alive
76   * while(running)
77   * Thread.sleep(1000);
78   * SubscriptionCallbackListener.stop(c, "default", start.getBindingKey());
79   * </pre>
80   *
81   * @author <a href="mailto:alexoree@apache.org">Alex O'Ree</a>
82   * @since 3.2
83   */
84  @WebService(serviceName = "UDDISubscriptionListenerClientService",
85          endpointInterface = "org.uddi.v3_service.UDDISubscriptionListenerPortType",
86          targetNamespace = "urn:uddi-org:v3_service")
87  public class SubscriptionCallbackListener implements org.uddi.v3_service.UDDISubscriptionListenerPortType, Runnable {
88  
89          /**
90           * adds a shutdown hook to trap and warn about leaving the server
91           * running on exit
92           */
93          public SubscriptionCallbackListener() {
94                  Runtime runtime = Runtime.getRuntime();
95                  runtime.addShutdownHook(new Thread(this));
96          }
97  
98          /**
99           * used for unit tests, may return null if the endpoint isn't started
100          * yet
101          *
102          * @return gets an instance
103          */
104         protected static SubscriptionCallbackListener getInstance() {
105                 return instance;
106         }
107         private static final Log log = LogFactory.getLog(SubscriptionCallbackListener.class);
108         private static List<ISubscriptionCallback> callbacks = new ArrayList<ISubscriptionCallback>();
109         private static SubscriptionCallbackListener instance = null;
110         private static Endpoint ep = null;
111 
112         /**
113          * Starts a embedded Jetty web server (comes with the JDK) using the
114          * Endpoint API.
115          *
116          * @param client
117          * @param cfg_node_name
118          * @param endpoint this is the url that a UDDI server would use to
119          * connect to the client's subscription listener service Recommend
120          * specifying a port that is firewall friendly
121          * @param keydomain
122          *
123          * @param autoregister
124          * @param behavior
125          * @param serviceKey
126          * @return null, if and only if callbackBusinessService was null,
127          * otherwise the modified callbackBusinessService is returned. Clients
128          * can then use it to continue the registration process.
129          * @throws ServiceAlreadyStartedException
130          * @throws SecurityException
131          * @throws ConfigurationException
132          * @throws TransportException
133          * @throws DispositionReportFaultMessage
134          * @throws java.rmi.UnexpectedException
135          * @throws
136          * org.apache.juddi.v3.client.subscription.RegistrationAbortedException
137          * @throws java.net.MalformedURLException
138          * @throws org.apache.juddi.v3.client.subscription.UnableToSignException
139          * @see Endpoint
140          */
141         public static synchronized BindingTemplate start(UDDIClient client, String cfg_node_name, String endpoint,
142                 String keydomain, boolean autoregister, String serviceKey,
143                 SignatureBehavior behavior) throws ServiceAlreadyStartedException, SecurityException, ConfigurationException, TransportException, DispositionReportFaultMessage, RemoteException, UnexpectedException, RegistrationAbortedException, UnableToSignException, MalformedURLException {
144 
145                 if (instance == null) {
146                         instance = new SubscriptionCallbackListener();
147                 }
148 
149                 if (ep != null && ep.isPublished()) {
150                         throw new ServiceAlreadyStartedException();
151                 }
152 
153                 URL url = null;
154                 try {
155                         url = new URL(endpoint);
156                 } catch (Exception ex) {
157                         log.warn("Callback endpoint couldn't be parsed, generating a random one: " + ex.getMessage());
158                         url = new URL("http://" + GetHostname() + ":" + GetRandomPort(4000) + "/" + UUID.randomUUID().toString());
159                 }
160                 endpoint = url.toString();
161                 //if (endpoint == null || endpoint.equals("")) {
162                 //    endpoint = "http://" + GetHostname() + ":" + GetRandomPort(url.getPort()) + "/" + UUID.randomUUID().toString();
163 
164                 int attempts = 5;
165                 if (ep == null) {
166                         while ((ep == null || !ep.isPublished()) && attempts > 0) {
167                                 try {
168                                         ep = Endpoint.publish(endpoint, instance);
169                                         callback = endpoint;
170                                 } catch (Exception be) {
171                                         log.info("trouble starting callback at " + endpoint + ", trying again with a random port: " + be.getMessage());
172                                         log.debug(be);
173                                         attempts--;
174                                         //if (be instanceof java.net.BindException) {
175                                         url = new URL("http://" + url.getHost() + ":" + GetRandomPort(url.getPort()) + "/" + url.getPath());
176                                         endpoint = url.toString();
177 
178                                 }
179                         }
180                 }
181                 if (ep == null || !ep.isPublished()) {
182                         log.warn("Unable to start callback endpoint, aborting");
183                         throw new SecurityException("unable to start endpoint, view previous errors for reason");
184                 }
185 
186                 log.info("Endpoint started at " + callback);
187 
188                 BindingTemplate bt = new BindingTemplate();
189                 bt.setAccessPoint(new AccessPoint());
190                 bt.getAccessPoint().setValue(callback);
191                 bt.getAccessPoint().setUseType("endPoint");
192                 TModelInstanceInfo instanceInfo = new TModelInstanceInfo();
193                 instanceInfo.setTModelKey("uddi:uddi.org:transport:http");
194                 bt.setTModelInstanceDetails(new TModelInstanceDetails());
195                 bt.getTModelInstanceDetails().getTModelInstanceInfo().add(instanceInfo);
196                 bt.setServiceKey(serviceKey);
197                 if (keydomain.endsWith(":")) {
198                         bt.setBindingKey(keydomain + GetHostname() + "_subscription_callback");
199                 } else {
200                         bt.setBindingKey(keydomain + ":" + GetHostname() + "_subscription_callback");
201                 }
202 
203                 if (autoregister) {
204                         bt = registerBinding(client, cfg_node_name, bt, behavior);
205                 }
206 
207                 return bt;
208 
209         }
210 
211         /**
212          * Starts a subscription callback service using the juddi client config
213          * file's settings. This will use the config setting PROPERTY_NODE, or
214          * default if not defined
215          *
216          * @param client
217          * @return a bindingtemplate populated with the relevant information for
218          * most UDDI servers for asynchronous callbacks.
219          * @throws ServiceAlreadyStartedException
220          * @throws SecurityException
221          * @throws ConfigurationException
222          * @throws TransportException
223          * @throws DispositionReportFaultMessage
224          * @throws UnexpectedException
225          * @throws RemoteException
226          * @throws
227          * org.apache.juddi.v3.client.subscription.RegistrationAbortedException
228          * @throws org.apache.juddi.v3.client.subscription.UnableToSignException
229          * @throws java.net.MalformedURLException
230          */
231         public static synchronized BindingTemplate start(UDDIClient client) throws ServiceAlreadyStartedException, SecurityException, ConfigurationException, TransportException, DispositionReportFaultMessage, UnexpectedException, RemoteException, RegistrationAbortedException, UnableToSignException, MalformedURLException {
232                 return start(client, client.getClientConfig().getConfiguration().getString(PROPERTY_NODE, "default"));
233         }
234 
235         /**
236          * Starts a subscription callback service using the juddi client config
237          * file's settings. This will use the specified node
238          *
239          * @param client
240          * @param cfg_node_name the node to connect to and perform all
241          * operations on
242          * @return a bindingtemplate populated with the relevant information for
243          * most UDDI servers for asynchronous callbacks.
244          * @throws ServiceAlreadyStartedException
245          * @throws SecurityException
246          * @throws ConfigurationException
247          * @throws TransportException
248          * @throws DispositionReportFaultMessage
249          * @throws UnexpectedException
250          * @throws RemoteException
251          * @throws
252          * org.apache.juddi.v3.client.subscription.RegistrationAbortedException
253          * @throws org.apache.juddi.v3.client.subscription.UnableToSignException
254          * @throws java.net.MalformedURLException
255          */
256         public static synchronized BindingTemplate start(UDDIClient client, String cfg_node_name) throws ServiceAlreadyStartedException, SecurityException, ConfigurationException, TransportException, DispositionReportFaultMessage, UnexpectedException, RemoteException, RegistrationAbortedException, UnableToSignException, MalformedURLException {
257 
258                 try {
259                         boolean reg = (client.getClientConfig().getConfiguration().getBoolean(PROPERTY_AUTOREG_BT, false));
260 
261                         String endpoint = client.getClientConfig().getConfiguration().getString(PROPERTY_LISTENURL);
262                         String kd = client.getClientConfig().getConfiguration().getString(PROPERTY_KEYDOMAIN);
263                         String key = client.getClientConfig().getConfiguration().getString(PROPERTY_AUTOREG_SERVICE_KEY);
264                         String sbs = client.getClientConfig().getConfiguration().getString(PROPERTY_SIGNATURE_BEHAVIOR);
265                         SignatureBehavior sb = SignatureBehavior.DoNothing;
266                         try {
267                                 sb = SignatureBehavior.valueOf(sbs);
268                         } catch (Exception ex) {
269                                 log.warn("Unable to parse config setting for SignatureBehavior, defaulting to DoNothing", ex);
270                         }
271                         return start(client, cfg_node_name, endpoint, kd, reg, key, sb);
272                 } catch (ConfigurationException ex) {
273                         throw new ConfigurationException("failed to some critical settings from the juddi client config file. I won't be able to fire up the subscription callback endpoint ", ex);
274                 }
275 
276         }
277         private static String callback = null;
278 
279         /**
280          * gets the current callback url, may be null if the endpoint isn't
281          * started yet
282          *
283          * @return the current callback url or null
284          */
285         public static String getCallbackURL() {
286                 return callback;
287 
288         }
289 
290         /**
291          * Registers an implementation of ISubscriptionCallback for subscription
292          * callbacks from a UDDI server.
293          *
294          *
295          * @param callback if null, no action is taken
296          */
297         public static synchronized void registerCallback(ISubscriptionCallback callback) {
298                 if (callback != null) {
299                         if (!callbacks.contains(callback)) {
300                                 callbacks.add(callback);
301                         }
302                 }
303         }
304 
305         /**
306          * unregisters a ISubscriptionCallback for callbacks
307          *
308          * @param callback if null, no action is taken
309          */
310         public static synchronized void unRegisterCallback(ISubscriptionCallback callback) {
311                 if (callback != null) {
312                         if (callbacks.contains(callback)) {
313                                 callbacks.remove(callback);
314                         }
315                 }
316         }
317         /**
318          * config parameter
319          */
320         public static final String PROPERTY_LISTENURL = "client.subscriptionCallbacks.listenUrl";
321         /**
322          * config parameter, if not defined, default will be used
323          */
324         public static final String PROPERTY_NODE = "client.subscriptionCallbacks.node";
325         /**
326          * config parameter
327          */
328         public static final String PROPERTY_KEYDOMAIN = "client.subscriptionCallbacks.keyDomain";
329         /**
330          * config parameter true/false
331          */
332         public static final String PROPERTY_AUTOREG_BT = "client.subscriptionCallbacks.autoRegisterBindingTemplate";
333         /**
334          * config parameter business key
335          */
336         public static final String PROPERTY_AUTOREG_SERVICE_KEY = "client.subscriptionCallbacks.autoRegisterBusinessServiceKey";
337         /**
338          * config parameter
339          *
340          * @see SignatureBehavior
341          */
342         public static final String PROPERTY_SIGNATURE_BEHAVIOR = "client.subscriptionCallbacks.signatureBehavior";
343 
344         /**
345          * return true if and only if the binding exists and is signed
346          *
347          * @param bindingKey
348          * @param uddiInquiryService
349          * @param token
350          * @param behavior
351          * @return true/false
352          */
353         private static boolean CheckExistingBindingForSignature(String bindingKey, UDDIInquiryPortType uddiInquiryService, String token, SignatureBehavior behavior) {
354                 GetBindingDetail gbd = new GetBindingDetail();
355                 gbd.setAuthInfo(token);
356                 gbd.getBindingKey().add(bindingKey);
357                 try {
358                         BindingDetail bindingDetail = uddiInquiryService.getBindingDetail(gbd);
359                         if (bindingDetail != null
360                                 && !bindingDetail.getBindingTemplate().isEmpty()
361                                 && !bindingDetail.getBindingTemplate().get(0).getSignature().isEmpty()) {
362                                 log.info("the binding template with key=" + bindingKey + " exists and is digitally signed");
363                         }
364                         return true;
365                 } catch (Exception ex) {
366                         log.debug("Error caught checking for the existence of and if a signature is present for binding key " + bindingKey + " this may be ignorable", ex);
367                 }
368                 return false;
369         }
370 
371         private static boolean CheckServiceAndParentForSignature(String serviceKey, UDDIInquiryPortType uddiInquiryService, String token) throws UnexpectedResponseException {
372                 GetServiceDetail gsd = new GetServiceDetail();
373                 gsd.setAuthInfo(token);
374                 gsd.getServiceKey().add(serviceKey);
375                 String bizkey = null;
376                 try {
377                         ServiceDetail serviceDetail = uddiInquiryService.getServiceDetail(gsd);
378                         if (serviceDetail != null) {
379                                 if (!serviceDetail.getBusinessService().isEmpty()) {
380                                         bizkey = serviceDetail.getBusinessService().get(0).getBusinessKey();
381                                         if (!serviceDetail.getBusinessService().get(0).getSignature().isEmpty()) {
382                                                 log.info("the service with key=" + serviceKey + " exists and is digitally signed");
383                                                 return true;
384                                         }
385                                 }
386                         }
387                 } catch (Exception ex) {
388                         log.info("Error caught checking for the existence of and if a signature is present for service key " + serviceKey, ex);
389                         throw new UnexpectedResponseException("Error caught checking for the existence of and if a signature is present for service key " + serviceKey, ex);
390                 }
391                 if (bizkey == null) {
392                         throw new UnexpectedResponseException("The service with key " + serviceKey + " parent's business key could not be determined. This is unexpected");
393                 }
394                 GetBusinessDetail gbd = new GetBusinessDetail();
395                 gbd.setAuthInfo(token);
396                 gbd.getBusinessKey().add(bizkey);
397                 try {
398                         BusinessDetail businessDetail = uddiInquiryService.getBusinessDetail(gbd);
399                         if (businessDetail != null && !businessDetail.getBusinessEntity().isEmpty()) {
400                                 if (!businessDetail.getBusinessEntity().get(0).getSignature().isEmpty()) {
401                                         log.info("the business with key=" + bizkey + " exists and is digitally signed");
402                                         return true;
403                                 }
404                         }
405                 } catch (Exception ex) {
406                         log.info("Error caught checking for the existence of and if a signature is present for business key " + bizkey, ex);
407                         throw new UnexpectedResponseException("Error caught checking for the existence of and if a signature is present for business key " + bizkey, ex);
408                 }
409                 return false;
410         }
411 
412         private static int GetRandomPort(int oldport) {
413                 if (oldport <= 0) {
414                         oldport = 4000;
415                 }
416                 return oldport + new Random().nextInt(99);
417 
418         }
419 
420         /**
421          * shutdown hook
422          */
423         @Override
424         public void run() {
425                 shutdown();
426         }
427 
428         private synchronized void shutdown() {
429                 if (ep != null && !ep.isPublished()) {
430                         log.fatal("Hey, someone should tell the developer to call SubscriptionCallbackListern.stop(...) before ending the program. Stopping endpoint at " + callback);
431                         unregisterAllCallbacks();
432                         ep.stop();
433                         ep = null;
434                         callback = null;
435                 }
436 
437         }
438 
439         /**
440          * This defines how the automatic subscription binding template is
441          * suppose to behave
442          */
443         public enum SignatureBehavior {
444 
445                 /**
446                  * Aborts the save request if either the entity exists and is
447                  * already signed, or if any parent uddi element is signed
448                  */
449                 AbortIfSigned,
450                 /**
451                  * Signs this element. Warning: It may cause signatures of
452                  * parent elements to become invalid. If unable to sign, an
453                  * exception will be thrown
454                  */
455                 SignAlways,
456                 /**
457                  * Signs this element, but only if parents are not signed. If
458                  * unable to sign, an exception will be thrown
459                  */
460                 SignOnlyIfParentIsntSigned,
461                 /**
462                  * Do nothing, don't sign it and don't check if a parent item is
463                  * signed or not.
464                  */
465                 DoNothing
466         }
467 
468         /**
469          * Registers a UDDI binding template that represents the subscription
470          * callback endpoint
471          *
472          * @param client
473          * @param cfg_node_name
474          * @param bt - Binding Template
475          * @param behavior
476          * @return a binding template
477          * @throws ServiceAlreadyStartedException
478          * @throws SecurityException
479          * @throws ConfigurationException
480          * @throws TransportException
481          * @throws DispositionReportFaultMessage
482          * @throws RemoteException
483          * @throws UnexpectedException
484          * @throws RegistrationAbortedException
485          * @throws UnableToSignException
486          */
487         public static BindingTemplate registerBinding(UDDIClient client, String cfg_node_name, BindingTemplate bt, SignatureBehavior behavior) throws ServiceAlreadyStartedException, SecurityException, ConfigurationException, TransportException, DispositionReportFaultMessage, RemoteException, UnexpectedException, RegistrationAbortedException, UnableToSignException {
488 
489                 UDDIClerk clerk = client.getClerk(cfg_node_name);
490                 Transport tp = client.getTransport(cfg_node_name);
491                 UDDIInquiryPortType uddiInquiryService = tp.getUDDIInquiryService();
492                 UDDIPublicationPortType uddiPublishService = tp.getUDDIPublishService();
493 
494                 String token = clerk.getAuthToken(clerk.getUDDINode().getSecurityUrl());
495 
496                 switch (behavior) {
497                         case AbortIfSigned:
498                                 if (CheckExistingBindingForSignature(bt.getBindingKey(), uddiInquiryService, token, behavior)) {
499                                         throw new RegistrationAbortedException("Aborting, Either the item exists and is signed");
500                                 }
501                                 if (CheckServiceAndParentForSignature(bt.getServiceKey(), uddiInquiryService, token)) {
502                                         throw new RegistrationAbortedException("Aborting, Either the service or busness is signed");
503                                 }
504                                 break;
505                         case DoNothing:
506                                 break;
507                         case SignAlways:
508                                 try {
509                                         DigSigUtil ds = new DigSigUtil(client.getClientConfig().getDigitalSignatureConfiguration());
510                                         bt = ds.signUddiEntity(bt);
511                                 } catch (Exception ex) {
512                                         log.error("Unable to sign", ex);
513                                         throw new UnableToSignException(ex);
514                                 }
515 
516                                 break;
517                         case SignOnlyIfParentIsntSigned:
518                                 if (!CheckServiceAndParentForSignature(bt.getServiceKey(), uddiInquiryService, token)) {
519                                         try {
520                                                 DigSigUtil ds = new DigSigUtil(client.getClientConfig().getDigitalSignatureConfiguration());
521                                                 bt = ds.signUddiEntity(bt);
522                                         } catch (Exception ex) {
523                                                 log.error("Unable to sign", ex);
524                                                 throw new UnableToSignException(ex);
525                                         }
526                                 }
527                                 break;
528                 }
529                 SaveBinding sb = new SaveBinding();
530                 sb.setAuthInfo(token);
531                 sb.getBindingTemplate().add(bt);
532 
533                 BindingDetail saveBinding = uddiPublishService.saveBinding(sb);
534                 if (saveBinding.getBindingTemplate().isEmpty() || saveBinding.getBindingTemplate().size() > 1) {
535                         throw new UnexpectedResponseException("The number of binding templates returned was unexpected, count=" + saveBinding.getBindingTemplate().size());
536                 }
537                 return saveBinding.getBindingTemplate().get(0);
538         }
539 
540         protected static synchronized void unregisterAllCallbacks() {
541                 if (callbacks != null) {
542                         log.info("Notifying all subscribing classes, count=" + callbacks.size());
543                         for (int i = 0; i < callbacks.size(); i++) {
544                                 if (callbacks.get(i) != null) {
545                                         try {
546                                                 callbacks.get(i).notifyEndpointStopped();
547                                         } catch (Exception ex) {
548                                                 log.warn("Your implementation on ISubscriptionCallback is faulty and threw an error, contact the developer", ex);
549                                         }
550                                 }
551                         }
552                         callbacks.clear();
553                 }
554 
555         }
556 
557         /**
558          * This effectively stops the endpoint address and notifies all
559          * ISubscriptionCallback clients that the endpoint as been stopped.
560          * After it has been stopped, all ISubscriptionCallback are removed from
561          * the callback list. If the configuration file is set to automatically
562          * register binding templates, the binding template will be unregistered
563          * from the UDDI server
564          *
565          * @param client
566          * @param cfg_node_name
567          * @param bindingKey
568          * @throws org.apache.commons.configuration.ConfigurationException
569          */
570         public static synchronized void stop(UDDIClient client, String cfg_node_name, String bindingKey) throws ConfigurationException {
571                 //stop the service
572                 if (ep != null && ep.isPublished()) {
573                         log.warn("Stopping jUDDI Subscription callback endpoint at " + callback);
574                         ep.stop();
575                         if (ep.isPublished()) {
576                                 log.fatal("Unable to stop the endpoint. the port may be locked until this java process terminates");
577                         }
578                         ep = null;
579                         callback = null;
580                 }
581                 unregisterAllCallbacks();
582                 if (client.getClientConfig().getConfiguration().getBoolean(PROPERTY_AUTOREG_BT, false) && bindingKey != null) {
583 
584                         try {
585                                 UDDIClerk clerk = client.getClerk(cfg_node_name);
586                                 Transport tp = client.getTransport(cfg_node_name);
587                                 String token = clerk.getAuthToken(clerk.getUDDINode().getSecurityUrl());
588                                 UDDIPublicationPortType uddiPublishService = tp.getUDDIPublishService();
589                                 DeleteBinding db = new DeleteBinding();
590                                 db.setAuthInfo(token);
591                                 db.getBindingKey().add(bindingKey);
592                                 uddiPublishService.deleteBinding(db);
593                                 log.info("Subscription callback binding unregistered.");
594                         } catch (Exception ex) {
595                                 log.error("Unable to unregister binding " + bindingKey, ex);
596                         }
597                 }
598 
599                 //TODO optionally kill the subscription?
600                 //get all subscriptions from the uddi node, 
601                 //loop through and deduce which ones are pointed at this endpoint
602                 //then remove them
603         }
604 
605         private static String GetHostname() {
606                 try {
607                         return java.net.InetAddress.getLocalHost().getHostName();
608                 } catch (UnknownHostException ex) {
609                         return "HOST_UNKNOWN";
610                 }
611         }
612 
613         @Override
614         public DispositionReport notifySubscriptionListener(NotifySubscriptionListener body) throws DispositionReportFaultMessage, RemoteException {
615                 for (int i = 0; i < callbacks.size(); i++) {
616                         try {
617                                 callbacks.get(i).handleCallback(body.getSubscriptionResultsList());
618                         } catch (Exception ex) {
619                                 log.warn("Your implementation on ISubscriptionCallback is faulty and threw an error, contact the developer", ex);
620                         }
621                 }
622                 DispositionReport r = new DispositionReport();
623                 r.getResult().add(new Result());
624                 return r;
625         }
626 }