This project has retired. For details please refer to its
Attic page.
SubscriptionCallbackListener xref
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
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
91
92
93 public SubscriptionCallbackListener() {
94 Runtime runtime = Runtime.getRuntime();
95 runtime.addShutdownHook(new Thread(this));
96 }
97
98
99
100
101
102
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
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
162
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
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
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
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
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
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
281
282
283
284
285 public static String getCallbackURL() {
286 return callback;
287
288 }
289
290
291
292
293
294
295
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
307
308
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
319
320 public static final String PROPERTY_LISTENURL = "client.subscriptionCallbacks.listenUrl";
321
322
323
324 public static final String PROPERTY_NODE = "client.subscriptionCallbacks.node";
325
326
327
328 public static final String PROPERTY_KEYDOMAIN = "client.subscriptionCallbacks.keyDomain";
329
330
331
332 public static final String PROPERTY_AUTOREG_BT = "client.subscriptionCallbacks.autoRegisterBindingTemplate";
333
334
335
336 public static final String PROPERTY_AUTOREG_SERVICE_KEY = "client.subscriptionCallbacks.autoRegisterBusinessServiceKey";
337
338
339
340
341
342 public static final String PROPERTY_SIGNATURE_BEHAVIOR = "client.subscriptionCallbacks.signatureBehavior";
343
344
345
346
347
348
349
350
351
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
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
441
442
443 public enum SignatureBehavior {
444
445
446
447
448
449 AbortIfSigned,
450
451
452
453
454
455 SignAlways,
456
457
458
459
460 SignOnlyIfParentIsntSigned,
461
462
463
464
465 DoNothing
466 }
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
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
559
560
561
562
563
564
565
566
567
568
569
570 public static synchronized void stop(UDDIClient client, String cfg_node_name, String bindingKey) throws ConfigurationException {
571
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
600
601
602
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 }