ovidiu 02/01/09 14:20:42 Modified: src/documentation/xdocs/developing book.xml src/java/org/apache/cocoon cocoon.roles src/java/org/apache/cocoon/transformation TraxTransformer.java src/webapp cocoon.xconf sitemap.xmap src/webapp/docs/samples samples.xml Added: src/documentation/xdocs/developing deli.xml deliquick.xml src/java/org/apache/cocoon/components/deli Deli.java DeliImpl.java src/webapp deliCocoonConfig.xml legacyDevice.xml src/webapp/stylesheets deli_test.xsl Log: Added support for Deli, a CC/PP and UAProf support library by Mark Butler <[EMAIL PROTECTED]>. Revision Changes Path 1.2 +2 -0 xml-cocoon2/src/documentation/xdocs/developing/book.xml Index: book.xml =================================================================== RCS file: /home/cvs/xml-cocoon2/src/documentation/xdocs/developing/book.xml,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- book.xml 3 Jan 2002 12:31:02 -0000 1.1 +++ book.xml 9 Jan 2002 22:20:42 -0000 1.2 @@ -15,6 +15,8 @@ <menu-item label="Avalon" href="avalon.html"/> <menu-item label="Using Databases" href="datasources.html"/> <menu-item label="Parent CM" href="parent-component-manager.html"/> + <menu-item label="Deli quick start" href="deliquick.html"/> + <menu-item label="CC/PP and UAProf" href="deli.html"/> </menu> <menu label="Java"> 1.1 xml-cocoon2/src/documentation/xdocs/developing/deli.xml Index: deli.xml =================================================================== <?xml version="1.0" encoding="UTF-8"?> <!-- edited with XML Spy v3.0.7 NT (http://www.xmlspy.com) by Mark Butler (Hewlett-Packard Laboratories UK) --> <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.0//EN" "dtd/document-v10.dtd"> <document> <header> <title>DELI: A Delivery Context Library for CC/PP and UAProf</title> <authors> <person name="Mark H. Butler" email="[EMAIL PROTECTED]"/> </authors> </header> <body> <s1 title="Introduction"> <p>In order for a web server to provide optimized content to different clients it requires a description of the capabilities of the client. Two new compatible standards have been created for describing delivery context based on the <link href="http://www.w3.org/RDF/">Resource Description Framework (RDF)</link>: <link href="http://www.w3.org/Mobile/CCPP/">Composite Capabilities / Preferences Profile (CC/PP)</link> created by the <link href="http://www.w3.org">W3C</link> and <link href="http://www1.wapforum.org/tech/terms.asp?doc=WAP-248-UAProf-20010530-p.pdf">User Agent Profile (UAProf)</link> created by the <link href="http://www.wapforum.org">WAP Forum</link>. These standards allow the efficient transmission of delivery context information to the server even via low bandwidth wireless networks. Instead of sending an entire profile with every request, a client only sends a reference to a profile, stored on a third device known as a profile repository, along with a list of differences specific to this particular client. The process of reassembling the final profile from the profile references and differences is known as profile resolution.</p> <p><link href="http://www-uk.hpl.hp.com/">HP Labs</link> has produced an open-source library called DELI that allows Java servlets to resolve HTTP requests containing CC/PP or UAProf information and query the resolved profile. This document describes how DELI may be used within Apache Cocoon. For more information on the DELI library please refer to the <link href="http://www-uk.hpl.hp.com/people/marbut/">DELI web-site</link>. DELI currently uses <link href="http://www.hpl.hp.com/semweb/jena-top.html">Jena</link>, an RDF Framework developed at HP Labs. For more details of Jena see Brian McBride's <link href="http://www-uk.hpl.hp.com/people/bwm/papers/20001221-paper/">paper</link> and the HP Labs <link href="http://www.hpl.hp.com/semweb/">Semantic Web activity</link> homepage.</p> </s1> <s1 title="CC/PP"> <p>CC/PP is described in <link href="http://www.w3.org/TR/CCPP-struct-vocab/">CC/PP Structure and Vocabularies</link>, <link href="http://www.w3.org/TR/2000/WD-CCPP-ra-20000721/">CC/PP Requirements and Architecture</link> and <link href="http://www.w3.org/TR/2000/WD-CCPP-ta-20000721/">CC/PP Terminology and Abbreviations</link>. A CC/PP profile is broadly constructed as a two level hierarchy: a profile has a number of components and each component has a number of attributes. A proposed (and largely deprecated) protocol for CC/PP is described in <link href="http://www.w3.org/TR/NOTE-CCPPexchange">CC/PP exchange protocol using HTTP extension framework</link> and <link href="http://search.ietf.org/internet-drafts/drafts-hjelm-http-cnhttp-scenarios-00.txt">Content Negotiation Header in HTTP Scenarios</link>. The protocol work has been deprecated because the CC/PP Working Group was not chartered by the W3C to do protocol work. In addition this protocol uses <link href="http://www.w3.org/Protocols/HTTP/ietf-http-ext/">HTTP-ex</link> which means it is incompatible with existing HTTP web servers. Therefore it is suggested that people requiring CC/PP functionality should use the W-HTTP protocol used by UAProf. This has identical functionality to the deprecated CC/PP protocol based on HTTP-ex, but will work with existing HTTP servers. Hopefully when the CC/PP Working Group is recharted to work on protocols, it will propose a protocol compatible with HTTP/1.1 similar to W-HTTP.</p> </s1> <s1 title="UAProf"> <p>The UAProf specification is based on the CC/PP specification. Like CC/PP, a UAProf profile is a two level hierarchy composed of components and attributes. Unlike CC/PP, the UAProf specification also proposes a vocabulary - a specific set of components and attributes - to describe the next generation of WAP phones. The specification also describes two protocols for transmitting the profile from the client to the server. Currently DELI only supports one of the UAProf protocols, as the other is based on HTTP-ex so is incompatible with existing web servers. </p> <p>Profiles using the UAProf vocabulary consist of six components: HardwarePlatform, SoftwarePlatform, NetworkCharacteristics, BrowserUA, WapCharacteristics and PushCharacteristics. These components contain attributes. In DELI each attribute has a distinct name and has an associated collection type, attribute type and resolution rule. In UAProf there are three collection types:</p> <ul> <li><code>Simple</code> contains a single value e.g. ColorCapable in HardwarePlatform. </li> <li><code>Bag</code> contains multiple unordered values e.g. BluetoothProfile in the HardwarePlatform component.</li> <li><code>Seq</code> contains multiple ordered values e.g. Ccpp-AcceptLanguage in the SoftwarePlatform component.</li> </ul> <p>In addition attributes can have one of four attribute types:</p> <ul> <li><code>String</code> e.g. BrowserName in BrowserUA.</li> <li><code>Boolean</code> e.g. ColorCapable in HardwarePlatform.</li> <li><code>Number</code> is a positive integer e.g. BitsPerPixel in HardwarePlatform.</li> <li><code>Dimension</code> is a pair of positive integers e.g. ScreenSize in HardwarePlatform.</li> </ul> <p>Finally attributes are associated with a resolution rule:</p> <ul> <li><code>Locked</code> indicates the final value of an attribute is the first occurrence of the attribute outside the default description block.</li> <li><code>Override</code> indicates the final value of an attribute is the last occurrence of the attribute outside the default description block.</li> <li><code>Append</code> indicates the final value of the attribute is the list of all occurrences of the attribute outside the default description block.</li> </ul> <p>The UAProf vocabulary is described using the file <code>uaprofspec.xml</code>. This describes the attribute name, component, collectionType, attributeType and resolution rule of each component. The vocabulary description file has the following format:</p> <source><![CDATA[ <?xml version="1.0"?> <vocabspec> <attribute> <name>CcppAccept</name> <component>SoftwarePlatform</component> <collectionType>Bag</collectionType> <attributeType>Literal</attributeType> <resolution>Append</resolution> </attribute> </vocabspec> ]]></source> </s1> <s1 title="W-HTTP Protocol"> <p>An example W-HTTP request using this protocol is shown below:</p> <source><![CDATA[ GET /ccpp/html/ HTTP/1.1 Host: localhost x-wap-profile:"http://127.0.0.1:8080/ccpp/profiles/test09defaults.rdf", "1-Rb0sq/nuUFQU75vAjKyiHw==" x-wap-profile-diff:1;<?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:prf="http://www.wapforum.org/profiles/UAPROF/ccppschema-20010430#"> <rdf:Description rdf:ID="MyDeviceProfile"> <prf:component> <rdf:Description rdf:ID="HardwarePlatform"> <rdf:type rdf:resource="http://www.wapforum.org/profiles/UAPROF/ccppschema- 20010426#HardwarePlatform"/> <prf:BitsPerPixel>16</prf:BitsPerPixel> </rdf:Description> </prf:component> </rdf:Description> </rdf:RDF> ]]></source> <p>The first two lines describe the resource that is being requested by the client, http://localhost/ccpp/html, and the method being used to make the request, GET, and the protocol being used HTTP/1.1. The remaining lines of the request describe the device delivery context. This is specified using a profile reference and a profile-diff. The profile is referenced via the x-wap-profile line and has the URI</p> <source><![CDATA[ http://127.0.0.1:8080/ccpp/profiles/test09defaults.rdf. ]]></source> <p>After the profile reference, there is a value</p> <source><![CDATA[ 1-Rb0sq/nuUFQU75vAjKyiHw== ]]></source> <p>known as a profile-diff digest. The first part of the profile-diff-digest, 1-, is the profile-diff sequence number. This is used to indicate the order of the profile-diffs and to indicate which profile-diff the profile-diff digest refers to. The remainder of the profile-diff digest is generated by applying the <link href="http://www.faqs.org/rfcs/rfc1321.html">MD5 message digest algorithm</link> and Base64 algorithm to the corresponding profile-diff. The MD5 algorithm takes as input a message of arbitary length and produces as output a 128-bit "fingerprint" or "message-digest" of the input. The <link href="http://www.faqs.org/rfcs/rfc2045.html">Base64 algorithm</link> takes as input arbitary binary data and produces as output printable encoding data.</p> <p>After the profile-diff digest, the next line contains the x-wap-profile-diff. This request header field also has a profile-diff sequence number which indicates that this profile-diff corresponds to the previous profile-diff-digest. The profile-diff itself consists of the XML fragment which spans the remainder of the request. Multi-line request header fields are permitted by the HTTP/1.1 specification as long as each subsequent line starts with either a tab character or a whitespace. </p> <p>When the server receives a HTTP request with UAProf request headers, it has to perform profile resolution i.e. retrieve the referenced profile(s) and any further profiles referenced via default blocks. It then has to merge these profiles and the profile-diffs while applying the UAProf resolution rules.</p> </s1> <s1 title="Configuring DELI"> <p>In order to use DELI, you need to enable the DELI component in the <code>cocoon.xconf</code> file and configure TraxTransformer in the <code>sitemap.xmap</code> file to supply the CC/PP profile to a stylesheet via parameters. In addition, you may want to configure DELI using <code>deliCocoonConfig.xml</code>, the DELI configuration file or <code>legacyDevices.xml</code>, the DELI legacy device support file.</p> <s2 title="Cocoon.xconf"> <p>In order to use DELI you need to specify the configuration file and set the use-deli parameter to true in <code>cocoon.xconf</code>:</p> <source><![CDATA[ <deli> <parameter name="deli-config-file" value="deliCocoonConfig.xml"/> <parameter name="use-deli" value="true"/> </deli> ]]></source> </s2> <s2 title="Sitemap.xmap"> Then to provide the resolved DELI profile as a parameter in stylesheets, you need to configure TraxTransformer to use DELI in <code>sitemap.xmap</code>: <source><![CDATA[ <map:transformers default="xslt"> <map:transformer name="xslt" src="org.apache.cocoon.transformation.TraxTransformer" pool-max="32" pool-min="16" pool-grow="4"> <use-request-parameters>false</use-request-parameters> <use-browser-capabilities-db>false</use-browser-capabilities-db> <use-deli>true</use-deli> </map:transformer> ]]></source> </s2> <s2 title="Main Configuration File"> <p>DELI also has its own configuration file has the following format:</p> <source><![CDATA[ <?xml version="1.0"?> <deli> <debug>false</debug> <printDefaults>false</printDefaults> <printProfileBeforeMerge>false</printProfileBeforeMerge> <legacyDeviceFile>legacyDevice.xml</legacyDeviceFile> <vocabularyFile>uaprofspec.xml</vocabularyFile> </deli> ]]></source> <p>This file can contain a number of configuration directives described in in the following sections:</p> <s3 title="Caching options"> <p>The caching options control how the server caches referenced profiles. DELI can either cache profiles indefinitely or update stale profiles after a set interval. It is also possible to configure the maximum size of the profile cache.</p> <table> <tr> <th>Element Name</th> <th>Default Value</th> <th>Description</th> </tr> <tr> <td>maxCachedProfileLifetime</td> <td>24 hours</td> <td>The maximum lifetime of a cached profile in hours.</td> </tr> <tr> <td>maxCacheSize</td> <td>100</td> <td>The maximum number of profiles in the profile cache.</td> </tr> <tr> <td>refreshStaleProfiles</td> <td>false</td> <td>Do we refresh cached profiles after the maximum lifetime has expired?</td> </tr> </table> </s3> <s3 title="Debugging options"> <p>The debugging options are used to control the information that DELI prints to the Servlet engine console.</p> <table> <tr> <th>Element Name</th> <th>Default Value</th> <th>Description</th> </tr> <tr> <td>debug</td> <td>true</td> <td>Is the automatic debug log information turned on?</td> </tr> <tr> <td>printDefaults</td> <td>true</td> <td>Print both default and override values of attributes for debugging purposes?</td> </tr> <tr> <td>printProfileBeforeMerge</td> <td>false</td> <td>Print the profile before merging for debugging purposes?</td> </tr> </table> </s3> <s3 title="Legacy device options"> <p>As already mentioned DELI can support legacy devices by recognising the user-agent string supplied by a client and mapping it on to a profile. In order to use this facility it is necessary to supply an XML file that contains information about legacy device user-agent strings and the corresponding profile URLs. The format for the legacy device file is described in a subsequent section. </p> <table> <tr> <th>Element Name</th> <th>Default Value</th> <th>Description</th> </tr> <tr> <td>supportLegacyDevices</td> <td>true</td> <td>Is the legacy device database turned on?</td> </tr> <tr> <td>legacyDeviceFile</td> <td>legacyDevice.xml</td> <td>The file containing the legacy device database.</td> </tr> </table> </s3> <s3 title="Protocol options"> <p>It is possible to switch on whitespace normalisation in profile-diffs prior to calculating the profile-diff-digest so that additional whitespaces added by the proxy are ignored. To use this option clients must also support whitespace normalisation.</p> <table> <tr> <th>Element Name</th> <th>Default Value</th> <th>Description</th> </tr> <tr> <td>normaliseWhitespaceInProfileDiff</td> <td>true</td> <td>Is whitespace normalisation of the profile-diff prior to calculating the profile-diff-digest turned on?</td> </tr> </table> </s3> <s3 title="Vocabulary options"> <p>DELI has a number of vocabulary options. Firstly it is possible to configure the vocabulary using an XML file. Secondly it is possible to specify the URI to be used for the RDF namespace and the CC/PP or UAProf namespace. This is important because as the specifications are revised they adopt new namespaces. Thirdly it is possible to set the string used to represent components and defaults in the vocabulary. This is important because the two standards currently use different cases for the first letter of default elements (CC/PP uses "default" whereas UAProf uses "Default"). </p> <table> <tr> <th>Element Name</th> <th>Default Value</th> <th>Description</th> </tr> <tr> <td>vocabularyFile</td> <td>uaprofspec.xml</td> <td>The file containing the vocabulary specification.</td> </tr> <tr> <td>ccppUri</td> <td>http://www.wapforum.org/profiles/UAPROF/ccppschema-20010430#</td> <td>The namespace used for CC/PP constructs such as component.</td> </tr> <tr> <td>rdfUri</td> <td>http://www.w3.org/1999/02/22-rdf-syntax-ns#</td> <td>The namespace used for RDF constructs.</td> </tr> <tr> <td>componentProperty</td> <td>component</td> <td>The name for components.</td> </tr> <tr> <td>defaultProperty</td> <td>Default</td> <td>The name for defaults</td> </tr> </table> </s3> </s2> <s2 title="Configuring Legacy Devices"> <p>It is easy to configure DELI to recognise legacy devices via user-agent strings. The legacy device configuration file maps user-agent strings on to profile references on a profile repository. By default this is done in the <code>legacyDevice.xml</code> file, although it is possible to select a different file. The legacy device configuration file has the following format:</p> <source><![CDATA[ <?xml version="1.0"?> <devices> <legacyDevice> <useragentstring>MSIE</useragentstring> <profileref>http://localhost:8080/cocoon/resources/legacyProfiles/msie.rdf</profileref> </legacyDevice> </devices> ]]></source> <p>Where <code>useragentstring</code> is a device unique string found in the user-agent string of the device and <code>profileref</code> is a URL for the appropriate profile on a profile repository. </p> </s2> </s1> <s1 title="Writing CC/PP and UAProf aware stylesheets"> <p>Once you have got DELI running on Cocoon, the next step in creating a CC/PP aware site is to create some stylesheets that use profile information. DELI makes CC/PP or UAProf attributes available to XSLT stylesheets as parameters. As CC/PP attributes are unique within a profile, the component information is omitted. Hence to retrieve the <code>CcppAccept</code> attribute you use the XPath <code>deli-capabilities/browser/CcppAccept</code> whereas to retrieve the <code>ScreenSize</code> attribute you use the XPath <code>deli-capabilities/browser/ScreenSize</code>. In addition where attributes contain multiple values e.g. Bags or Sequences those values are separated using <code><![CDATA[<li>]]></code> elements. Hence to retrieve the individual elements you use the XPath <code>deli-capabilities/browser/CcppAccept/li</code>. The following code demonstrates how to retrieve both a simple and a complex attribute:</p> <source><![CDATA[ <?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:param name="deli-capabilities"/> <xsl:template match="/"> <xsl:if test="contains($deli-capabilities/browser/CcppAccept/li,'wml')"> <xsl:call-template name="wmldevice"/> </xsl:if> <xsl:if test="not(contains($deli-capabilities/browser/CcppAccept/li,'wml'))"> <xsl:call-template name="htmldevice"/> </xsl:if> </xsl:template> <xsl:template name="wmldevice"> <wml> <card id="init" newcontext="true"> <p> <xsl:call-template name="capabilities"/> </p> </card> </wml> </xsl:template> <xsl:template name="htmldevice"> <html> <head> <title>Test Page for DELI in Cocoon</title> </head> <body> <xsl:call-template name="capabilities"/> </body> </html> </xsl:template> <xsl:template name="capabilities"> <xsl:if test="$deli-capabilities/browser/ImageCapable"> ImageCapable: <xsl:value-of select="$deli-capabilities/browser/ImageCapable"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/CcppAccept"> CcppAccept: <xsl:for-each select="$deli-capabilities/browser/CcppAccept/li"> <xsl:value-of select="."/>, </xsl:for-each> <br/> </xsl:if> </xsl:template> </xsl:stylesheet> ]]></source> </s1> </body> </document> 1.1 xml-cocoon2/src/documentation/xdocs/developing/deliquick.xml Index: deliquick.xml =================================================================== <?xml version="1.0" encoding="UTF-8"?> <!-- edited with XML Spy v3.0.7 NT (http://www.xmlspy.com) by Mark Butler (Hewlett-Packard Laboratories UK) --> <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.0//EN" "dtd/document-v10.dtd"> <document> <header> <title>DELI Quick Start Guide</title> <authors> <person name="Mark H. Butler" email="[EMAIL PROTECTED]"/> </authors> </header> <body> <s1 title="DELI Quick Start Guide"> <p>For more information on DELI, see the <link href="deli.html">DELI documentation</link>.</p> <p>In order to enable DELI and try the test pages, you need to enable the DELI component in the <code>cocoon.xconf</code> file. Make sure that the configuration file is correctly specified and set the use-deli parameter to true in <code>cocoon.xconf</code>:</p> <source><![CDATA[ <deli> <parameter name="deli-config-file" value="deliCocoonConfig.xml"/> <parameter name="use-deli" value="true"/> </deli> ]]></source> <p>Then configure TraxTransformer in the <code>sitemap.xmap</code> file to supply the CC/PP profile to a stylesheet via parameters e.g.:</p> <source><![CDATA[ <map:transformer name="xslt" src="org.apache.cocoon.transformation.TraxTransformer" pool-max="32" pool-min="16" pool-grow="4"> <use-request-parameters>false</use-request-parameters> <use-browser-capabilities-db>false</use-browser-capabilities-db> <use-deli>true</use-deli> </map:transformer> ]]></source> <p>By default DELI recognises Internet Explorer and the Nokia WAP development kit as legacy browsers. If you are using a different browser, you may need to edit the <code>legacyDevices.xml</code>, the DELI legacy device support file. For more details see the <link href="deli.html">DELI documentation</link>.</p> </s1> </body> </document> 1.2 +4 -0 xml-cocoon2/src/java/org/apache/cocoon/cocoon.roles Index: cocoon.roles =================================================================== RCS file: /home/cvs/xml-cocoon2/src/java/org/apache/cocoon/cocoon.roles,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- cocoon.roles 3 Jan 2002 12:31:06 -0000 1.1 +++ cocoon.roles 9 Jan 2002 22:20:42 -0000 1.2 @@ -33,6 +33,10 @@ <role name="org.apache.cocoon.Processor" shorthand="processor"/> --> + <role name="org.apache.cocoon.components.deli.Deli" + shorthand="deli" + default-class="org.apache.cocoon.components.deli.DeliImpl"/> + <role name="org.apache.cocoon.Processor" shorthand="sitemap" default-class="org.apache.cocoon.sitemap.SitemapManager"/> 1.1 xml-cocoon2/src/java/org/apache/cocoon/components/deli/Deli.java Index: Deli.java =================================================================== /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.cocoon.components.deli; import org.apache.avalon.framework.component.Component; import org.apache.cocoon.environment.Request; import org.w3c.dom.Document; import javax.servlet.http.HttpServletRequest; import javax.servlet.Servlet; import javax.servlet.ServletException; import java.io.IOException; import com.hp.hpl.deli.*; /** * A component for providing CC/PP and UAProf support using the DELI * library. * * @author <a href="mailto:[EMAIL PROTECTED]">Mark H. Butler</a> * @version CVS $ $ $Date: 2002/01/09 22:20:42 $ */ public interface Deli extends Component { String ROLE = "org.apache.cocoon.components.deli.Deli"; /** Process a HttpServletRequest and either extract * CC/PP or UAProf information from it and use this information * to resolve a profile or examine the user agent string, match * this using the DELI legacy device database, and use this * information to retrieve the appropriate CC/PP profile. * *@param theRequest The Request. *@return The profile as a vector of profile attributes. *@exception IOException. *@exception ServletException. *@exception Exception. */ public Profile getProfile(Request theRequest) throws IOException, ServletException, Exception; /** Convert a profile stored as a vector of profile attributes * to a DOM tree. * *@param theProfile The profile as a vector of profile attributes. *@return The DOM tree. */ public Document getUACapabilities(Profile theProfile); } 1.1 xml-cocoon2/src/java/org/apache/cocoon/components/deli/DeliImpl.java Index: DeliImpl.java =================================================================== /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.cocoon.components.deli; import org.apache.avalon.framework.component.Component; import org.apache.avalon.framework.component.Composable; import org.apache.avalon.framework.configuration.Configurable; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.avalon.framework.activity.Disposable; import org.apache.avalon.framework.component.ComponentException; import org.apache.avalon.framework.component.ComponentManager; import org.apache.avalon.framework.thread.ThreadSafe; import org.apache.avalon.framework.parameters.Parameters; import org.apache.avalon.framework.context.Context; import org.apache.avalon.framework.context.ContextException; import org.apache.avalon.framework.context.Contextualizable; import org.apache.avalon.framework.logger.AbstractLoggable; import org.apache.cocoon.environment.http.HttpContext; import org.apache.cocoon.environment.Request; import org.apache.cocoon.Constants; import org.apache.cocoon.xml.dom.DOMFactory; import org.apache.cocoon.components.parser.Parser; import java.util.Vector; import java.util.Iterator; import java.util.TreeSet; import java.util.Enumeration; import java.util.Locale; import java.util.Map; import java.io.IOException; import java.io.BufferedReader; import java.net.MalformedURLException; import java.security.Principal; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.Text; import javax.servlet.http.HttpServletRequest; import javax.servlet.ServletRequest; import javax.servlet.Servlet; import javax.servlet.ServletException; import javax.servlet.ServletContext; import javax.servlet.ServletInputStream; import javax.servlet.RequestDispatcher; import javax.servlet.http.Cookie; import javax.servlet.http.HttpSession; import com.hp.hpl.deli.Profile; import com.hp.hpl.deli.ProfileAttribute; import com.hp.hpl.deli.Workspace; /** * Allows the use of <a href="http://www-uk.hpl.hp.com/people/marbut/">DELI</a> * to provide <a href="http://www.w3.org/Mobile/CCPP/">CC/PP</a> or * <a href="http://www1.wapforum.org/tech/terms.asp?doc=WAP-248-UAProf-20010530-p.pdf">UAProf</a> * support. For more details of DELI see the Technical Report * <a href="http://www-uk.hpl.hp.com/people/marbut/DeliUserGuideWEB.htm">DELI: * A Delivery Context Library for CC/PP and UAProf</a>. * * @author <a href="mailto:[EMAIL PROTECTED]">Mark H. Butler</a> * @version CVS $ $ $Date: 2002/01/09 22:20:42 $ */ public class DeliImpl extends AbstractLoggable implements Configurable, Component, Deli, Composable, Disposable, ThreadSafe, Contextualizable { /** The path to the Cocoon configuration files */ private String defaultPath = null; /** The name of the main DELI configuration file */ private String deliConfig = "deliCocoonConfig.xml"; /** The DELI workspace */ private Workspace workspace; /** The component manager */ protected ComponentManager manager = null; /** Parser used to construct the DOM tree to import the profile to a stylesheet */ Parser parser; /** A context, used to retrieve the path to the configuration file */ protected Context context; /** This flag indicates whether DELI has been enabled in sitemap.xmap */ boolean useDeli = false; /** Contextualize this class */ public void contextualize(Context context) throws ContextException { this.context = context; org.apache.cocoon.environment.Context envContext = (org.apache.cocoon.environment.Context) context.get(Constants.CONTEXT_ENVIRONMENT_CONTEXT); try { this.defaultPath = envContext.getRealPath("/"); } catch (Exception e) { getLogger().error("DELI: Could not retrieve directory for configuration files", e); } } /** Compose this class */ public void compose(ComponentManager manager) throws ComponentException { this.manager = manager; parser = (Parser)this.manager.lookup(Parser.ROLE); } /** Configure this class */ public final void configure(Configuration conf) throws ConfigurationException { Parameters params = Parameters.fromConfiguration(conf); this.deliConfig = params.getParameter("deli-config-file", this.deliConfig); this.useDeli = params.getParameterAsBoolean("use-deli", this.useDeli); if (this.useDeli) { workspace = new Workspace(this.defaultPath, this.deliConfig); } } /** Dispose of this class */ public void dispose() { if(parser != null) this.manager.release((Component)parser); } /** Process a HttpServletRequest and either extract * CC/PP or UAProf information from it and use this information * to resolve a profile or examine the user agent string, match * this using the DELI legacy device database, and use this * information to retrieve the appropriate CC/PP profile. * *@param theRequest The Request. *@return The profile as a vector of profile attributes. *@exception IOException. *@exception ServletException. *@exception Exception. */ public Profile getProfile(Request theRequest) throws IOException, ServletException, Exception { CocoonServletRequest servletRequest = new CocoonServletRequest(theRequest); Profile theProfile = new Profile(workspace, (HttpServletRequest) servletRequest); return theProfile; } /** Convert a profile stored as a vector of profile attributes * to a DOM tree. * *@param theProfile The profile as a vector of profile attributes. *@return The DOM tree. */ public Document getUACapabilities(Profile theProfile) { Document document; Element rootElement; Element attributeNode; Element complexAttributeNode; Text text; document = ((DOMFactory)parser).newDocument(); rootElement = document.createElementNS(null, "browser"); document.appendChild(rootElement); Iterator profileIter = theProfile.iterator(); while (profileIter.hasNext()) { ProfileAttribute p = (ProfileAttribute) profileIter.next(); attributeNode = document.createElementNS(null, p.getAttribute()); rootElement.appendChild(attributeNode); Vector attributeValue = p.get(); Iterator complexValueIter = attributeValue.iterator(); if (p.getCollectionType().equals("Simple")) { // Simple attribute String value = (String) complexValueIter.next(); text = document.createTextNode(value); attributeNode.appendChild(text); } else { // Complex attribute e.g. Seq or Bag while (complexValueIter.hasNext()) { String value = (String) complexValueIter.next(); complexAttributeNode = document.createElementNS(null, "li"); attributeNode.appendChild(complexAttributeNode); text = document.createTextNode(value); complexAttributeNode.appendChild(text); } } } return document; } /** * Stub implementation of HttpServletRequest */ public class CocoonServletRequest implements HttpServletRequest { Request request; public CocoonServletRequest(Request request) { this.request = request; } public String getAuthType(){ return request.getAuthType(); } public long getDateHeader(String s){ return request.getDateHeader(s); } public String getHeader(String s){ return request.getHeader(s); } public Enumeration getHeaders(String s){ return request.getHeaders(s); } public Enumeration getHeaderNames(){ return request.getHeaderNames(); } public String getMethod(){ return request.getMethod(); } public String getPathInfo(){ return request.getPathInfo(); } public String getPathTranslated(){ return request.getPathTranslated(); } public String getContextPath(){ return request.getContextPath(); } public String getQueryString(){ return request.getQueryString(); } public String getRemoteUser(){ return request.getRemoteUser(); } public boolean isUserInRole(String s){ return request.isUserInRole(s); } public String getRequestedSessionId(){ return request.getRequestedSessionId(); } public String getRequestURI(){ return request.getRequestURI(); } public String getServletPath(){ return request.getServletPath(); } public boolean isRequestedSessionIdValid(){ return request.isRequestedSessionIdValid(); } public boolean isRequestedSessionIdFromCookie(){ return request.isRequestedSessionIdFromCookie(); } public Object getAttribute(String s){ return request.getAttribute(s); } public Enumeration getAttributeNames(){ return request.getAttributeNames(); } public String getCharacterEncoding(){ return request.getCharacterEncoding(); } public int getContentLength(){ return request.getContentLength(); } public String getContentType(){ return request.getContentType(); } public String getParameter(String s){ return request.getParameter(s); } public Enumeration getParameterNames(){ return request.getParameterNames(); } public String[] getParameterValues(String s){ return request.getParameterValues(s); } public String getProtocol(){ return request.getProtocol(); } public String getScheme(){ return request.getScheme(); } public String getServerName(){ return request.getServerName(); } public int getServerPort(){ return request.getServerPort(); } public String getRemoteAddr(){ return request.getRemoteAddr(); } public String getRemoteHost(){ return request.getRemoteHost(); } public void setAttribute(String s, Object obj){ request.setAttribute(s,obj); } public void removeAttribute(String s){ request.removeAttribute(s); } public boolean isSecure(){ return request.isSecure(); } public StringBuffer getRequestURL() { return null; } public Map getParameterMap() { return null; } public void setCharacterEncoding(String s) { } public Principal getUserPrincipal(){ return request.getUserPrincipal(); } public Locale getLocale(){ return request.getLocale(); } public Enumeration getLocales(){ return request.getLocales(); } public String getRealPath(String s){ return null; } public Cookie[] getCookies(){ return null; } public RequestDispatcher getRequestDispatcher(String s){ return null; } public BufferedReader getReader() throws IOException{ return null; } public ServletInputStream getInputStream() throws IOException{ return null; } public HttpSession getSession(boolean flag){ return null; } public HttpSession getSession(){ return null; } public boolean isRequestedSessionIdFromURL(){ return false; } public boolean isRequestedSessionIdFromUrl(){ return false; } public int getIntHeader(String s){ return 0; } } } 1.2 +59 -4 xml-cocoon2/src/java/org/apache/cocoon/transformation/TraxTransformer.java Index: TraxTransformer.java =================================================================== RCS file: /home/cvs/xml-cocoon2/src/java/org/apache/cocoon/transformation/TraxTransformer.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- TraxTransformer.java 3 Jan 2002 12:31:20 -0000 1.1 +++ TraxTransformer.java 9 Jan 2002 22:20:42 -0000 1.2 @@ -25,6 +25,7 @@ import org.apache.cocoon.caching.TimeStampCacheValidity; import org.apache.cocoon.components.browser.Browser; import org.apache.cocoon.components.xslt.XSLTProcessor; +import org.apache.cocoon.components.deli.Deli; import org.apache.cocoon.environment.Session; import org.apache.cocoon.environment.Cookie; import org.apache.cocoon.environment.Request; @@ -40,6 +41,9 @@ import java.text.StringCharacterIterator; import java.util.*; +import com.hp.hpl.deli.Profile; +import com.hp.hpl.deli.ProfileAttribute; + /** * This Transformer is used to transform this incomming SAX stream using * a XSLT stylesheet. Use the following sitemap declarations to define, configure @@ -76,10 +80,18 @@ * of the session information available in the XSLT stylesheetas.<br> * These infos are (boolean values are "true" or "false" strings: session-is-new, * session-id-from-cookie, session-id-from-url, session-valid, session-id.<br> - * Note that this might have issues concerning cachability of the generated output of this - * transformer.<br> * This property is false by default. * + * <p> The <use-deli> configuration forces the transformer to + * make all the properties from the CC/PP profile resolved from the + * request available in the XSLT stylesheets. CC/PP support is + * provided via the DELI library. If the request does not provide + * CC/PP information, then CC/PP information can added via the DELI + * legacy device database. This property is false by default. + * + * <p>Note that these properties might introduces issues concerning + * cacheability of the generated output of this transformer.<br> + * * * The <xslt-processor> configuration allows to specify the XSLT processor that will be * used by its role name. This allows to have several XSLT processors in the configuration @@ -103,7 +115,8 @@ * @author <a href="mailto:[EMAIL PROTECTED]">Carsten Ziegeler</a> * @author <a href="mailto:[EMAIL PROTECTED]">Giacomo Pati</a> * @author <a href="mailto:[EMAIL PROTECTED]">Ovidiu Predescu</a> - * @version CVS $Id: TraxTransformer.java,v 1.1 2002/01/03 12:31:20 giacomo Exp $ + * @author <a href="mailto:[EMAIL PROTECTED]">Mark H. Butler</a> + * @version CVS $Id: TraxTransformer.java,v 1.2 2002/01/09 22:20:42 ovidiu Exp $ */ public class TraxTransformer extends AbstractTransformer implements Transformer, Composable, Recyclable, Configurable, Cacheable, Disposable { @@ -113,6 +126,9 @@ /** The Browser service instance */ private Browser browser = null; + /** The DELI service instance */ + private Deli deli = null; + /** Should we make the request parameters available in the stylesheet? (default is off) */ private boolean useParameters = false; private boolean _useParameters = false; @@ -121,6 +137,10 @@ private boolean useBrowserCap = false; private boolean _useBrowserCap = false; + /* Should we make the DELI CC/PP profile available to the stylesheet (default is off) */ + private boolean useDeli = false; + private boolean _useDeli = false; + /** Should we make the cookies availalbe in the stylesheet? (default is off) */ private boolean useCookies = false; private boolean _useCookies = false; @@ -170,11 +190,16 @@ child = conf.getChild("xslt-processor-role"); String xsltRole = child.getValue(XSLTProcessor.ROLE); - if (this.getLogger().isDebugEnabled() == true) { + child = conf.getChild("use-deli"); + this.useDeli = child.getValueAsBoolean(false); + this._useDeli = this.useDeli; + + if (this.getLogger().isDebugEnabled() == true) { this.getLogger().debug("Use parameters is " + this.useParameters + " for " + this); this.getLogger().debug("Use cookies is " + this.useCookies + " for " + this); this.getLogger().debug("Use browser capabilities is " + this.useBrowserCap + " for " + this); this.getLogger().debug("Use session info is " + this.useSessionInfo + " for " + this); + this.getLogger().debug("Use DELI is " + this.useDeli + " for " + this); this.getLogger().debug("Use XSLTProcessor of role " + xsltRole); } @@ -196,6 +221,8 @@ getLogger().debug("Looking up " + Browser.ROLE); } this.browser = (Browser) manager.lookup(Browser.ROLE); + getLogger().debug("Looking up " + Deli.ROLE); + this.deli = (Deli) manager.lookup(Deli.ROLE); } /** @@ -216,6 +243,7 @@ xsltProcessor.setSourceResolver(resolver); _useParameters = par.getParameterAsBoolean("use-request-parameters", this.useParameters); _useBrowserCap = par.getParameterAsBoolean("use-browser-capabilities-db", this.useBrowserCap); + _useDeli = par.getParameterAsBoolean("use-deli", this.useDeli); _useCookies = par.getParameterAsBoolean("use-cookies", this.useCookies); _useSessionInfo = par.getParameterAsBoolean("use-session-info", this.useSessionInfo); if (this.getLogger().isDebugEnabled() == true) { @@ -409,6 +437,32 @@ getLogger().error("Error setting Browser info", e); } + if (this._useDeli) try { + Request request = (Request) objectModel.get(Constants.REQUEST_OBJECT); + if (map == null) + { + map = new HashMap(); + } + + if (request != null) + { + + Profile theProfile = deli.getProfile(request); + org.w3c.dom.Document deliCapabilities = deli.getUACapabilities(theProfile); + map.put("deli-capabilities", deliCapabilities); + + String accept = request.getParameter("accept"); + if (accept == null) + accept = request.getHeader("accept"); + + /* add the accept param */ + map.put("accept", accept); + } + + } catch (Exception e) { + getLogger().error("Error setting DELI info", e); + } + return map; } @@ -475,6 +529,7 @@ this._useParameters = this.useParameters; this._useCookies = this.useCookies; this._useBrowserCap = this.useBrowserCap; + this._useDeli = this.useDeli; this._useSessionInfo = this.useSessionInfo; super.recycle(); } 1.5 +6 -0 xml-cocoon2/src/webapp/cocoon.xconf Index: cocoon.xconf =================================================================== RCS file: /home/cvs/xml-cocoon2/src/webapp/cocoon.xconf,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- cocoon.xconf 9 Jan 2002 12:01:33 -0000 1.4 +++ cocoon.xconf 9 Jan 2002 22:20:42 -0000 1.5 @@ -194,6 +194,12 @@ <parameter name="servlet-name" value="*.jsp"/> </jsp-engine> + <!-- Deli support --> + <deli> + <parameter name="deli-config-file" value="deliCocoonConfig.xml"/> + <parameter name="use-deli" value="true"/> + </deli> + <!-- Xscript: --> <xscript logger="core.xscript"> 1.4 +27 -0 xml-cocoon2/src/webapp/sitemap.xmap Index: sitemap.xmap =================================================================== RCS file: /home/cvs/xml-cocoon2/src/webapp/sitemap.xmap,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- sitemap.xmap 8 Jan 2002 10:08:03 -0000 1.3 +++ sitemap.xmap 9 Jan 2002 22:20:42 -0000 1.4 @@ -107,6 +107,15 @@ pool-max="32" pool-min="16" pool-grow="4"> <use-request-parameters>false</use-request-parameters> <use-browser-capabilities-db>false</use-browser-capabilities-db> + <use-deli>false</use-deli> + </map:transformer> + + <map:transformer name="xslt-deli" logger="sitemap.transformer.xslt" + src="org.apache.cocoon.transformation.TraxTransformer" + pool-max="32" pool-min="16" pool-grow="4"> + <use-request-parameters>false</use-request-parameters> + <use-browser-capabilities-db>false</use-browser-capabilities-db> + <use-deli>true</use-deli> </map:transformer> <map:transformer name="log" logger="sitemap.transformer.log" @@ -458,6 +467,12 @@ <map:pipelines> + <map:pipeline> + <map:match pattern="sites/images/*.gif"> + <map:read src="resources/images/{1}.gif" mime-type="image/gif"/> + </map:match> + </map:pipeline> + <!-- Utility for viewing source xml or html --> <map:pipeline> <!-- sample use of regexp equivalent to "**.source" using wildcard @@ -680,6 +695,18 @@ <!-- ================ Hello =========================== --> + + <map:match pattern="deli.html"> + <map:generate src="docs/samples/hello-page.xml"/> + <map:transform src="stylesheets/deli_test.xsl" type="xslt-deli"/> + <map:serialize type="html"/> + </map:match> + + <map:match pattern="deli.wml"> + <map:generate src="docs/samples/hello-page.xml"/> + <map:transform src="stylesheets/deli_test.xsl" type="xslt-deli"/> + <map:serialize type="wap"/> + </map:match> <map:match pattern="hello.html"> <map:generate src="docs/samples/hello-page.xml"/> 1.1 xml-cocoon2/src/webapp/deliCocoonConfig.xml Index: deliCocoonConfig.xml =================================================================== <?xml version="1.0"?> <deli> <debug>false</debug> <printDefaults>false</printDefaults> <printProfileBeforeMerge>false</printProfileBeforeMerge> <legacyDeviceFile>legacyDevice.xml</legacyDeviceFile> <vocabularyFile>uaprofspec.xml</vocabularyFile> </deli> 1.1 xml-cocoon2/src/webapp/legacyDevice.xml Index: legacyDevice.xml =================================================================== <?xml version="1.0" encoding="UTF-8"?> <devices> <legacyDevice> <useragentstring>MSIE</useragentstring> <profileref>http://localhost:8080/cocoon/legacyProfiles/msie.rdf</profileref> </legacyDevice> <legacyDevice> <useragentstring>Nokia-WAP-Toolkit</useragentstring> <profileref>http://localhost:8080/cocoon/legacyProfiles/nokia.rdf</profileref> </legacyDevice> <legacyDevice> <useragentstring>Rainbow</useragentstring> <profileref>http://localhost:8080/cocoon/legacyProfiles/nokia.rdf</profileref> </legacyDevice> </devices> 1.2 +12 -0 xml-cocoon2/src/webapp/docs/samples/samples.xml Index: samples.xml =================================================================== RCS file: /home/cvs/xml-cocoon2/src/webapp/docs/samples/samples.xml,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- samples.xml 3 Jan 2002 12:31:39 -0000 1.1 +++ samples.xml 9 Jan 2002 22:20:42 -0000 1.2 @@ -105,6 +105,18 @@ </sample> </group> + <group name="CC/PP and UAProf"> + <sample name="Quick Start" href="documents/deliquick.html"> + Read this to find out how to enable DELI before trying the test pages. + </sample> + <sample name="DELI" href="deli.html"> + Test page for HTML clients. + </sample> + <sample name="DELI" href="deli.wml"> + Test page for WAP clients. + </sample> + </group> + <group name="Dynamic Content"> <sample name="Simple XSP" href="xsp/simple"> Simple XSP example. 1.1 xml-cocoon2/src/webapp/stylesheets/deli_test.xsl Index: deli_test.xsl =================================================================== <?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:param name="deli-capabilities"/> <xsl:param name="accept"/> <xsl:template match="/"> <xsl:if test="contains($accept,'wml')"> <xsl:call-template name="wmldevice"/> </xsl:if> <xsl:if test="not(contains($accept,'wml'))"> <xsl:call-template name="htmldevice"/> </xsl:if> </xsl:template> <xsl:template name="wmldevice"> <wml> <card id="init" newcontext="true"> <p> <xsl:call-template name="capabilities"/> </p> </card> </wml> </xsl:template> <xsl:template name="htmldevice"> <html> <head> <title>Test Page for DELI in Cocoon</title> </head> <body> <xsl:call-template name="capabilities"/> </body> </html> </xsl:template> <xsl:template name="capabilities"> <xsl:if test="$deli-capabilities/browser/ColorCapable"> ColorCapable: <xsl:value-of select="$deli-capabilities/browser/ColorCapable"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/AudioInputEncoder"> AudioInputEncoder: <xsl:for-each select="$deli-capabilities/browser/AudioInputEncoder/li"> <xsl:value-of select="."/>, </xsl:for-each> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/DownloadableBrowserApps"> DownloadableBrowserApps: <xsl:for-each select="$deli-capabilities/browser/DownloadableBrowserApps/li"> <xsl:value-of select="."/>, </xsl:for-each> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/TextInputCapable"> TextInputCapable: <xsl:value-of select="$deli-capabilities/browser/TextInputCapable"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/ImageCapable"> ImageCapable: <xsl:value-of select="$deli-capabilities/browser/ImageCapable"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/CcppAccept"> CcppAccept: <xsl:for-each select="$deli-capabilities/browser/CcppAccept/li"> <xsl:value-of select="."/>, </xsl:for-each> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/CcppAccept-Charset"> CcppAccept-Charset: <xsl:for-each select="$deli-capabilities/browser/CcppAccept-Charset/li"> <xsl:value-of select="."/>, </xsl:for-each> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/CcppAccept-Encoding"> CcppAccept-Encoding: <xsl:for-each select="$deli-capabilities/browser/CcppAccept-Encoding/li"> <xsl:value-of select="."/>, </xsl:for-each> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/CcppAccept-Language"> CcppAccept-Language: <xsl:for-each select="$deli-capabilities/browser/CcppAccept-Language/li"> <xsl:value-of select="."/>, </xsl:for-each> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/JavaPlatform"> JavaPlatform: <xsl:for-each select="$deli-capabilities/browser/JavaPlatform/li"> <xsl:value-of select="."/>, </xsl:for-each> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/JVMVersion"> JVMVersion: <xsl:for-each select="$deli-capabilities/browser/JVMVersion/li"> <xsl:value-of select="."/>, </xsl:for-each> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/XhtmlModules"> XhtmlModules: <xsl:for-each select="$deli-capabilities/browser/XhtmlVersion/li"> <xsl:value-of select="."/>, </xsl:for-each> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/SupportedPictogramSet"> SupportedPictogramSet: <xsl:for-each select="$deli-capabilities/browser/SupportedPictogramSet/li"> <xsl:value-of select="."/>, </xsl:for-each> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/OutputCharSet"> OutputCharSet: <xsl:for-each select="$deli-capabilities/browser/OutputCharSet/li"> <xsl:value-of select="."/>, </xsl:for-each> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/InputCharSet"> InputCharSet: <xsl:for-each select="$deli-capabilities/browser/InputCharSet/li"> <xsl:value-of select="."/>, </xsl:for-each> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/WmlScriptVersion"> WmlScriptVersion: <xsl:for-each select="$deli-capabilities/browser/WmlScriptVersion/li"> <xsl:value-of select="."/>, </xsl:for-each> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/WmlVersion"> WmlVersion: <xsl:for-each select="$deli-capabilities/browser/WmlVersion/li"> <xsl:value-of select="."/>, </xsl:for-each> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/VideoInputEncoder"> VideoInputEncoder: <xsl:for-each select="$deli-capabilities/browser/VideoInputEncoder/li"> <xsl:value-of select="."/>, </xsl:for-each> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/SupportedBeareres"> SupportedBearers: <xsl:for-each select="$deli-capabilities/browser/SupportedBearers/li"> <xsl:value-of select="."/>, </xsl:for-each> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/SecuritySupport"> SecuritySupport: <xsl:value-of select="$deli-capabilities/browser/SecuritySupport"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/CurrentBearerService"> CurrentBearerService: <xsl:value-of select="$deli-capabilities/browser/CurrentBearerService"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/BrowserName"> BrowserName: <xsl:value-of select="$deli-capabilities/browser/BrowserName"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/BrowserVersion"> BrowserVersion: <xsl:value-of select="$deli-capabilities/browser/BrowserVersion"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/SupportedBlueToothVersion"> SupportedBluetoothVersion: <xsl:value-of select="$deli-capabilities/browser/SupportedBlueToothVersion"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/SoftwareNumber"> SoftwareNumber: <xsl:value-of select="$deli-capabilities/browser/SoftwareNumber"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/HtmlVersion"> HtmlVersion: <xsl:value-of select="$deli-capabilities/browser/HtmlVersion"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/JavaAppletEnabled"> JavaAppletEnabled: <xsl:value-of select="$deli-capabilities/browser/JavaAppletEnabled"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/JavaScriptEnabled"> JavaScriptEnabled: <xsl:value-of select="$deli-capabilities/browser/JavaScriptEnabled"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/JavaScriptVersion"> JavaScriptVersion: <xsl:value-of select="$deli-capabilities/browser/JavaScriptVersion"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/PreferenceForFrames"> PreferenceForFrames: <xsl:value-of select="$deli-capabilities/browser/PreferenceForFrames"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/TablesCapable"> TablesCapable: <xsl:value-of select="$deli-capabilities/browser/TablesCapable"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/XhtmlVersion"> XhtmlVersion: <xsl:value-of select="$deli-capabilities/browser/XhtmlVersion"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/WapDeviceClass"> WapDeviceClass: <xsl:value-of select="$deli-capabilities/browser/WapDeviceClass"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/WapVersion"> WapVersion: <xsl:value-of select="$deli-capabilities/browser/WapVersion"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/WmlDeckSize"> WmlDeckSize: <xsl:value-of select="$deli-capabilities/browser/WmlDeckSize"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/WmlScriptLibraries"> WmlScriptLibraries: <xsl:for-each select="$deli-capabilities/browser/WmlScriptLibraries/li"> <xsl:value-of select="."/>, </xsl:for-each> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/WtaiLibraries"> WtaiLibraries: <xsl:for-each select="$deli-capabilities/browser/WtaiLibraries/li"> <xsl:value-of select="."/>, </xsl:for-each> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/WtaiVersion"> WtaiVersion: <xsl:value-of select="$deli-capabilities/browser/WtaiVersion"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/BluetoothProfile"> BluetoothProfile: <xsl:for-each select="$deli-capabilities/browser/BluetoothProfile/li"> <xsl:value-of select="."/>, </xsl:for-each> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/ImageCapable"> ImageCapable: <xsl:value-of select="$deli-capabilities/browser/ImageCapable"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/Keyboard"> Keyboard: <xsl:value-of select="$deli-capabilities/browser/Keyboard"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/CPU"> CPU: <xsl:value-of select="$deli-capabilities/browser/CPU"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/Model"> Model: <xsl:value-of select="$deli-capabilities/browser/Model"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/NumberOfSoftKeys"> NumberOfSoftKeys: <xsl:value-of select="$deli-capabilities/browser/NumberOfSoftKeys"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/PixelAspectRatio"> PixelAspectRatio: <xsl:value-of select="$deli-capabilities/browser/PixelAspectRatio"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/PointingResolution"> PointingResolution: <xsl:value-of select="$deli-capabilities/browser/PointingResolution"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/ScreenSize"> ScreenSize: <xsl:value-of select="$deli-capabilities/browser/ScreenSize"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/ScreenSizeChar"> ScreenSizeChar: <xsl:value-of select="$deli-capabilities/browser/ScreenSizeChar"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/StandardFontProportional"> StandardFontProportional: <xsl:value-of select="$deli-capabilities/browser/StandardFontProportional"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/SoundOutputCapable"> SoundOutputCapable: <xsl:value-of select="$deli-capabilities/browser/SoundOutputCapable"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/TextInputCapable"> TextInputCapable: <xsl:value-of select="$deli-capabilities/browser/TextInputCapable"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/RecipientAppAgent"> RecipientAppAgent: <xsl:value-of select="$deli-capabilities/browser/RecipientAppAgent"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/OSVersion"> OSVersion: <xsl:value-of select="$deli-capabilities/browser/OSVersion"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/MexeSpec"> MexeSpec: <xsl:value-of select="$deli-capabilities/browser/MexeSpec"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/MexeClassmarks"> MexeClassmarks: <xsl:for-each select="$deli-capabilities/browser/MexeClassmarks/li"> <xsl:value-of select="."/>, </xsl:for-each> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/JavaEnabled"> JavaEnabled: <xsl:value-of select="$deli-capabilities/browser/JavaEnabled"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/DownloadableSoftwareSupport"> DownloadableSoftwareSupport: <xsl:for-each select="$deli-capabilities/browser/DownloadableSoftwareSupport/li"> <xsl:value-of select="."/>, </xsl:for-each> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/AcceptDownloadableSoftware"> AcceptDownloadableSoftware: <xsl:value-of select="$deli-capabilities/browser/AcceptDownloadableSoftware"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/VoiceInputCapable"> VoiceInputCapable: <xsl:value-of select="$deli-capabilities/browser/VoiceInputCapable"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/Vendor"> Vendor: <xsl:value-of select="$deli-capabilities/browser/Vendor"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/FramesCapable"> FramesCapable: <xsl:value-of select="$deli-capabilities/browser/FramesCapable"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/BitsPerPixel"> BitsPerPixel: <xsl:value-of select="$deli-capabilities/browser/BitsPerPixel"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/Push-Accept"> Push-Accept: <xsl:for-each select="$deli-capabilities/browser/Push-Accept/li"> <xsl:value-of select="."/>, </xsl:for-each> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/Push-Accept-Charset"> Push-Accept-Charset: <xsl:for-each select="$deli-capabilities/browser/Push-Accept-Charset/li"> <xsl:value-of select="."/>, </xsl:for-each> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/Push-Accept-Encoding"> Push-Accept-Encoding: <xsl:for-each select="$deli-capabilities/browser/Push-Accept-Encoding/li"> <xsl:value-of select="."/>, </xsl:for-each> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/Push-Accept-Language"> Push-Accept-Language: <xsl:for-each select="$deli-capabilities/browser/Push-Accept-Language/li"> <xsl:value-of select="."/>, </xsl:for-each> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/Push-Accept-AppID"> Push-Accept-AppID: <xsl:for-each select="$deli-capabilities/browser/PushAccept-AppID/li"> <xsl:value-of select="."/>, </xsl:for-each> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/Push-MsgSize"> Push-MsgSize: <xsl:value-of select="$deli-capabilities/browser/Push-MsgSize"/> <br/> </xsl:if> <xsl:if test="$deli-capabilities/browser/Push-MaxPushReq"> Push-MaxPushReq: <xsl:value-of select="$deli-capabilities/browser/Push-MaxPushReq"/> <br/> </xsl:if> </xsl:template> </xsl:stylesheet>
---------------------------------------------------------------------- In case of troubles, e-mail: [EMAIL PROTECTED] To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]