Sun Java Solaris Communities My SDN Account Join SDN
 
Article

Getting Started With Composite Capabilities/Preference Profiles and JSR 188

 
By Qusay H. Mahmoud, October 2004  

Web applications accessed from traditional HTML browsers running on desktops make assumptions about such client capabilities as screen size, bandwidth, support for color images, and so on. These assumptions break down when the same content is accessed from mobile devices, whose capabilities are more limited – and varied. The challenge for application developers is to support thousands of mobile devices with widely varying capabilities. Customizing content for different devices, and for different users, requires significant investments of time and effort.

One way to ensure compatibility among the largest set of devices is to settle for the least common denominator, but then users of high-end devices are limited to the capabilities of lower-end devices, and there is little scope for user preferences. The challenge is then: How do you deliver content that reflects users' preferences and the capabilities of their devices without the time and effort of tailoring the code to each platform?

The World Wide Web Consortium (W3C) has finalized the Composite Capabilities/Preference Profiles (CC/PP) standard for representing device capabilities and user preferences. Using CC/PP, you design content once, then use tools to customize and deliver content in formats that specific mobile devices support, and that reflect settings specified by users. As a result, users can access the same application or content from any device, and be confident that it will work on that device, and will accommodate their preferences. This process has become easier for developers of applications based on Java technology since the development within the Java Community Process (JCP) of a standard set of Java APIS for handling CC/PP information, CC/PP Processing (JSR 188).

To give you a fast-track introduction to CC/PP and to JSR 188; this article:

  • Identifies the drawbacks of earlier techniques for determining device capabilities
  • Discusses the CC/PP framework
  • Introduces JSR 188
  • Describes how to download, install, and set up the reference implementation (RI) of JSR 188
  • Demonstrates how to use JSR 188 APIs to query CC/PP profiles
  • Provides a sense of the effort involved in using the APIs
  • Furnishes sample code you can adapt to the needs of your own applications

Legacy Means of Adapting Content to Device Capabilities

In the past, to adapt content for multiple devices, web applications and HTTP servers have conveyed information on device capabilities in HTTP headers. The two widely used approaches are:

  1. User-Agent Request Header: When a web browser sends an HTTP request to an HTTP server, the client identifies itself using a User-Agent string like this example:

    User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; YComp 5.0.0.0)

    An application can examine the User-Agent and select content accordingly. Note, however, that the application adapts content, not based on particular capabilities of the device, but only on its identity; e.g., a cell phone such as the Motorola A760 or a web browser such as Microsoft Internet Explorer 6.0.

  2. Accept Request Headers:To support a particular type of content adaptation called content negotiation, HTTP 1.1 provides four request header fields:
    • Accept: the MIME types accepted by the User-Agent
    • Accept-Charset: the preferred character set
    • Accept-Encoding: the encoding for the User-Agent
    • Accept-Language: the language set

    This sample HTTP request shows how Accept request headers are used:

    GET / HTTP/1.1
    Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, 
      application/vnd.ms-powerpoint, application/vnd.ms-excel, 
      application/msword, */*
    Accept-Language: en-ca
    Accept-Encoding: gzip, deflate
    

    The problem is that browsers may not provide full or correct information. Consider this field from one browser's request header:

    Accept: */*

    This asserts that the browser will accept any media type – which is simply no help from a content adaptation point of view.

Introduction to CC/PP

An application can use the CC/PP framework to discover information about the user's mobile device. CC/PP defines a model for formalizing device profiles – describing device capabilities and user preferences – and a mechanism for sending a profile to the content server along with web page requests: The client's browser adds to the HTTP request a header containing a URL for the device profile. When a content server receives an HTTP request containing a CC/PP reference, it processes the request, follows the URL to the profile, and uses the information it finds there to format content that's suited to the device and to the user's preferences, all automatically.

CC/PP was originally designed to support device independence: when a device's browser requests content, servers and proxies can customize the content to the target device. UAProf, developed by the Open Mobile Alliance (OMA), is a concrete implementation of CC/PP aimed at mobile devices that support the Wireless Application Protocol (WAP).

Today, CC/PP is an industry standard for describing a delivery context, a set of attributes that characterizes the capabilities of the access mechanisms and the preferences of the user. CC/PP represents device capabilities as a two-level hierarchy that consists of attributes grouped into components. Here's a simple example of a list of two components, Hardware Capabilities and Software Capabilities, and their attributes:

  • Hardware Capabilities: vendor, mode, class of devices (mobile phone or PDA), screen size in pixels, colors, memory, CPU, input/output devices, storage
  • Software Capabilities: operating environment, application brand, application version, level of HTML support, supported XML vocabularies, level of CS support, supported scripting languages

In the next example, a simple profile shows data that might be encoded in a CC/PP profile:

Vocabulary = "http://www.wapforum.org/profiles/UAPROF/ccppschema-20010430#"
  Hardware
    ImageCapable = Yes
    InputCharSet = {US-ASCII,ISO-8859-1]
    Model = SomeModelNumber
    ScreenSize = 120x102
    SoftKeysCapable = Yes
    Vendor = SomeVendorName

  Software
    CcppAccept = {application/vnd.wap.wml,image/vnd.wap.wbmp}
    OSVendor = SomeOtherVendorName

  BrowserUA
    BrowserName = SomeBrowserName
    BrowserVersion = 1.1

Vocabularies

One of the first things to note about the sample profile is that it uses a vocabulary, a set of valid component names, valid attribute names, data types of the attributes, and so on. In other words, the vocabulary defines the format and the language used to communicate profile information between senders and receivers. The W3C document CC/PP Structures and Vocabularies defines the structure of profile information as a set of components containing a set of attributes. It's important to note that the CC/PP is independent of any particular vocabulary and therefore doesn't define what components and attributes must be used in a profile. This latitude enables any application to define its own vocabulary. In other words, CC/PP can be extended through the introduction of new vocabularies, and therefore applications that use CC/PP may define different vocabularies tailored to specific application domains.

One important example vocabulary is that of UAProf because the majority of CC/PP-capable devices use UAProf. The UAProf vocabulary has six components:

  • HardwarePlatform contains attributes that describe the hardware characteristics of the terminal, including type of device, model number, display size, input/output methods, and so on.
  • SoftwarePlatform identifies the operating environment of the device.
  • NetworkCharacteristics describes network infrastructure such as bearer information.
  • BrowserUA identifies the device' browser application.
  • WapCharacteristicslists the WAP capabilities of the terminal.
  • PushCharacteristics describes the push specifications of the device, such as maximum size of a push message.

Along with CC/PP and UAProf, W3C recommends the use of the Resource Description Framework (RDF) Schema for defining vocabularies. CC/PP is actually based on RDF, which provides the mechanisms for exchanging modular and interoperable metadata across different resource description communities. RDF itself uses XML for its syntax. Basically, RDF provides a model for describing resources that have properties or attributes and characteristics. RDF Schema is beyond the scope of this article, but you can find more about it in W3C's RDF Vocabulary Description Language 1.0: RDF Schema.

Each vocabulary is associated with an XML namespace. XML namespaces define a notation for associating user-friendly name forms with arbitrary URIs. In CC/PP they're used to create identifying URIs for RDF core elements, CC/PP structural elements, and CC/PP attribute vocabularies. This XML snippet contains three namespace declarations:

<?xml version="1.0"?>
<RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
     xmlns:ccpp="http://www.w3.org/2002/11/08-ccpp-schema#"
     xmlns:prf="http://www.wapforum.org/profiles/UAPROF/ccppschema-20010430#">

The first namespace declaration is for RDF use. The second names the CC/PP structural vocabulary, and the third names a component CC/PP properties vocabulary.

Sample CC/PP Profile

Recall that a CC/PP profile is a description of a device's capabilities and of user preferences that can be used to guide the adaptation of content presented to that device. It contains one or more components, and each component contains one or more attributes. Code Sample 1 shows a sample profile. As you can see, it defines the capabilities of the device as attributes grouped in components:

Code Sample 1: sample-profile.xml

<?xml version="1.0"?>
<rdf:RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
	    xmlns:ccpp="http://www.w3.org/2002/11/08-ccpp-schema#"
		    xmlns:prf="http://www.wapforum.org/profiles/UAPROF/ccppschema-20010430#">
  <rdf:Description rdf:ID="MyDeviceProfile">
    <ccpp:component>
      <rdf:Description rdf:ID="HardwarePlatform">
        <rdf:type
            rdf:resource="http://www.wapforum.org/profiles/UAPROF/ccppschema-20010430#HardwarePlatform"/>
        <prf:BitsPerPixel>2</prf:BitsPerPixel>
        <prf:InputCharSet>
          <rdf:Bag>
            <rdf:li>ISO-8859-1</rdf:li>
          </rdf:Bag>
        </prf:InputCharSet>
      </rdf:Description>
    </ccpp:component>
    <ccpp:component>
      <rdf:Description rdf:ID="SoftwarePlatform">
        <rdf:type 
            rdf:resource="http://www.wapforum.org/profiles/UAPROF/ccppschema-20010430#SoftwarePlatform"/>
        <prf:CcppAccept-Charset>
          <rdf:Bag>
            <rdf:li>US-ASCII</rdf:li>
            <rdf:li>ISO-8859-1</rdf:li>
            <rdf:li>UTF-8</rdf:li>
            <rdf:li>ISO-10646-UCS-2</rdf:li>
          </rdf:Bag>
        </prf:CcppAccept-Charset>
        <prf:CcppAccept-Language>
          <rdf:Seq>
            <rdf:li>en</rdf:li>
            <rdf:li>ja</rdf:li>
          </rdf:Seq>
        </prf:CcppAccept-Language>
      </rdf:Description>
    </ccpp:component>
  </rdf:Description>
</rdf:RDF>

A CC/PP Validation Service is available. You can use it to check CC/PP syntax, but it doesn't do any vocabulary check. Try it on sample-profile.xml.

A server uses the attributes in a CC/PP profile to determine the most appropriate form of a resource to deliver to a client. A client can send a profile to a CC/PP-capable application handler on the server side using the indirect approach: sending a URI representing the default profile from the vendor-specific location. Where the user has defined preferences that aren't in the default profile, the device transmits the preferences inline.

Who Does What?

For CC/PP to work, several parties must participate. The good news is that everything's invisible to users unless they want to transmit preferences not found in the default profile, in which case some user configuration is required. The parties involved:

  • Device vendors are responsible for authoring the reference profile describing the base capabilities of each type of device. In addition, vendors must provide browser support so that applications can attach a CC/PP profile to the HTTP request. Finally, vendors must ensure that all profiles are in valid CC/PP or UAProf syntax.
  • Content authors create text, images, sounds, and other media that can be read, viewed, or heard. The authors are responsible for creating multiple versions of the same content, suited to multiple devices. A widely used approach is to write content in XML and provide XSLT stylesheets that transform content for various delivery contexts.
  • Application developers write the Java code that retrieves different content based on the delivery context. Such applications can be written using JavaServer Pages (JSPs) or servlets.

The Java CC/PP Processing Specification

JSR 188 defines a set of standard APIs for processing information about delivery contexts. The aim is to simplify the developerment of applications for the Java platform by providing standard APIs for processing information on device capabilities and user preferences in CC/PP profiles.


Note: JSR 188 is not intended to compete with J2EE Client Provisioning (JSR 124), which defines a standard for distributing client applications from J2EE environments. In fact, JSR 124 servers can use the CC/PP Processing APIs to identify client devices, and thus provide a flexible implementation that is independent of both the vocabulary and the protocol.

The JSR 188 Reference Implementation

The CC/PP processing APIs are independent of any particular CC/PP processing implementation. Version 1.0 of the RI uses HP's Jena Toolkit as the underlying RDF processor, but the pluggable architecture of the CC/PP Processing API allows you to use any conformant implementation. With the reference implementation, you can build fully functional CC/PP-enabled mobile applications.

You can download the API and RI for free. Then unzip the archive in your favorite directory; you'll get the following subdirectories:

  • api: javadoc APIs
  • doc: documentation
  • lib: JAR files
  • samples: sample application
  • src: Java source files

The samples directory contains a sample parser application, and the lib directory contains these JAR files:

  • ccpp-1_0.jar contains two packages, javax.ccpp and javax.ccpp.uaprof. These in turn contain the APIs that give applications a consistent access mechanism to CC/PP processing implementations.
  • ccpp-ri-1_0.jar contains the implementation classes for the CC/PP processing API.
  • jena-1.4.0.jar: contains the Jena Toolkit classes.
  • rdffilter.jar: contains the RDF filter classes used by the Jena tools.

To use the reference implementation you need the J2SE SDK 1.4.1 or higher, and a Servlet/JSP container such as Sun Java Application Server Edition 8 or Apache Tomcat. For this article I've used Tomcat 4.1, which is the application server that the RI has been tested under.

Setting Up and Running the Sample Application

The samples directory contains a sample parser packaged as a .war file, ccpp-ri-parser-1_0.war. This contains all the necessary libraries, several vocabulary definition files, and JSPs to demonstrate the use of the Java CC/PP Processing API to parse CC/PP documents. To see the parser in action, deploy the .war file into your application server. Using Apache Tomcat, for example:

  1. Start Tomcat.
  2. To deploy the .war file of the sample application, in the browser enter this URL:

    http://localhost:8080/manager/install?path=/ccpp-ri-parser& war=file:///c:/ccpp-1_0/samples/ccpp-ri-parser-1_0.war

    Note that you'll be asked for the server's admin password.
  3. Now you can invoke the sample parser using this URL: http://localhost:8080/ccpp-ri-parser/parse.

If all goes well, you'll see the main page as in Figure 1.

 
Figure 1: The Sample Parser Application in Action
Figure 1: The Sample Parser Application in Action

You can have the application parse the CC/PP profile that already appears in the text area, or supply a new profile or its URL to parse. If you parse the CC/PP profile shown in the text area, you'll see output like Figure 2.

 
Figure 2: Sample Parser Output
Figure 2: Sample Parser Output

As you can see in Figure 1 and others, the sample application includes a vocabulary manager as well as a parser: You can view, add, or remove vocabularies. Figure 3 shows the list of vocabularies that comes with the reference implementation.

 
Figure 3: Vocabularies Supported by the JSR 188 RI
Figure 3: Vocabularies Supported by the JSR 188 RI

You can view any of the vocabularies. Figure 4 shows a snapshot of one.

 
Figure 4: Sample vocabulary
Figure 3: Vocabularies Supported by the JSR 188 RI

Programming With the CC/PP Processing APIs

The JSR 188 reference implementation comprises three packages:

  • com.sun.ccpp provides the DescriptionManager class to configure the CC/PP Processing RI; it is used to manage CC/PP vocabulary description objects.
  • javax.ccpp contains classes and interfaces that enable you to create and access CC/PP profile objects and represent CC/PP components and attributes. Here you'll find the entry point for most applications, the ProfileFactory class.
  • javax.ccpp.uaprof provides classes that represent UAProf attributes and values.

To give you an idea of the modest effort involved in using these classes, Code Sample 2 shows you how an application can use the APIs to query a profile and print its components and attributes. In this example the profile is read from a local file; for a real-world application you can easily modify the code to read the profile from an HTTP request, using ServletContext.getResource().

The ProfileFactory class implements the Abstract Factory design pattern, and is the entry point for most applications. The concrete class must be configured to create Profile objects, easily done using the method ProfileFactory.setInstance(ProfileFactory). If getInstance() is called before the concrete class is configured, it will return a null. The same is true for the ProfileFragmentationFactory class, which you can use to create profiles from input streams, strings, or URLs.

The next step is to configure the vocabulary used in the profile. You can configure multiple vocabularies so that your application can query different profiles that use different vocabularies. This example, however, queries only one: sample-profile.xml, Code Sample 1. To configure vocabularies you use the DescriptionManager class. The CC/PP Processing specification defines an XML schema to represent parent vocabularies and extensions, vocabulary.xsd, which is used to validate CC/PP vocabulary definition files. The schema comes with the reference implementation as part of the sample .war file. Once the schema is set, vocabulary definitions can be added to the system. The example uses this schema, and adds three vocabularies, ccppschema-20010430.xml, ccppschema-20010430a.xml, and ccppschema-20010430b.xml, because these represent the vocabulary defined in sample-profile.xml.

The next step is to construct a Profile object from the CC/PP profile defined in a file, then query the profile to list its components and attributes.

Code Sample 2: QueryProfile.java

import java.io.*;
import java.net.*;
import java.util.*;

import javax.ccpp.*;
import com.sun.ccpp.*;

public class QueryProfile {

   // Construct a Profile object from an XML profile file
   public Profile getProfileFromFile(File ccppFile) throws FileNotFoundException {
      ProfileFactory pf = ProfileFactoryImpl.getInstance();
      //ProfileFactory.setInstance(pf);

      ProfileFragmentFactory ff = ProfileFragmentFactoryImpl.getInstance();
      //ProfileFragmentFactory.setInstance(ff);

      //Configure the vocabulary
      DescriptionManager dm = DescriptionManager.getInstance();
      try {
         // set the schema
         File schema = new File("vocabulary.xsd");
         DescriptionManager.setSchema(schema);

         File vocab = null;
         vocab = new File("ccppschema-20010430.xml");
         dm.addVocabulary(vocab);
         vocab = new File("ccppschema-20010430a.xml");
         dm.addVocabulary(vocab);
         vocab = new File("ccppschema-20010430b.xml");
         dm.addVocabulary(vocab);

      } catch(Exception e) {
         e.printStackTrace();
      }

      // Read the CC/PP profile from a file
      InputStream is = new FileInputStream(ccppFile);
      ProfileFragment pfa[] = new ProfileFragment[1];

      pfa[0] = ff.newProfileFragment(is);
      return pf.newProfile(pfa);
   }

   // Given a profile, list its attribute name/value pairs
   public void processProfile(Profile profile) {
      Set comps = profile.getComponents();
      for(Iterator i = comps.iterator(); i.hasNext(); ) {
         Component comp = (Component) i.next();
         System.out.println("Component: " + comp.getName());

         Set attrs = comp.getAttributes();

         for(Iterator j = attrs.iterator(); j.hasNext(); ) {
            Attribute attr = (Attribute) j.next();
            Object value = attr.getValue();
            System.out.println("\tAttribute: " + attr.getName() + 
			    " = " + attr.getValue());
         }
      }         
   }

   public static void main(String argv[]) throws Exception {
      if(argv.length != 1) {
         System.out.println("Usage: java QueryProfile [profileName.xml]");
         System.exit(0);
      }         

      QueryProfile p = new QueryProfile();
      File f = new File(argv[0]);
      Profile profile = p.getProfileFromFile(f);

      // If the profile is null then something went wrong
      if(profile == null) {
         System.out.println("Null profile");
      } else {
         // Print vocabulary information
         ProfileDescription pd = profile.getDescription();
         System.out.println("Vocabulary: "+pd.getURI());
        
         // process the profile
         p.processProfile(profile);
      }
   }
}

To experiment with this application:

  1. Download and install the JSR 188 API and reference implementation.
  2. Create a directory of your choice – I used SampleApp.
  3. Copy the QueryProfile class in Code Sample 2 and save it as a .java file in the SampleApp directory.
  4. Compile QueryProfile.java using javac. If you don't want to worry about setting the classpath, you can simply copy the JAR files, ccpp-1_0.jar, ccpp-ri-1_0.jar, jena-1.4.0.jar, and rdffilter.jar, from the lib directory of your JSR 188 RI to the jre\lib\ext subdirectory of your J2SDK 1.4 installation.
  5. Copy sample-profile.xml from Code Sample 1 and save it in SampleApp.
  6. From the ccpp-ri-parser-1_0.war file that comes with the JSR 188 RI, extract the vocabulary files ccppschema-20010430.xml, ccppschema-20010430a.xml, and ccppschema-20010430b.xml, and the schema vocabulary.xsd, and save them in SampleApp.

You are now ready to run the QueryProfile application using the standard java interpreter:

java QueryProfile sample-profile.xml

Here's the output you should see:

Vocabulary: http://www.wapforum.org/profiles/UAPROF/ccppschema-20010430#
Component: SoftwarePlatform
        Attribute: CcppAccept-Language = [en, ja]
        Attribute: CcppAccept-Charset = [UTF-8, ISO-8859-1, US-ASCII, ISO-10646-UCS-2]
Component: HardwarePlatform
        Attribute: BitsPerPixel = 2
        Attribute: InputCharSet = [ISO-8859-1]

Note that this output resembles Figure 2 – no surprise, really: The CC/PP profile we have parsed, sample-profile.xml, is the profile that comes with the JSR 188 RI.

Conclusion

The task of developing and delivering device-independent mobile applications is complex primarily because the thousands of different client devices have such widely varying capabilities. The task became easier, however, with the advent of Composite Capabilities/Preference Profiles, a standard for representing device capabilities and user preferences, and of the Java CC/PP Processing specification, a standard set of Java APIs for parsing and querying CC/PP profiles.

This article presented an introduction to the CC/PP and JSR 188 standards, and provided code samples that show how easy it is to use the CC/PP processing APIs.

As you develop CC/PP-capable applications, do keep security in mind. A CC/PP profile may contain sensitive information, and the CC/PP standard itself doesn't address such issues. It is intended to be used in conjunction with appropriate trust and security mechanisms.

For More Information

Acknowledgments

Special thanks to Luu Tran and Kenneth K. Lui of Sun Microsystems, whose feedback helped me improve this article.

About the author

Qusay H. Mahmoud provides Java technology consulting and training services. He has published dozens of Java articles, and is the author of Distributed Programming with Java (Manning Publications, 1999) and Learning Wireless Java (O'Reilly, 2002).

Rate and Review
Tell us what you think of the content of this page.
Excellent   Good   Fair   Poor  
Comments:
Your email address (no reply is possible without an address):
Sun Privacy Policy

Note: We are not able to respond to all submitted comments.