8 Parlay X Presence Web Services

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:

8.1 Introduction

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 the PresenceNotification 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.

8.2 Installing the Web Services

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.

8.3 Configuring Web Services

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.

8.4 Presence Web Services Interface Descriptions

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).


8.5 Using the Presence Web Services Interfaces

This section describes how to use each of the operations in the interfaces, and includes code examples.

8.5.1 Interface: PresenceConsumer, Operation: subscribePresence

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).

8.5.1.1 Code Example

// 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 ("sip.presentity@test.example.com" , pat, "unused", sr);

8.5.2 Interface: PresenceConsumer, Operation: getUserPresence

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.

8.5.2.1 Code Example

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");
    }
  }
}

8.5.3 Interface: PresenceNotification, Operation: statusChanged

This asynchronous operation is called by the Web Service when an attribute for which notifications were requested changes.

8.5.3.1 Code Example

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);
}

8.5.4 Interface: PresenceNotification, Operation: 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.

8.5.4.1 Code Example

public void statusEnd(String context, String correlator) 
System.out.println("statusEnd Called:-");
System.out.println("Context = " + context);
System.out.println("Correlator = " + correlator);
}

8.5.5 Interface: PresenceNotification, Operation: notifySubscription

This asynchronous method notifies the watcher that the presentity handled the pending subscription.

8.5.5.1 Code Example

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());
}
}
}

8.5.6 Interface: PresenceNotification, Operation: subscriptionEnded

This asynchronous operation is called by the Web Service to notify the watcher that the subscription has terminated.

8.5.6.1 Code Example

public void subscriptionEnded(String context, String uri, String reason) {
System.out.println("subscriptionEnded Called:-");
System.out.println("Context = " + context);
System.out.println("Uri = " + uri);
System.out.println("Reason = " + reason);
}

8.5.7 Interface PresenceSupplier, Operation: publish and Oracle Specific "Unpublish"

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.

8.5.7.1 Code Example

// 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);

8.5.8 Interface: PresenceSupplier, Operation: getOpenSubscriptions

This operation retrieves a list of new requests to be on your watcher list.

8.5.8.1 Code Example

List<SubscriptionRequest> srList = getOpenSubscriptions();
for (SubscriptionRequest sr :srList) {
System.out.println(sr.getWatcher() .toString());
}

8.5.9 Interface: PresenceSupplier, Operation: updateSubscriptionAuthorization

This operation allows you to place a watcher on either the block or allow list.

8.5.9.1 Code Example

PresencePermission p = new PresencePermission();
p.setDecision(true);
List<PresencePermission> pp = new ArrayList<PresencePermission>();
p.setPresenceAttribute(PresenceAttributeType.ACTIVITY);
pp.add(p);
updateSubscriptionAuthorization("sip:allow@test.example.com",pp);

8.5.10 Interface: PresenceSupplier, Operation: getMyWatchers

This operation retrieves the list of watchers in your allow list.

8.5.10.1 Code Example

List<String> watchers = getMyWatchers();
 
for(String watcher: watchers){
System.out.println(watcher);
}

8.5.11 Interface: PresenceSupplier, Operation: getSubscribedAttributes

This operation returns only a single item of PresenceTypeAttribute.Activity. An exception is thrown if there is no existing subscription.

8.5.11.1 Code Example

List<PresenceAttributeType> pat = getSubscribedAttributes("sip:watcher@test.example.com");

8.5.12 Interface: PresenceSupplier, Operation: blockSubscription

This operation places a watcher into the block list.

8.5.12.1 Code Example

blockSubscription("sip:block.this.watcher@test.example.com");

8.6 OWLCS Parlay X Presence Custom Error Codes

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.


8.7 Buddy List Manager API

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.

8.7.1 Consuming the API

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;

8.7.1.1 Obtaining the BuddyListManagerFactory

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.

8.7.1.2 Creating a BuddyListManager

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:alice@example.com");
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:alice@example.com. 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.

8.7.1.3 Adding a Buddy to a Buddy List and Retrieving the List

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:bob@example.com");
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 method getVCard() 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.

8.7.1.4 Removing a Buddy from a Buddy List

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.

Example 8-4 Removing a Buddy

URI uri = new URI("sip:bob@example.com");
Buddy bob = manager.createBuddy(uri);
manager.removeBuddy(bob);

8.7.1.5 Manipulating your presence rules document

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:bob@example.com");
manager.blockWatcher("sip:carol@example.com");

8.7.2 Exceptions

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.