    //*********************************************************
    /** Determine if the user-agent supports XSL transformations
    *
    *   @param  userAgent   The user-agent string
    *   @return             True if the user agents has XSLT
    *                       support
    */
    //*********************************************************
    private boolean browserSupportsXSLT ( String userAgent )
    {
        boolean supports = false;

        if ( userAgent == null )
            return supports;

      // check for IE 6.0 or greater
        if ( userAgent.indexOf ( "MSIE 6" ) != -1  ||
             userAgent.indexOf("MSIE 7") != -1 )
            supports = true;

        return supports;
    }

    //*********************************************************
    /** Perform an XSL transformation using the JAXP TRAX API
    *
    *   We assume that the request was for a file with .xml
    *   as file extension. We then assume that the XSLT
    *   stylesheet has the same base name but .xsl for
    *   extension.
    *
    *   @param  req     The request object
    *   @param  res     The response object
    */
    //*********************************************************
    public void transform ( HttpServletRequest req
                          , HttpServletResponse res )
        throws IOException, ServletException, TransformerException
    {
      // set the content type and retrieve an output writer
        res.setContentType ( "text/html" );
        PrintWriter out = res.getWriter();

      // retrieve the request URI
      // the URI is an absolute within the webapp context,
      // e.g. /lab08/xmlfiles/roster.xml
        String xmlURI = req.getRequestURI();

      // create a similar URI string with .xsl as an extension
        int index = xmlURI.indexOf ( '.' );
        if ( index == -1 )
            throw new ServletException ( "bad URI: " + xmlURI );
        String xslURI = xmlURI.substring ( 0, index );
        xslURI += ".xsl";

      // in the next step, we will convert the URI to an absolute
      // file path on the server. However, that call requires a
      // URI that does not include the webapp context. For example,
      // we need to change "/lab08/xmlfiles/roster.xml" to
      // "/xmlfiles/roster.xml" (assuming that /lab08 is the
      // context path)

      // we need to use an actual file path rather than a URI,
      // since if we access the XML file via HTTP, the container
      // will invoke this filter again, resulting in an infinite
      // recursive loop!
        index = xmlURI.indexOf ( '/' );
        int index2 = xmlURI.indexOf ( '/', index + 1 );
        String xmlRelURI = xmlURI.substring ( index2 );
        String xslRelURI = xslURI.substring ( index2 );

      // convert the URIs for the XML and XSL into actual file
      // paths on the web server
        String xmlRealPath = context.getRealPath ( xmlRelURI );
        String xslRealPath = context.getRealPath ( xslRelURI );

      // retrieve a factory for XSLT transformation using JAXP
        TransformerFactory factory =
            TransformerFactory.newInstance();

      // create JAXP transformation Sources from the XML and
      // XSL files
        StreamSource source =
            new StreamSource ( new File ( xmlRealPath ) );
        StreamSource xsl =
            new StreamSource ( new File ( xslRealPath ) );

      // create a JAXP transformation Result from the servlet
      // output writer
        StreamResult result = new StreamResult ( out );

      // create the the XSL transformer
        Transformer tformer = factory.newTransformer ( xsl );

      // perform the transformation, sending the result back
      // to the user agent
        tformer.transform ( source, result );
    }
