WAP 1.2.1 (June 2000 release) introduced a new way to determine handset
capabilities. The standard of User Agent Profile (UAProf) has been
around for a while, yet few have implemented systems that take advantage
the facilities it provides. In this article, I will introduce a software
component called DELI and how to use it to extract information from
UAProf.
UAProf In a nutshell, UAProf is a RDF (resource description
framework) document consisting of components and each component has a
number of attributes. ( For more on what exactly an RDF is check out the
RDF Primer from the W3C at http://www.w3.org/TR/rdf-primer/).
Each attribute has a distinct name and has an associated collection
type and attribute type. UAProf also has a vocabulary system within
components to enable common attribute names throughout the UAProf
implementations for WAP 1.2.1 (or above) devices. The UAProf of a
device can be verifies against the schemas provided by WAP Forum. Three of
such schemas exist and the latest version is available here (http://www.wapforum.org/profiles/UAPROF/ccppschema-20020710). Please
note also the UAProf component can be extended for other device
capabilities. MmsCharacteristics is a good example of schema that is not
in WAP Forum's UAProf list. The following are some URLs that point to the
location of real UAProf documents:
At the end of the day, these RDF documents are simply XML. You can, if
you choose, use your favorite tools and environments to parse the XML and
get at the data you need. However, rather than reinvent the wheel here and
build our own XML parser for UAProf from scratch, we will instead turn to
the Open Source community and leverage
DELI DELI it is an open source project available from http://delicon.sourceforge.net/
that that allows Java servlets to resolve HTTP requests containing
delivery context information from CC/PP or UAProf capable devices and
query the resolved profile. It also provides support for legacy devices so
that the proprietary delivery context descriptions currently used by
applications can be replaced by standardised CC/PP descriptions. Once DELI
is enabled in your application. It will automatically determine the best
set of UAProf attributes to use and make them available to your
system. If DELI cannot find the HTTP header "x-wap-profile" or
"profile" then it will look up its legacy database using the user agent
string sent by the request. This database basically is a number of
known UAProf documents stored as individual files (which makes updating
easy).
The following example shows how to make use the attribute "ScreenSize"
in order to select a picture that is suitable for the device's screen
width. The example uses images with dimension of 120x120, 101x101,
144x144 and 80x80 (default) and makes use of DELI version 0.7.0. In
order to avoid the need to recompile DELI, the the example servlet has
been included to be used in the ccpp folder as a bit of a hack, but works
fine with Apache Tomcat.
In examining the doGet method of the code, the work of obtaining and
parsing the UAProf is all done in one simple call to the constructor of
the Profile class (part of the Deli Package). Profile deviceProfile = new Profile(req);
The constructor simply takes the
HTTP request, parses it, matches it against the local library of RDFs or
fetched the RDF referenced in the UAProf HTTP Header if not stored
locally. Once we have the profile loaded we check the BrowserName to determine
if we really have a wireless device accessing the site or something like InternetExplorer
or Mozilla with a call to ProfileAttribute bn= deviceProfile.getAttribute("BrowserName")
Once we have decided that the browser is a wireless deivce we then use the
created Profile object in the selectPict method where we call ProfileAttribute ss = theProfile.getAttribute("ScreenSize");
The ProfileAttribute (another Deli class) is a vector created with the
value of the ScreenSize attribute from the RDF file, which in its raw form
looks like: <prf:ScreenSize>120x160</prf:ScreenSize>
Based on this vector, we can select the appropriate image to deliver to
the handset, and use this image in our WML deck. Clearly, this is a very
simple use of UAProf, and only represents the surface of what can be done
with the information available. The sample code below is available for
download as a zip file here, and also can be viewed in its deployed form
at http://demo.openwave.com/uaprof
import java.io.*;
import java.util.*;
import java.net.*;
import javax.servlet.*;
import javax.servlet.http.*;
import com.hp.hpl.deli.*;
public class ScreenRes extends HttpServlet
{
Workspace workspace;
protected ServletContext servletContext;
public void init(ServletConfig config) throws ServletException
{
super.init(config);
servletContext = config.getServletContext();
try
{
Workspace.getInstance().configure(servletContext, "config/deliConfig.xml");
}
catch (Exception e)
{
System.out.println(e.toString());
}
}
public void printWML(Profile theProfile, PrintWriter out)
{
StringWriter outstr = new StringWriter();
String inlineImg=selectPict(theProfile);
ProfileAttribute ssAttr = theProfile.getAttribute("ScreenSize");
String screenSize = ssAttr.getValue().toString();
String ss= screenSize.substring(1,screenSize.length()-1);
ProfileAttribute bnAttr = theProfile.getAttribute("BrowserName");
String browserName = bnAttr.getValue().toString();
String bn= browserName.substring(1,browserName.length()-1);
outstr.write("<?xml version=\"1.0\"?>\n");
outstr.write("<!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\" \"http://www.wapforum.org/DTD/wml_1.1.xml\">\n");
outstr.write("<wml>\n");
outstr.write("<card id=\"pict\">\n");
outstr.write("<p>"+"<img src=/ccpp/\"" +inlineImg +"\" alt=\"wait...\"/></p>");
outstr.write("<p>The browser name is "+bn +"</p>"+"\n");
outstr.write("<p>Screen Size of this device is "+ss +"</p>"+"\n");
outstr.write("</card>\n");
outstr.write("</wml>\n");
String str = outstr.getBuffer().toString();
out.print(str);
}
public void printHTML(Profile theProfile, PrintWriter out)
{
String inlineImg=selectPict(theProfile);
ProfileAttribute bnAttr = theProfile.getAttribute("BrowserName");
String browserName = bnAttr.getValue().toString();
String bn= browserName.substring(1,browserName.length()-1);
out.println("<HTML>\n<HEAD><TITLE>UAProf Example</TITLE></HEAD>\n");
out.println("<BODY><H1>UAProf Example</H1>");
out.println("<P> The Browser Name is:"+ bn);
out.println("<P><img src=/ccpp/\"" +inlineImg +"\" alt=\"wait...\"/></P>");
out.println();
out.println("</BODY></HTML>");
}
private String selectPict(Profile theProfile)
{
String imageName="image/pictDefault.jpg";
ProfileAttribute ss = theProfile.getAttribute("ScreenSize");
if (ss!=null)
{
String ssAttrValue = ss.getValue().toString();
String ScreenSize= ssAttrValue.substring(1,ssAttrValue.length()-1);
if (ScreenSize.startsWith("120"))
{
imageName="image/pict120.jpg";
}else if (ScreenSize.startsWith("101"))
{
imageName="image/pict101.jpg";
}else if (ScreenSize.startsWith("144"))
{
imageName="image/pict144.jpg";
}
}
return imageName;
}
public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
{
PrintWriter out = res.getWriter();
Profile deviceProfile = new Profile(req);
ProfileAttribute bn= deviceProfile.getAttribute("BrowserName");
if (bn!=null)
{
String bnValue=bn.getValue().toString();
String BrowserName= bnValue.substring(1,bnValue.length()-1);
if (BrowserName.equals("Microsoft")||BrowserName.equals("Mozilla"))
{
res.setContentType("text/html");
printHTML(deviceProfile, out);
}else
{
res.setContentType("text/vnd.wap.wml");
printWML(deviceProfile, out);
}
}
res = UAProfCreateHttpResponse.addWarningHeader(res, UAProfCreateHttpResponse.CONTENT_GENERATION_APPLIED);
}
}
Installing the example:
Download and install DELI 0.7.0. (do not use 0.8.0)
Copy the image folder to the ccpp folder of DELI
Add a folder called "classes" in the WEB-INF folder.
Copy the ScreenRes.class file there.
Add a servlet mapping to the web.xml file (example included).
It is not very exciting to access this servlet with a standard HTML
browser such as Netscape or IE, but you should use the 6.2 SDK, or
any device that actually supports UAProf.
To use DELI in your servlets, you will need to initialise in the
HttpServlet's init method (full details in DELI user doc). The UAProf
attribute is stored in standard Java vectors but you can also access the
value directly.
For
example: System.out.println(myProfile.getAttribute("BrowserName").toString());