package org.mobicents.slee.sippresence.server.publication; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.sip.address.URI; import javax.sip.header.ContentTypeHeader; import javax.sip.header.Header; import javax.sip.header.HeaderFactory; import javax.slee.ActivityContextInterface; import javax.slee.ChildRelation; import javax.slee.CreateException; import javax.slee.RolledBackContext; import javax.slee.SLEEException; import javax.slee.Sbb; import javax.slee.SbbContext; import javax.slee.TransactionRequiredLocalException; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import net.java.slee.resource.sip.SleeSipProvider; import org.apache.log4j.Logger; import org.mobicents.slee.sipevent.server.publication.ImplementedPublicationControlSbbLocalObject; import org.mobicents.slee.sipevent.server.publication.pojo.ComposedPublication; import org.mobicents.slee.sipevent.server.publication.pojo.Publication; import org.mobicents.slee.sipevent.server.subscription.SubscriptionControlSbbLocalObject; import org.mobicents.slee.sippresence.pojo.pidf.Basic; import org.mobicents.slee.sippresence.pojo.pidf.Presence; import org.mobicents.slee.sippresence.pojo.pidf.Status; import org.mobicents.slee.sippresence.pojo.pidf.Tuple; /** * Publication control implementation child sbb that transforms the sip event * framework in the PUBLISH interface of a SIP Presence Server. * * @author eduardomartins * */ public abstract class PresencePublicationControlSbb implements Sbb, ImplementedPublicationControlSbbLocalObject { private static Logger logger = Logger .getLogger(PresencePublicationControlSbb.class); private final static String[] eventPackages = { "presence" }; /** * SbbObject's sbb context */ private SbbContext sbbContext; /** * SbbObject's context setting */ public void setSbbContext(SbbContext sbbContext) { this.sbbContext = sbbContext; } private HeaderFactory headerFactory; private HeaderFactory getHeaderFactory() throws NamingException { if (headerFactory == null) { headerFactory = ((SleeSipProvider) new InitialContext() .lookup("java:comp/env/slee/resources/jainsip/1.2/provider")) .getHeaderFactory(); } return headerFactory; } public abstract ChildRelation getChildRelation(); public abstract SubscriptionControlSbbLocalObject getChildSbbCMP(); public abstract void setChildSbbCMP(SubscriptionControlSbbLocalObject value); private SubscriptionControlSbbLocalObject getChildSbb() throws TransactionRequiredLocalException, SLEEException, CreateException { SubscriptionControlSbbLocalObject childSbb = getChildSbbCMP(); if (childSbb == null) { childSbb = (SubscriptionControlSbbLocalObject) getChildRelation() .create(); setChildSbbCMP(childSbb); } return childSbb; } public String[] getEventPackages() { return eventPackages; } public void notifySubscribers(ComposedPublication composedPublication) { try { SubscriptionControlSbbLocalObject childSbb = getChildSbb(); ContentTypeHeader contentTypeHeader = (composedPublication .getContentType() == null || composedPublication .getContentSubType() == null) ? null : getHeaderFactory() .createContentTypeHeader( composedPublication.getContentType(), composedPublication.getContentSubType()); if (composedPublication.getDocument() != null && composedPublication.getUnmarshalledContent() == null) { // content needs to unmarshalled StringReader stringReader = new StringReader( composedPublication.getDocument()); composedPublication .setUnmarshalledContent((JAXBElement) getUnmarshaller() .unmarshal(stringReader)); stringReader.close(); } childSbb.notifySubscribers(composedPublication .getComposedPublicationKey().getEntity(), composedPublication.getComposedPublicationKey() .getEventPackage(), composedPublication .getUnmarshalledContent(), contentTypeHeader); } catch (Exception e) { logger.error("failed to notify subscribers for " + composedPublication.getComposedPublicationKey(), e); } } public boolean authorizePublication(String requestEntity, JAXBElement unmarshalledContent) { // returns true if request uri matches entity (stripped from pres: // prefix if found) inside pidf doc String entity = ((JAXBElement<Presence>) unmarshalledContent) .getValue().getEntity(); if (entity != null) { if (entity.startsWith("pres:") && entity.length() > 5) { entity = entity.substring(5); } return entity.equals(requestEntity); } return false; } public boolean acceptsContentType(String eventPackage, ContentTypeHeader contentTypeHeader) { // FIXME return true; } public Header getAcceptsHeader(String eventPackage) { // FIXME if (eventPackage.equals("presence")) { try { return getHeaderFactory().createAcceptHeader("application", "pidf+xml"); } catch (Exception e) { logger.error(e); } } return null; } /* * JAXB context is thread safe */ private static final JAXBContext jaxbContext = initJAXBContext(); private static JAXBContext initJAXBContext() { try { return JAXBContext .newInstance("org.mobicents.slee.sippresence.pojo.pidf" + ":org.mobicents.slee.sippresence.pojo.pidf.oma" + ":org.mobicents.slee.sippresence.pojo.rpid" + ":org.mobicents.slee.sippresence.pojo.datamodel" + ":org.mobicents.slee.sippresence.pojo.commonschema"); } catch (JAXBException e) { logger.error("failed to create jaxb context"); return null; } } public Unmarshaller getUnmarshaller() { try { return jaxbContext.createUnmarshaller(); } catch (JAXBException e) { logger.error("failed to create unmarshaller", e); return null; } } public Marshaller getMarshaller() { try { return jaxbContext.createMarshaller(); } catch (JAXBException e) { logger.error("failed to create unmarshaller", e); return null; } } private static final PresenceCompositionPolicy presenceCompositionPolicy = new PresenceCompositionPolicy(); private JAXBElement unmarshall(String marshalledContent, Unmarshaller unmarshaller) { StringReader stringReader = new StringReader(marshalledContent); JAXBElement jaxbElement = null; try { jaxbElement = (JAXBElement) unmarshaller.unmarshal(stringReader); } catch (JAXBException e) { logger.error("failed to unmarshall presence content", e); } stringReader.close(); return jaxbElement; } private String marshall(Presence presence, Marshaller marshaller) { StringWriter stringWriter = new StringWriter(); String result = null; try { marshaller.marshal(presence, stringWriter); result = stringWriter.toString(); } catch (JAXBException e) { logger.error("failed to marshall presence content", e); } try { stringWriter.close(); } catch (IOException e) { logger.error("failed to close string writer", e); } return result; } public ComposedPublication combinePublication(Publication publication, ComposedPublication composedPublication) { Unmarshaller unmarshaller = null; Marshaller marshaller = null; try { unmarshaller = jaxbContext.createUnmarshaller(); marshaller = jaxbContext.createMarshaller(); } catch (JAXBException e) { logger.error("failed to create unmarshaller", e); return null; } JAXBElement publicationUnmarshalledContent = publication.getUnmarshalledContent(); if (publicationUnmarshalledContent == null) { publicationUnmarshalledContent = unmarshall(publication.getDocument(), unmarshaller); publication.setUnmarshalledContent(publicationUnmarshalledContent); } JAXBElement composedpublicationUnmarshalledContent = composedPublication.getUnmarshalledContent(); if (composedpublicationUnmarshalledContent == null) { composedpublicationUnmarshalledContent = unmarshall(composedPublication.getDocument(), unmarshaller); } if (publicationUnmarshalledContent != null && composedpublicationUnmarshalledContent != null) { Presence composedPresence = presenceCompositionPolicy.compose((Presence)publicationUnmarshalledContent.getValue(), (Presence)composedpublicationUnmarshalledContent.getValue()); composedpublicationUnmarshalledContent.setValue(composedPresence); composedPublication.setUnmarshalledContent(composedpublicationUnmarshalledContent); composedPublication.setDocument(marshall(composedPresence, marshaller)); } return composedPublication; } public Publication getAlternativeValueForExpiredPublication( Publication publication) { JAXBElement element = publication.getUnmarshalledContent(); if (element == null) { StringReader stringReader = new StringReader(publication .getDocument()); try { element = (JAXBElement) getUnmarshaller().unmarshal( stringReader); } catch (Exception e) { logger.error("failed to unmarshall publication", e); return null; } finally { stringReader.close(); } publication.setUnmarshalledContent(element); } if (element.getValue() instanceof Presence) { Presence presence = (Presence) element.getValue(); for (Tuple tuple : presence.getTuple()) { tuple.getAny().clear(); tuple.getNote().clear(); tuple.setTimestamp(null); Status status = new Status(); status.setBasic(Basic.CLOSED); tuple.setStatus(status); } presence.getAny().clear(); presence.getNote().clear(); // marshall new content StringWriter stringWriter = new StringWriter(); try { getMarshaller().marshal(element, stringWriter); publication.setDocument(stringWriter.toString()); } catch (Exception e) { logger.error("failed to marshall alternative publication", e); return null; } finally { try { stringWriter.close(); } catch (IOException e) { // ignore } } return publication; } else { return null; } } public boolean isResponsibleForResource(URI uri) { return true; } // ----------- SBB OBJECT's LIFE CYCLE public void sbbActivate() { } public void sbbCreate() throws CreateException { } public void sbbExceptionThrown(Exception arg0, Object arg1, ActivityContextInterface arg2) { } public void sbbLoad() { } public void sbbPassivate() { } public void sbbPostCreate() throws CreateException { } public void sbbRemove() { } public void sbbRolledBack(RolledBackContext arg0) { } public void sbbStore() { } public void unsetSbbContext() { this.sbbContext = null; } }