PageRenderTime 47ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/servers/sip-presence/sip-event/server/subscription/sbb/src/main/java/org/mobicents/slee/sipevent/server/subscription/eventlist/EventListSubscriberSbb.java

http://mobicents.googlecode.com/
Java | 434 lines | 300 code | 70 blank | 64 comment | 63 complexity | af72b8d2199c8d6fd78be47569aad957 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-3.0, LGPL-2.1, GPL-2.0, CC-BY-SA-3.0, CC0-1.0, Apache-2.0, BSD-3-Clause
  1. /*
  2. * JBoss, Home of Professional Open Source
  3. * Copyright 2011, Red Hat, Inc. and individual contributors
  4. * by the @authors tag. See the copyright.txt in the distribution for a
  5. * full listing of individual contributors.
  6. *
  7. * This is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU Lesser General Public License as
  9. * published by the Free Software Foundation; either version 2.1 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This software is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this software; if not, write to the Free
  19. * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  20. * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  21. */
  22. package org.mobicents.slee.sipevent.server.subscription.eventlist;
  23. import gov.nist.javax.sip.Utils;
  24. import java.util.Set;
  25. import javax.sip.message.Response;
  26. import javax.slee.ActivityContextInterface;
  27. import javax.slee.CreateException;
  28. import javax.slee.RolledBackContext;
  29. import javax.slee.Sbb;
  30. import javax.slee.SbbContext;
  31. import javax.slee.facilities.Tracer;
  32. import org.mobicents.slee.ChildRelationExt;
  33. import org.mobicents.slee.SbbContextExt;
  34. import org.mobicents.slee.sipevent.server.rlscache.RLSService;
  35. import org.mobicents.slee.sipevent.server.rlscache.RLSServiceActivity;
  36. import org.mobicents.slee.sipevent.server.rlscache.events.RLSServicesRemovedEvent;
  37. import org.mobicents.slee.sipevent.server.rlscache.events.RLSServicesUpdatedEvent;
  38. import org.mobicents.slee.sipevent.server.subscription.EventListSubscriber;
  39. import org.mobicents.slee.sipevent.server.subscription.EventListSubscriberParentSbbLocalObject;
  40. import org.mobicents.slee.sipevent.server.subscription.SubscriptionClientControlSbbLocalObject;
  41. import org.mobicents.slee.sipevent.server.subscription.data.Subscription;
  42. import org.mobicents.slee.sipevent.server.subscription.data.Subscription.Event;
  43. import org.mobicents.slee.sipevent.server.subscription.data.Subscription.Status;
  44. import org.mobicents.slee.sipevent.server.subscription.data.SubscriptionKey;
  45. import org.openxdm.xcap.client.appusage.resourcelists.jaxb.EntryType;
  46. /**
  47. *
  48. * Sbb that acts as the back end subscriber to the entries in a resource list.
  49. *
  50. * @author Eduardo Martins
  51. *
  52. */
  53. public abstract class EventListSubscriberSbb implements Sbb,
  54. EventListSubscriber {
  55. private static Tracer tracer;
  56. // --- CMPs
  57. public abstract void setRLSServiceACI(ActivityContextInterface value);
  58. public abstract ActivityContextInterface getRLSServiceACI();
  59. public abstract void setNotificationData(NotificationData value);
  60. public abstract NotificationData getNotificationData();
  61. public abstract void setSubscriptionKey(SubscriptionKey subscriptionKey);
  62. public abstract SubscriptionKey getSubscriptionKey();
  63. public abstract void setSubscriber(String subscriber);
  64. public abstract String getSubscriber();
  65. // --- sbb logic
  66. private String getVirtualSubscriptionId(SubscriptionKey originalSubscriptionKey,String virtualSubscriptionNotifier) {
  67. return new StringBuilder(originalSubscriptionKey.toString()).append(":list:").append(virtualSubscriptionNotifier).toString();
  68. }
  69. private EventListSubscriberParentSbbLocalObject getParentSbb() {
  70. return (EventListSubscriberParentSbbLocalObject) sbbContext.getSbbLocalObject().getParent();
  71. }
  72. public void subscribe(Subscription subscription, RLSService rlsService, ActivityContextInterface rlsServiceAci) {
  73. if (tracer.isFineEnabled()) {
  74. tracer.fine("creating backend subscriptions for rls subscription "+subscription.getKey());
  75. }
  76. // store subscription data in cmp
  77. setSubscriptionKey(subscription.getKey());
  78. setSubscriber(subscription.getSubscriber());
  79. setRLSServiceACI(rlsServiceAci);
  80. // set notification data object, when a notification comes and this
  81. // object exists the notification data will be added, otherwise a new
  82. // NotificationData object for a single entry is created and the parent
  83. // is notified with the resulting multipart
  84. setNotificationData(new NotificationData(subscription.getNotifier().getUriWithParam(),subscription.getVersion(),rlsService,Utils.getInstance().generateTag(),Utils.getInstance().generateTag()));
  85. // get subscription client child
  86. SubscriptionClientControlSbbLocalObject subscriptionClient = null;
  87. try {
  88. subscriptionClient = (SubscriptionClientControlSbbLocalObject) getSubscriptionClientControlChildRelation().create(ChildRelationExt.DEFAULT_CHILD_NAME);
  89. }
  90. catch (Exception e) {
  91. tracer.severe("failed to create child",e);
  92. return;
  93. }
  94. // create "virtual" subscriptions
  95. for (EntryType entryType : rlsService.getEntries()) {
  96. subscriptionClient.subscribe(subscription.getSubscriber(), subscription.getSubscriberDisplayName(), entryType.getUri(), subscription.getKey().getEventPackage(), getVirtualSubscriptionId(subscription.getKey(),entryType.getUri()), subscription.getExpires(), null, null, null);
  97. }
  98. }
  99. public void onRLSServicesRemovedEvent(RLSServicesRemovedEvent event, ActivityContextInterface aci) {
  100. if (tracer.isFineEnabled()) {
  101. tracer.fine("rls service removed, terminating subscription "+getSubscriptionKey());
  102. }
  103. // time to remove the subscription
  104. unsubscribe(getSubscriber(), getSubscriptionKey(),getRLService());
  105. }
  106. public void onRLSServicesUpdatedEvent(RLSServicesUpdatedEvent event, ActivityContextInterface aci) {
  107. Subscription subscription = getParentSbb().getSubscription(getSubscriptionKey());
  108. if (subscription != null) {
  109. resubscribe(subscription,getRLService(),event.getNewEntries(),event.getOldEntries(),event.getRemovedEntries());
  110. }
  111. }
  112. public void resubscribe(Subscription subscription, RLSService rlsService) {
  113. resubscribe(subscription, rlsService, null, rlsService.getEntries(), null);
  114. }
  115. private void resubscribe(Subscription subscription, RLSService rlsService, Set<EntryType> newEntries, Set<EntryType> oldEntries, Set<EntryType> removedEntries) {
  116. if (tracer.isFineEnabled()) {
  117. tracer.fine("refreshing backend subscriptions for rls subscription "+subscription.getKey());
  118. }
  119. // version is incremented
  120. subscription.incrementVersion();
  121. subscription.store();
  122. // prepare for a full state notification
  123. setNotificationData(new NotificationData(subscription.getNotifier().getUriWithParam(),subscription.getVersion(),rlsService,Utils.getInstance().generateTag(),Utils.getInstance().generateTag()));
  124. // get subscription client child
  125. SubscriptionClientControlSbbLocalObject subscriptionClient = (SubscriptionClientControlSbbLocalObject) getSubscriptionClientControlChildRelation().get(ChildRelationExt.DEFAULT_CHILD_NAME);
  126. // update "virtual" subscriptions
  127. if (removedEntries != null) {
  128. for (EntryType entryType : removedEntries) {
  129. subscriptionClient.unsubscribe(subscription.getSubscriber(), entryType.getUri(), subscription.getKey().getEventPackage(), getVirtualSubscriptionId(subscription.getKey(),entryType.getUri()));
  130. }
  131. }
  132. if (oldEntries != null) {
  133. for (EntryType entryType : oldEntries) {
  134. subscriptionClient.resubscribe(subscription.getSubscriber(), entryType.getUri(), subscription.getKey().getEventPackage(), getVirtualSubscriptionId(subscription.getKey(),entryType.getUri()), subscription.getExpires());
  135. }
  136. }
  137. if (newEntries != null) {
  138. for (EntryType entryType : newEntries) {
  139. subscriptionClient.subscribe(subscription.getSubscriber(), subscription.getSubscriberDisplayName(), entryType.getUri(), subscription.getKey().getEventPackage(), getVirtualSubscriptionId(subscription.getKey(),entryType.getUri()), subscription.getExpires(),null,null,null);
  140. }
  141. }
  142. }
  143. public void unsubscribe(Subscription subscription, RLSService rlsService) {
  144. unsubscribe(subscription.getSubscriber(), subscription.getKey(), rlsService);
  145. }
  146. private void unsubscribe(String subscriber, SubscriptionKey key, RLSService rlsService) {
  147. if (tracer.isFineEnabled()) {
  148. tracer.fine("removing backend subscriptions for rls subscription "+key);
  149. }
  150. for (ActivityContextInterface aci : sbbContext.getActivities()) {
  151. aci.detach(sbbContext.getSbbLocalObject());
  152. }
  153. // let's set the key as null so there are no further notifications from back end subscriptions
  154. setSubscriptionKey(null);
  155. if(rlsService != null) {
  156. // get subscription client child
  157. SubscriptionClientControlSbbLocalObject subscriptionClient = (SubscriptionClientControlSbbLocalObject) getSubscriptionClientControlChildRelation().get(ChildRelationExt.DEFAULT_CHILD_NAME);
  158. // remove "virtual" subscriptions
  159. for (EntryType entryType : rlsService.getEntries()) {
  160. subscriptionClient.unsubscribe(subscriber, entryType.getUri(), key.getEventPackage(), getVirtualSubscriptionId(key,entryType.getUri()));
  161. }
  162. }
  163. }
  164. private RLSService getRLService() {
  165. ActivityContextInterface aci = getRLSServiceACI();
  166. if (aci == null) return null;
  167. RLSServiceActivity activity = (RLSServiceActivity) aci.getActivity();
  168. return activity.getRLSService();
  169. }
  170. private Subscription getSubscription(EventListSubscriberParentSbbLocalObject parentSbb, SubscriptionKey key, String subscriber) {
  171. Subscription subscription = parentSbb.getSubscription(key);
  172. if (subscription == null && getSubscriptionKey() != null) {
  173. tracer.warning("Unable to get subscription "+key+" from parent sbb, it does not exists anymore! Removing all virtual subscriptions");
  174. unsubscribe(subscriber, key,getRLService());
  175. }
  176. return subscription;
  177. }
  178. // --- SIP EVENT CHILD SBB CALL BACKS
  179. private NotificationData createPartialStateNotificationData(EventListSubscriberParentSbbLocalObject parentSbb, SubscriptionKey subscriptionKey, String subscriber, String notifier) {
  180. // get subscription
  181. Subscription subscription = getSubscription(parentSbb, subscriptionKey, subscriber);
  182. if (subscription != null) {
  183. // increment subscription version
  184. subscription.incrementVersion();
  185. subscription.store();
  186. // create notification data for a single resource
  187. RLSService rlsService = getRLService();
  188. if (rlsService != null) {
  189. for (EntryType entryType : rlsService.getEntries()) {
  190. if (entryType.getUri().equals(notifier)) {
  191. return new NotificationData(subscription.getNotifier().getUriWithParam(),subscription.getVersion(),entryType,Utils.getInstance().generateTag(), Utils.getInstance().generateTag());
  192. }
  193. }
  194. }
  195. }
  196. return null;
  197. }
  198. @Override
  199. public void notifyEvent(String subscriber, String notifier,
  200. String eventPackage, String subscriptionId,
  201. Event terminationReason, Status status, String content,
  202. String contentType, String contentSubtype) {
  203. SubscriptionKey subscriptionKey = getSubscriptionKey();
  204. // if key is null we are removing subscriptions and have no interest in further notifications
  205. if (subscriptionKey != null) {
  206. if (tracer.isFineEnabled()) {
  207. tracer.fine("notification for rls subscription "+subscriptionKey+" from " + notifier);
  208. }
  209. EventListSubscriberParentSbbLocalObject parentSbb = getParentSbb();
  210. NotificationData notificationData = getNotificationData();
  211. if (notificationData == null) {
  212. notificationData = createPartialStateNotificationData(parentSbb, subscriptionKey, subscriber, notifier);
  213. if (notificationData == null) {
  214. // null then abort notification
  215. return;
  216. }
  217. }
  218. // add notification data
  219. String id = notifier;
  220. String cid = content != null ? id : null;
  221. MultiPart multiPart = null;
  222. try {
  223. multiPart = notificationData.addNotificationData(notifier, cid, id, content, contentType, contentSubtype, status.toString(), (terminationReason == null ? null : terminationReason.toString()));
  224. }
  225. catch (IllegalStateException e) {
  226. if (tracer.isFineEnabled()) {
  227. tracer.fine(e.getMessage(),e);
  228. }
  229. // there is a chance that on a full state update concurrent backend subscriptions may try add notification data after multipart was built, if that happens we will get this exception and do a partial notification
  230. notificationData = createPartialStateNotificationData(parentSbb, subscriptionKey, subscriber, notifier);
  231. if (notificationData == null) {
  232. // null then abort notification
  233. return;
  234. }
  235. multiPart = notificationData.addNotificationData(notifier, cid, id, content, contentType, contentSubtype, status.toString(), (terminationReason == null ? null : terminationReason.toString()));
  236. }
  237. // notify parent?
  238. if (multiPart != null) {
  239. setNotificationData(null);
  240. parentSbb.notifyEventListSubscriber(subscriptionKey, multiPart);
  241. }
  242. }
  243. }
  244. public void resubscribeError(String subscriber, String notifier,
  245. String eventPackage, String subscriptionId, int error) {
  246. if (tracer.isFineEnabled()) {
  247. tracer.fine("resubscribeError: sid="+subscriptionId+", error="+error);
  248. }
  249. EventListSubscriberParentSbbLocalObject parentSbb = getParentSbb();
  250. SubscriptionKey key = getSubscriptionKey();
  251. switch (error) {
  252. case Response.CONDITIONAL_REQUEST_FAILED:
  253. // perhaps virtual subscription died, lets try to subscribe again
  254. Subscription subscription = getSubscription(parentSbb, key, subscriber);
  255. if (subscription != null) {
  256. ((SubscriptionClientControlSbbLocalObject) getSubscriptionClientControlChildRelation().get(ChildRelationExt.DEFAULT_CHILD_NAME)).subscribe(subscriber, subscription.getSubscriberDisplayName(), notifier, eventPackage, subscriptionId, subscription.getExpires(), null, null, null);
  257. }
  258. break;
  259. default:
  260. break;
  261. }
  262. }
  263. public void resubscribeOk(String subscriber, String notifier,
  264. String eventPackage, String subscriptionId, int expires) {
  265. // ignore
  266. if (tracer.isFineEnabled()) {
  267. tracer.fine("resubscribeOk: sid="+subscriptionId);
  268. }
  269. }
  270. public void subscribeError(String subscriber, String notifier,
  271. String eventPackage, String subscriptionId, int error) {
  272. if (tracer.isFineEnabled()) {
  273. tracer.fine("subscribeError: sid="+subscriptionId+", error="+error);
  274. }
  275. EventListSubscriberParentSbbLocalObject parentSbb = getParentSbb();
  276. SubscriptionKey subscriptionKey = getSubscriptionKey();
  277. NotificationData notificationData = getNotificationData();
  278. if (notificationData == null) {
  279. notificationData = createPartialStateNotificationData(parentSbb, subscriptionKey, subscriber, notifier);
  280. }
  281. String cid = notifier;
  282. MultiPart multiPart = null;
  283. // add notification data
  284. switch (error) {
  285. case Response.FORBIDDEN:
  286. try {
  287. multiPart = notificationData.addNotificationData(notifier, null, cid, null, null, null, "terminated", "rejected");
  288. }
  289. catch (IllegalStateException e) {
  290. // there is a chance that on a full state update concurrent backend subscriptions may try add notification data after multipart was built, if that happens we will get this exception and do a partial notification
  291. notificationData = createPartialStateNotificationData(parentSbb, subscriptionKey, subscriber, notifier);
  292. multiPart = notificationData.addNotificationData(notifier, null, cid, null, null, null, "terminated", "rejected");
  293. }
  294. break;
  295. default:
  296. try {
  297. multiPart = notificationData.notificationDataNotNeeded(notifier);
  298. }
  299. catch (IllegalStateException e) {
  300. // there is a chance that on a full state update concurrent backend subscriptions may try add notification data after multipart was built, if that happens we will get this exception and do a partial notification
  301. notificationData = createPartialStateNotificationData(parentSbb, subscriptionKey, subscriber, notifier);
  302. multiPart = notificationData.notificationDataNotNeeded(notifier);
  303. }
  304. break;
  305. }
  306. // notify parent?
  307. if (multiPart != null) {
  308. setNotificationData(null);
  309. parentSbb.notifyEventListSubscriber(subscriptionKey, multiPart);
  310. }
  311. }
  312. public void subscribeOk(String subscriber, String notifier,
  313. String eventPackage, String subscriptionId, int expires,
  314. int responseCode) {
  315. // ignore
  316. if (tracer.isFineEnabled()) {
  317. tracer.fine("subscribeOk: sid="+subscriptionId);
  318. }
  319. }
  320. public void unsubscribeError(String subscriber, String notifier,
  321. String eventPackage, String subscriptionId, int error) {
  322. if (tracer.isFineEnabled()) {
  323. tracer.fine("unsubscribeError: sid="+subscriptionId+", error="+error);
  324. }
  325. }
  326. public void unsubscribeOk(String subscriber, String notifier,
  327. String eventPackage, String subscriptionId) {
  328. if (tracer.isFineEnabled()) {
  329. tracer.fine("unsubscribeOk: sid="+subscriptionId);
  330. }
  331. }
  332. // --- SIP EVENT CLIENT CHILD SBB
  333. public abstract ChildRelationExt getSubscriptionClientControlChildRelation();
  334. // ----------- SBB OBJECT's LIFE CYCLE
  335. private SbbContextExt sbbContext;
  336. public void setSbbContext(SbbContext sbbContext) {
  337. this.sbbContext = (SbbContextExt) sbbContext;
  338. if (tracer == null) {
  339. tracer = sbbContext.getTracer(getClass().getSimpleName());
  340. }
  341. }
  342. public void sbbActivate() {
  343. }
  344. public void sbbCreate() throws CreateException {
  345. }
  346. public void sbbExceptionThrown(Exception arg0, Object arg1,
  347. ActivityContextInterface arg2) {
  348. }
  349. public void sbbLoad() {
  350. }
  351. public void sbbPassivate() {
  352. }
  353. public void sbbPostCreate() throws CreateException {
  354. }
  355. public void sbbRemove() {
  356. }
  357. public void sbbRolledBack(RolledBackContext arg0) {
  358. }
  359. public void sbbStore() {
  360. }
  361. public void unsetSbbContext() {
  362. this.sbbContext = null;
  363. }
  364. }