package org.mobicents.slee.sipevent.server.subscription.winfo; import java.io.StringWriter; import java.math.BigInteger; import java.text.ParseException; import java.util.Iterator; import java.util.List; import javax.persistence.EntityManager; import javax.sip.Dialog; import javax.sip.header.ContentTypeHeader; import javax.sip.message.Request; import javax.slee.ActivityContextInterface; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import org.apache.log4j.Logger; import org.mobicents.slee.sipevent.server.subscription.ImplementedSubscriptionControlSbbLocalObject; import org.mobicents.slee.sipevent.server.subscription.SubscriptionControlSbb; import org.mobicents.slee.sipevent.server.subscription.pojo.Subscription; import org.mobicents.slee.sipevent.server.subscription.winfo.pojo.Watcher; import org.mobicents.slee.sipevent.server.subscription.winfo.pojo.WatcherList; import org.mobicents.slee.sipevent.server.subscription.winfo.pojo.Watcherinfo; /** * Service logic regarding winfo subscriptions * * @author martins * */ public class WInfoSubscriptionHandler { private static Logger logger = Logger .getLogger(SubscriptionControlSbb.class); private SubscriptionControlSbb sbb; public WInfoSubscriptionHandler(SubscriptionControlSbb sbb) { this.sbb = sbb; } public void notifyWinfoSubscriptions(EntityManager entityManager, Subscription subscription, ImplementedSubscriptionControlSbbLocalObject childSbb) { if (!subscription.getKey().getEventPackage().endsWith(".winfo")) { // lookup persistent data fr subscriptions List winfoSubscriptions = entityManager.createNamedQuery(Subscription.JPA_NAMED_QUERY_SELECT_SUBSCRIPTIONS_FROM_NOTIFIER_AND_EVENTPACKAGE) .setParameter("notifier", subscription.getNotifier()) .setParameter("eventPackage", subscription.getKey().getEventPackage() + ".winfo") .getResultList(); // process result if (!winfoSubscriptions.isEmpty()) { for (Iterator it = winfoSubscriptions.iterator(); it.hasNext();) { Subscription winfoSubscription = (Subscription) it.next(); if (winfoSubscription.getStatus().equals( Subscription.Status.active)) { try { // get subscription aci ActivityContextInterface winfoAci = sbb .getActivityContextNamingfacility().lookup( winfoSubscription.getKey() .toString()); if (winfoAci != null) { // increment subscription version winfoSubscription.incrementVersion(); // get winfo notify content and content type // header String partialWInfoContent = getPartialWatcherInfoContent( winfoSubscription, subscription); ContentTypeHeader winfoContentHeader = getWatcherInfoContentHeader(); if (winfoSubscription.getKey() .isInternalSubscription()) { // internal subscription sbb .getInternalSubscriptionHandler() .getInternalSubscriberNotificationHandler() .notifyInternalSubscriber(entityManager, subscription, partialWInfoContent, winfoContentHeader, winfoAci); } else { // sip subscription Dialog winfoDialog = (Dialog) winfoAci .getActivity(); // create notify Request notify = sbb .getSipSubscribeHandler() .getSipSubscriberNotificationHandler() .createNotify(winfoDialog, winfoSubscription); // add content notify.setContent(partialWInfoContent, winfoContentHeader); // send notify in dialog related with // subscription winfoDialog.sendRequest(sbb .getSipProvider() .getNewClientTransaction(notify)); if (logger.isDebugEnabled()) { logger.debug("Request sent:\n" + notify.toString()); } } // persist subscription entityManager.persist(winfoSubscription); } else { // aci is gone, cleanup subscription logger .warn("Unable to find subscription aci to notify subscription " + winfoSubscription.getKey() + ". Removing subscription data"); sbb .removeSubscriptionData( entityManager, winfoSubscription, null, null, childSbb); } } catch (Exception e) { logger .error("failed to notify winfo subscriber", e); } } } } entityManager.flush(); } } private static final JAXBContext winfoJAXBContext = initWInfoJAXBContext(); private static JAXBContext initWInfoJAXBContext() { try { return JAXBContext .newInstance("org.mobicents.slee.sipevent.server.subscription.winfo.pojo"); } catch (JAXBException e) { logger.error("failed to create winfo jaxb context"); return null; } } private Marshaller getWInfoMarshaller() { try { return winfoJAXBContext.createMarshaller(); } catch (JAXBException e) { logger.error("failed to create winfo unmarshaller", e); return null; } } /* * creates watcher jaxb object for a subscription */ private Watcher createWInfoWatcher(Subscription subscription) { // create watcher Watcher watcher = new Watcher(); watcher.setId(String.valueOf(subscription.hashCode())); watcher.setStatus(subscription.getStatus().toString()); watcher.setDurationSubscribed(BigInteger.valueOf(subscription .getSubscriptionDuration())); if (subscription.getLastEvent() != null) { watcher.setEvent(subscription.getLastEvent().toString()); } if (subscription.getSubscriberDisplayName() != null) { watcher.setDisplayName(subscription.getSubscriberDisplayName()); } if (!subscription.getStatus().equals(Subscription.Status.terminated)) { watcher.setExpiration(BigInteger.valueOf(subscription .getRemainingExpires())); } watcher.setValue(subscription.getSubscriber()); return watcher; } /* * marshals a jaxb watcherinfo object to string */ private String marshallWInfo(Watcherinfo watcherinfo) { // marshall to string String result = null; StringWriter stringWriter = new StringWriter(); try { Marshaller marshaller = getWInfoMarshaller(); marshaller.marshal(watcherinfo, stringWriter); result = stringWriter.toString(); stringWriter.close(); } catch (Exception e) { logger.error("failed to marshall winfo", e); try { stringWriter.close(); } catch (Exception f) { logger.error("failed to close winfo string writer", f); } } return result; } /* * creates partial watcher info doc */ private String getPartialWatcherInfoContent(Subscription winfoSubscription, Subscription subscription) { // create watcher info Watcherinfo watcherinfo = new Watcherinfo(); watcherinfo.setVersion(BigInteger.valueOf(winfoSubscription .getVersion())); watcherinfo.setState("partial"); // create watcher list WatcherList watcherList = new WatcherList(); watcherList.setResource(winfoSubscription.getNotifier()); watcherList.setPackage(subscription.getKey().getEventPackage()); // create and add watcher to watcher info list watcherList.getWatcher().add(createWInfoWatcher(subscription)); // add watcher list to watcher info watcherinfo.getWatcherList().add(watcherList); // marshall and return return marshallWInfo(watcherinfo); } /* * generates full watcher info doc */ public String getFullWatcherInfoContent(EntityManager entityManager, Subscription winfoSubscription) { // create watcher info Watcherinfo watcherinfo = new Watcherinfo(); watcherinfo.setVersion(BigInteger.valueOf(winfoSubscription .getVersion())); watcherinfo.setState("full"); // create watcher list WatcherList watcherList = new WatcherList(); watcherList.setResource(winfoSubscription.getNotifier()); String winfoEventPackage = winfoSubscription.getKey().getEventPackage(); String eventPackage = winfoEventPackage.substring(0, winfoEventPackage .indexOf(".winfo")); watcherList.setPackage(eventPackage); // get watcher subscriptions List resultList = entityManager.createNamedQuery(Subscription.JPA_NAMED_QUERY_SELECT_SUBSCRIPTIONS_FROM_NOTIFIER_AND_EVENTPACKAGE).setParameter( "eventPackage", eventPackage).setParameter("notifier", winfoSubscription.getNotifier()).getResultList(); // add a watcher element for each List<Watcher> watchers = watcherList.getWatcher(); for (Iterator i = resultList.iterator(); i.hasNext();) { Subscription subscription = (Subscription) i.next(); // create and add watcher to watcher info list watchers.add(createWInfoWatcher(subscription)); } // add watcher list to watcher info watcherinfo.getWatcherList().add(watcherList); // marshall and return return marshallWInfo(watcherinfo); } public ContentTypeHeader getWatcherInfoContentHeader() throws ParseException { return sbb.getHeaderFactory().createContentTypeHeader("application", "watcherinfo+xml"); } }