This chapter describes support for the Parlay X 2.0 Presence Web services interfaces for developing applications. The Web service functions as a Presence Network Agent which can publish, subscribe, and listen for notifications on behalf of the users of the Web service. This chapter contains the following sections:
OWLCS provides support for Part 14 of the Parlay X Presence Web Service as defined in the Open Service Access, Parlay X Presence Web Services, Part 14, Presence ETSI ES 202 391-14 specification. The OWLCS Parlay X Web service maps the Parlay X Web service to a SIP/IMS network according to the Open Service Access, Mapping of Parlay X Presence Web Services to Parlay/OSA APIs, Part 14, Presence Mapping, Subpart 2, Mapping to SIP/IMS Networks, ETSI TR 102 397-14-2 specification.
Note:
Due to the synchronous nature of the Web service, to receive a callback from the Web service the client must implement the Web service callback interface. For presence, the required interface is thePresenceNotification
interface described in Open Service Access, Parlay X Presence Web Services, Part 14, Presence ETSI ES 202 391-14.The HTTP server that hosts the presence Web service is a Presence Network Agent or a Parlay X to SIP gateway.
The Web services are packaged as a standard .ear file and can be deployed the same as any other Web services through Admin Console. The .ear file contains two .war files that implement the two interfaces. The Web services use the Oracle SDP Platform, Client and Presence Commons shared libraries.
The following four mbean attributes are configurable for the Presence Supplier Web service:
SIPOutboundProxy: SipURI of the outbound proxy for SIP message. Empty string means no outbound proxy. For example, sip:127.0.0.1:5060; lr;transport=tcp.
PublicXCAPRootUrl: URI where the Presence Server is deployed. This attribute is used to update the presence rules stored on the XDMS. Example: http://127.0.0.1:8001/services/
Expires: Set the time in seconds after which the PUBLISH by a presentity expires. Default value is 3600 (that is, 1 hour).
SessionTimeout: Set the time in seconds after which HTTP sessions times out. Data for all timed out sessions is discarded.
For Presence Consumer, there are three mbean attributes that can be configured.
SIPOutboundProxy: SipURI of the outbound proxy for SIP message. Empty string means no outbound proxy. For example, sip:127.0.0.1:5060; lr;transport=tcp.
Expires: Set the time in seconds after which the SUBSCRIBE by a watcher expires. Default value is 3600 (ie. 1 hour).
SessionTimeout: Set the time in seconds after which HTTP sessions times out. Data for all timed out sessions is discarded.
The presence Web services consist of three interfaces:
PresenceConsumer: The watchers use these methods to obtain presence data (Table 8-1).
PresenceNotification: The presence consumer interface uses the client callback defined in this interface to send notifications (Table 8-2).
PresenceSupplier: The presentity uses these methods to publish presence data and manage access to the data by its watchers (Table 8-3).
Table 8-1 PresenceConsumer Interface
Operation | Description |
---|---|
subscribePresence |
The Web Service sends a SUBSCRIBE to the presence server. |
getUserPresence |
Returns the cached presence status because the status changes of the presentity are asynchronously sent to the Web services through a SIP NOTIFY. The Web services actually have the subscription, not the Web services client. |
startPresenceNotification |
Enables the Web service client from receiving asynchronous notifications whenever a presentity makes change to its presence status, or presence rules document. |
endPresenceNotification |
Disables the web service client to receive asynchronous notifications. |
Table 8-2 PresenceNotification Interface
Operation | Description |
---|---|
statusChanged |
The asynchronous operation is called by the Web Service when an attribute for which notifications were requested changes. |
statusEnd |
This method is called when the duration for the notifications (identified by the correlator) is over. In case of an error or explicit call to endPresenceNotification, this method is not called. |
notifySubscription |
This asynchronous method notifies the watcher that the presentity handled the pending subscription. |
subscriptionEnded |
This asynchronous operation is called by the Web Service to notify the watcher that the subscription has terminated. |
Table 8-3 PresenceSupplier Interface
Operation | Description |
---|---|
publish |
Maps directly to a SIP PUBLISH. |
getOpenSubscriptions |
Called by the presentity (supplier) to check if any watcher wants to subscribe to its presence data. No SIP message maps to this method. Returns pending subscriptions currently in the Web service server. |
updateSubscriptionAuthorization |
The supplier uses this method to answer any open pending subscriptions. An XCAP PUT message is sent to the XDMS server to update the presence-rule document. |
getMyWatchers |
Retrieves the local list of watchers from the Web service server. |
getSubscribedAttributes |
Retrieves the local list of subscribed attributes from the Web service server. Currently, only returns Activity. |
blockSubscription |
Causes the Web service server to end a watcher subscription by modifying the XCAP document on the XDMS server (that is, putting the watcher on the block list). |
This section describes how to use each of the operations in the interfaces, and includes code examples.
This is the first operation the application must call before using another operation in this interface. It serves two purposes:
It allows the Web services to associate the current HTTP session with a user.
It provides a context for all the other operations in this interface by subscribing to at least one presentity (SUBSCRIBE presence event).
// Setting the attribute to activity PresenceAttributeType pa = PresenceAttributeType.ACTIVITY; List<PresenceAttributeType> pat = new ArrayList<PresenceAttributeType>(); pat.add(pa); SimpleReference sr = new SimpleReference(); sr.setCorrelator(""); sr.setInterfaceName(""); sr.setEndpoint(""); consumer.subscribePresence ("[email protected]" , pat, "unused", sr);
Call this operation to retrieve a subscribed presentity presence. If the person is offline, it returns ActivityNone
and the hardstate note is written to PresenceAttribute.note
. If it returns Activity_Other
, the description of the activity is returned in the OtherValue
field.
If the Name
field is equal to "ServiceAndDeviceNote", OtherValue
is a combination of the service note and the device note. Note that there can be more than one "ServiceAndDeviceNote" when the presentity is logged into multiple clients.
PresenceAttributeType pat = PresenceAttributeType.ACTIVITY; List<PresenceAttribute> result = consumer.getUserPresence(presentity, pat); for (PresenceAttribute pa : result) { // Check to see if it is an activity type. if (pa.getTypeAndValue().getUnionElement() == PresenceAttributeType.ACTIVITY){ // Get the presence status. System.out.println("ACTIVITY: " + pa.getTypeAndValue().getActivity().toString()); // Get the customized presence note. if (pa.getNote().length() > 0){ System.out.println("Note: " + pa.getNote()); } } // If this is of type OTHER, then we need to extract // different type of information. if (pa.getTypeAndValue().getUnionElement() == PresenceAttributeType.OTHER){ // This is "Activity_Other", a custom presence status. if (pa.getTypeAndValue().getOther() .getName().compareToIgnoreCase("ACTIVITY_OTHER") == 0){ System.out.println("Other Activity->" + pa.getTypeAndValue().getOther().getValue() + "\n"); } else { // Currently, the only other value beside ACTIVITY_OTHER is // "ServiceAndDeviceNote" which is the service note + // device note. System.out.println("Combined Note->" + pa.getTypeAndValue().getOther().getValue() + "\n"); } } }
This asynchronous operation is called by the Web Service when an attribute for which notifications were requested changes.
public void statusChanged(String context, String correlator, String uri, List<PresenceAttribute> presenceAttributes) { System.out.println("statusChanged Called:-"); System.out.println("Context = " + context); System.out.println("Correlator = " + correlator); System.out.println("Presentity = " + uri); }
This method is called when the duration for the notifications (identified by the correlator) is over. In case of an error or explicit call to endPresenceNotification, this method is not called.
This asynchronous method notifies the watcher that the presentity handled the pending subscription.
public void notifySubscription(String context, String uri, List<PresencePermission> presencePermissions) { System.out.println("notifySubscription Called:-"); System.out.println("Context = " + context); System.out.println("Uri = " + uri); if (presencePermissions.size() > 0){ for (PresencePermission p:presencePermissions){ System.out.println("Permission " + p.getPresenceAttribute().value() + "->" + p.isDecision()); } } }
This asynchronous operation is called by the Web Service to notify the watcher that the subscription has terminated.
This is the first operation the application must call before using another operation in this interface. It serves three purposes:
It allows the Web services to associate the current HTTP session with a user.
It publishes the user's presence status.
It subscribes to watcher-info so that the Web services can keep track of any watcher requests.
There are three attributes that are of interest when performing a PUBLISH. These attributes can be set in a PresenceAttribute structure and passed into the PUBLISH method.
Presense status with a customized note: this is the customized note configured in the My Presence text box in Oracle Communicator. The <note> element is contained in the <person> element of the Presence Information Data Format (PIDF) XML file.
Device note: implicitly inserted by Oracle Communicator, or inserted from a Web service. The <note> element is contained in the <device> element of the Presence Information Data Format (PIDF) XML file.
Service note: configured in the Presence tab in the Oracle Communicator preferences. The <note> element is contained in the <tuple> element of the Presence Information Data Format (PIDF) XML file.
// A simple way to publish the Presence Status PresenceAttribute pa = new PresenceAttribute(); OtherValue other = new OtherValue(); //Set the name to "DeviceNote" to indicate the value must be used as device note. other.setName("DeviceNote"); other.setValue("Device Name"); //More other values can be defined for ServiceNote etc CommunicationValue comm = new CommunicationValue(); AttributeTypeAndValue typeValue = new AttributeTypeAndValue(); typeValue.setUnionElement(PresenceAttributeType.ACTIVITY); typeValue.setActivity(activity); typeValue.setPlace(PlaceValue.PLACE_NONE); typeValue.setPrivacy(PrivacyValue.PRIVACY_NONE); typeValue.setSphere(SphereValue.SPHERE_NONE); typeValue.setCommunication(comm); typeValue.setOther(other); pa.setTypeAndValue(typeValue); String note = "My Note"; pa.setNote(note); XMLGregorianCalendar dateTime = null; dateTime = DatatypeFactory.newInstance().newXMLGregorianCalendar(new GregorianCalendar()); pa.setLastChange(dateTime); List<PresenceAttribute> pat = new ArrayList<PresenceAttribute>(); pat.add(pa); supplier.publish(pat); //To UNPUBLISH,set the OtherValue to (Expires, 0) OtherValue other = new OtherValue(); other.setName("Expires"); other.setValue(0);
This operation retrieves a list of new requests to be on your watcher list.
This operation allows you to place a watcher on either the block or allow list.
PresencePermission p = new PresencePermission(); p.setDecision(true); List<PresencePermission> pp = new ArrayList<PresencePermission>(); p.setPresenceAttribute(PresenceAttributeType.ACTIVITY); pp.add(p); updateSubscriptionAuthorization("sip:[email protected]",pp);
This operation retrieves the list of watchers in your allow list.
This operation returns only a single item of PresenceTypeAttribute.Activity. An exception is thrown if there is no existing subscription.
List<PresenceAttributeType> pat = getSubscribedAttributes("sip:[email protected]");
Table 8-4 and Table 8-5 describe the error codes and their associated error message.
Table 8-4 OWLCS Parlay X Presence Custom Error Codes: PolicyException
Error Code | Error Message |
---|---|
POL0001 |
General Policy Exception. It can be of following types: SDP20201 Watcher is on the block, polite-block or pending list. SDP20202 Subscription is pending. |
POL0002 |
Privacy verification failed for address <address>, request is refused. |
POL0003 |
Too many addresses specified in message part. |
Table 8-5 OWLCS Parlay X Presence Custom Error Codes: ServiceException
Error Code | Error Message |
---|---|
SVC0001 |
General Service Exception. It can be of the following types: SDP20101 Invalid result from XDMS server. SDP20102 Invalid HTTP session data. SDP20103 Invalid uri. SDP20104 Peer unavaliable. SDP20105 Unknown host. SDP20106 Service not avaliable. SDP20107 Internal error. SDP20108 User unauthenticated. |
SVC0002 |
Invalid input value for message part. |
SVC0003 |
Invalid input value for message part, valid values are <values>. |
SVC0004 |
No valid addresses provided in message part. |
SVC0005 |
Correlator <correlator> specified in message part is a duplicate |
SVC0220 |
No subscription request from watcher <watcher> for attribute <attribute>. |
SVC0221 |
<watcher> is not a watcher. |
The Contact Management API (CMAPI) is an API for manipulating resource-lists (also known as Buddy Lists) and presence-rules documents. Through this high-level API it is possible to act on behalf of a user to add or remove buddies to the buddy list as well as allowing or blocking other users (watchers) from seeing the user's presence information. The CMAPI is capable of querying and manipulating those resources stored on the XDMS (XML Document Management Server). The CMAPI consists of a web service: XML Document Management Client (XDMC) Service and a Java client stub that is part of the oracle.sdp.client
shared library.
The CMAPI is part of the oracle.sdp.client shared library. Once this library is available, developers can import the package and use the API:
import oracle.sdp.presence.integration.Buddy; import oracle.sdp.presence.integration.BuddyListManager; import oracle.sdp.presence.integration.BuddyListManagerFactory; import oracle.sdp.presence.integrationimpl.BuddyListManagerImpl;
The BuddyListManagerFactory itself follows the singleton pattern, and there is only one instance of a factory per XDMS/XDMC combination. That is, when creating a BuddyListManagerFactory, you must supply the XCAP root URL to the XDMS from where documents are downloaded, as well as supplying the URL to the XDM Client Service that is running on the client side; the XDMC Service URL is passed in through the BindingProvider.ENDPOINT_ADDRESS_PROPERTY property. For each such combination of XCAP root URL and XDM Client Service endpoint, there can only exist exactly one BuddyListManagerFactory instance. Therefore it is possible to create different factories pointing to the different XDMS/XDMC Service combinations.
Example 8-1 Obtaining an instance of the BuddyListManagerFactory
// Create the URI pointing to the XDMS. URI xcapRoot = new URI("http://localhost:8001/services"); // Location of where the XDM Client webservice is. String wsUrl = "http://localhost:8001/XdmClientService/services/XdmClient"; String sWsSecurityPolicy = new String[]{"oracle/wss11_saml_token_with_message_protection_client_policy"}; Map<String, Object> params = new HashMap<String,Object>(); params.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, wsUrl); params.put(BindingProvider.USERNAME_PROPERTY, "alice"); params.put(ParlayXConstants.POLICIES, sWsSecurityPolicy); // Obtain the instance to the factory BuddyListManagerFactory factory = BuddyListManagerFactory.getInstance(xcapRoot, params);
Example 8-1 shows how to obtain a reference to a factory pointing to the XCAP root of localhost:8001/
services. Every operation performed on this factory is in the context of this particular XCAP root. Hence, when creating a BuddyListManager for a particular user, that BuddyListManager's XCAP root is the one of the factory through which it was created.
It is important to realize that a BuddyListManager (BLM) is acting on behalf of a particular user. Therefore, if a BLM is created for user Alice, all operations performed on that particular BLM are on behalf of Alice and manipulate her documents. Example 8-2 shows how to create a BLM for Alice through the factory created in the previous section.
Example 8-2 Obtaining a BuddyListManager for the user Alice
URI user = new URI("sip:[email protected]"); Map<String, Object> params = new HashMap<String,Object>(); params.put(XDMClientFactory.PROP_ASSERTED_IDENTITY, assertedId); BuddyListManager manager = factory.createBuddyListManager(user, params);
Example 8-2 shows how to create a BLM for the user Alice with SIP address of sip:[email protected]. If manipulation of the buddy list and presence rules document of another user is required, then a separate BLM must be created with the appropriate SIP address.
Adding a buddy to a buddy list is done by first creating a buddy, setting the information needed on that buddy and then using the BLM to add it to the buddy list. Example 8-3 shows how to use the BLM representing Alice to add Bob as a new buddy of Alice and then getting the updated list back.
Example 8-3 Adding a New Buddy to the Buddy List of Alice
URI uri = new URI("sip:[email protected]"); Buddy bob = manager.createBuddy(uri); // Optionally, setting additional information. manager.setDisplayname("Bobby"); VCard vcard = bob.getVCard(); vcard.setCity("San Francisco"); vcard.setCountry("USA"); // very important to set the VCard back on the buddy again bob.setVCard(vcard); // Update the buddy info using the BLM manager.updateBuddy(bob); // Getting the updated buddy list List<Buddy> buddies = manager.getBuddies();
Example 8-3 shows how to create a new Buddy, Bob, and how that buddy is added to Alice's buddy list by using the BLM representing Alice. To add more information about the user Bob, such as the address and other information, access Bob's Vcard information and then set the appropriate properties.
Note:
Since the methodgetVCard()
is actually returning a clone of the VCard, the method setVCard()
must be called on the buddy again in order for the information to be updated.Removing a buddy is very similar to adding a buddy. Use the method removeBuddy
and pass in the buddy that is to be removed. If there are many buddies to remove, use the removeBuddies
method and pass in the list of buddies to remove. Example 8-4 shows how Bob is removed from Alice's buddy list.
URI uri = new URI("sip:[email protected]"); Buddy bob = manager.createBuddy(uri); manager.removeBuddy(bob);
To allow a watcher to view the presence status, use the method allowWatcher
(String watcher)
to add the watcher to the allow list. Use blockWatcher
(String watcher)
to block someone from viewing your presence status.
Example 8-5 Allowing or blocking watchers
manager.allowWatcher("sip:[email protected]"); manager.blockWatcher("sip:[email protected]");
BuddyListException
is the base exception, and if the program is not set to register the specific exception, then it can simply catch it.
XDMException
is the base exception for all exceptions concerning communication with the remote XDMS. XDMException
signals that an error occurred when communicating with the XDMS (for example: a connection problem, wrong path to the XCAP root, or something else).
DocumentConflictException
is a subclass to the XDMException; it signals that a mid-air conflict was detected that could not be resolved. This can occur when multiple clients access the same document on the XDMS. BuddyListManager
attempts to resolve such a clash, but if it cannot, it throws an exception.