servlet filters

22
Servlet Filters Servlet Filters L. Grewe L. Grewe

Upload: norman

Post on 22-Jan-2016

110 views

Category:

Documents


3 download

DESCRIPTION

Servlet Filters. L. Grewe. Filters. New with Servlet Specification 2.3 Lightweight framework for filtering dynamic or static content A filter is a reusable piece of code that can transform the content of HTTP requests, responses, and header information. Example uses: Authentication filters - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Servlet Filters

Servlet FiltersServlet Filters

L. GreweL. Grewe

Page 2: Servlet Filters

FiltersFilters New with Servlet Specification 2.3New with Servlet Specification 2.3 Lightweight framework for filtering dynamic or static Lightweight framework for filtering dynamic or static

contentcontent A filter is a reusable piece of code that can transform A filter is a reusable piece of code that can transform

the content of HTTP requests, responses, and header the content of HTTP requests, responses, and header information.information.

Example uses:Example uses:• Authentication filtersAuthentication filters• Logging and auditing filtersLogging and auditing filters• Image conversion filtersImage conversion filters• Data compression filtersData compression filters• Encryption filtersEncryption filters• XSL/T filters that transform XML contentXSL/T filters that transform XML content• Caching filtersCaching filters

Page 3: Servlet Filters

Servlets: FiltersServlets: Filters

Transform HTTP requests and Transform HTTP requests and responsesresponses

filter servlet

request requestrequest

responseresponseresponse

Page 4: Servlet Filters

Example 1: Facebook AuthenticatonExample 1: Facebook Authenticaton

You have a facebook application built with various jsps You have a facebook application built with various jsps and/or servlets.and/or servlets.

Before someone can use your facebook application they Before someone can use your facebook application they must be logged into facebook as an authenticated user must be logged into facebook as an authenticated user before your application can get any user data from before your application can get any user data from facebook about them.facebook about them.

SOLUTION 1:SOLUTION 1:• Create a servlet that serves as the “interface servlet” (callback Create a servlet that serves as the “interface servlet” (callback

url) between facebook and your application. This servlet must url) between facebook and your application. This servlet must make sure that the user is logged into facebook/autheticated make sure that the user is logged into facebook/autheticated and if not forwards them to a URL for facebook log- in.and if not forwards them to a URL for facebook log- in.

PROBLEM with SOLUTION:PROBLEM with SOLUTION:• Now need separate Servlet layer for each time user makes Now need separate Servlet layer for each time user makes

request of your app.request of your app.

BETTER SOLUTION:……..FILTERS……next….BETTER SOLUTION:……..FILTERS……next….

Page 5: Servlet Filters

Facebook Authenticaton w/ FiltersFacebook Authenticaton w/ Filters

Instead of a separate servlet, create Instead of a separate servlet, create a filter used before each of your apps a filter used before each of your apps jsps/servlets.jsps/servlets.

This filter, FaceBookAuthFilter, This filter, FaceBookAuthFilter, makes sure the user is authentic and makes sure the user is authentic and • if so passes on this information to your if so passes on this information to your

main apps jsps/servlets as parameters in main apps jsps/servlets as parameters in request.request.

• If NOT then forwards request on to If NOT then forwards request on to facebook log-in page. facebook log-in page.

Page 6: Servlet Filters

FaceBookAuthFilter SetupFaceBookAuthFilter Setup

FaceBookAuthFilterFaceBookAuthFilter Facebook App JSPs/servlets

request requestrequest

responseresponseresponse

Facebook login

OR

requestrequest

Page 7: Servlet Filters

FaceBookAuthFilter Code FaceBookAuthFilter Code

/**/** * The servlet filter that makes sure that the user is logged in before* The servlet filter that makes sure that the user is logged in before * letting the requests reach the application code.* letting the requests reach the application code. * @author theliveweb.net* @author theliveweb.net ** */*/public class FaceBookAuthFilter implements Filter {public class FaceBookAuthFilter implements Filter { private String _apiKey;private String _apiKey; private String _secretKey;private String _secretKey;

//read in some parameters passed via web.xml file//read in some parameters passed via web.xml file //these parameters are unique to each facebook application and//these parameters are unique to each facebook application and // are required when you make facebook api calls in your webapp// are required when you make facebook api calls in your webapp public void init(final FilterConfig filterConfig){public void init(final FilterConfig filterConfig){ _apiKey = filterConfig.getInitParameter("api_key");_apiKey = filterConfig.getInitParameter("api_key"); _secretKey = filterConfig.getInitParameter("secret_key");_secretKey = filterConfig.getInitParameter("secret_key"); }}

(see website for complete code)

Page 8: Servlet Filters

/**/** * * Verifies whether user is logged in. If not, sends user to the login page.Verifies whether user is logged in. If not, sends user to the login page. */*/ public void public void doFilterdoFilter(final ServletRequest request, final ServletResponse response, (final ServletRequest request, final ServletResponse response,

FilterChain chain) throwsFilterChain chain) throws IOException, ServletException { IOException, ServletException {

HttpServletRequest httpReq = (HttpServletRequest) request;HttpServletRequest httpReq = (HttpServletRequest) request; HttpServletResponse httpRes = (HttpServletResponse) response;HttpServletResponse httpRes = (HttpServletResponse) response;

try {try { //determine if user authenticated and if not throw an exception//determine if user authenticated and if not throw an exception httpReq.getParameter(FacebookParam.SESSION_KEY.toString())+"<br><br>");httpReq.getParameter(FacebookParam.SESSION_KEY.toString())+"<br><br>"); FacebookXmlRestClient authClient = FacebookXmlRestClient authClient = FaceBookAuthHandler.getAuthenticatedClient(httpReq, _apiKey, _secretKey);FaceBookAuthHandler.getAuthenticatedClient(httpReq, _apiKey, _secretKey);

//if user authenticated set as request param and call next filter or the Servlet//if user authenticated set as request param and call next filter or the Servlet request.setAttribute("facebook.client", authClient);request.setAttribute("facebook.client", authClient); chain.doFilter(request, response);chain.doFilter(request, response); } catch (FailedLoginException fle) {} catch (FailedLoginException fle) { //user not logged in, this will forward request to facebook login page//user not logged in, this will forward request to facebook login page forceLogin(httpRes);forceLogin(httpRes);

} catch (Exception e) {} catch (Exception e) { //handle other exceptions//handle other exceptions }} }}

Page 9: Servlet Filters

Facebook example…partial web.xml fileFacebook example…partial web.xml file<display-name>Facebook Suchana</display-name><display-name>Facebook Suchana</display-name>

<filter><filter> <filter-name><filter-name> FaceBookAuthFilterFaceBookAuthFilter </filter-name></filter-name> <filter-class><filter-class> net.theliveweb.facebook.FaceBookAuthFilternet.theliveweb.facebook.FaceBookAuthFilter </filter-class></filter-class> <init-param><init-param> <param-name>api_key</param-name><param-name>api_key</param-name> <param-value>b70966a3bbf411cd67e12b052f159e9a</param-value><param-value>b70966a3bbf411cd67e12b052f159e9a</param-value> </init-param></init-param> <init-param><init-param> <param-name>secret_key</param-name><param-name>secret_key</param-name> <param-value>3eac91f71a179f810d4e2495cc3bace1</param-value><param-value>3eac91f71a179f810d4e2495cc3bace1</param-value> </init-param></init-param></filter></filter><filter-mapping><filter-mapping> <filter-name>FaceBookAuthFilter</filter-name><filter-name>FaceBookAuthFilter</filter-name> <url-pattern>/T.jsp</url-pattern><url-pattern>/T.jsp</url-pattern></filter-mapping></filter-mapping>

<filter-mapping><filter-mapping> <filter-name>FaceBookAuthFilter</filter-name><filter-name>FaceBookAuthFilter</filter-name> <url-pattern>/index.jsp</url-pattern><url-pattern>/index.jsp</url-pattern></filter-mapping></filter-mapping>

<filter-mapping><filter-mapping> <filter-name>FaceBookAuthFilter</filter-name><filter-name>FaceBookAuthFilter</filter-name> <url-pattern>/avatar</url-pattern><url-pattern>/avatar</url-pattern></filter-mapping></filter-mapping><servlet><servlet><servlet-name>avatar</servlet-name><servlet-name>avatar</servlet-name><jsp-file>/avatar.jsp</jsp-file><jsp-file>/avatar.jsp</jsp-file></servlet></servlet>

<servlet><servlet><servlet-name>T</servlet-name><servlet-name>T</servlet-name><jsp-file>/T.jsp</jsp-file><jsp-file>/T.jsp</jsp-file></servlet></servlet>

Declare our web-app servlets/jsps use our FaceBookAuthFilterthrough the web.xml file

Here we are declaring thefilter, you can have more than one if you want.

Here we are saying whatfilters are applied to whichwebapp url patterns

Here we have areservlet declarations…only partial info here

Page 10: Servlet Filters

Filter class methods:Filter class methods: initinit

• called before the servlet engine begins using the filter. called before the servlet engine begins using the filter. destroydestroy

• called before the engine removes a filter from service. If called before the engine removes a filter from service. If you need to clean up filter-specific resources, you can you need to clean up filter-specific resources, you can do that with the destroy method. do that with the destroy method.

doFilterdoFilter• meat of the filter, call each time user invokes filtered meat of the filter, call each time user invokes filtered

servlets/jspsservlets/jsps• where you have access to the request and response where you have access to the request and response

objects, just as you would in a normal servlet's doGet or objects, just as you would in a normal servlet's doGet or doPost method. You can query or modify these objects doPost method. You can query or modify these objects as needed. as needed.

• Then, you can forward the request to the next filter in Then, you can forward the request to the next filter in the chain (or to the servlet if this is deployed as the last the chain (or to the servlet if this is deployed as the last filter) by calling filterChain.doFilter. filter) by calling filterChain.doFilter.

Page 11: Servlet Filters

Generic Filter deploymentGeneric Filter deployment Deploy this class with webapp that use this Deploy this class with webapp that use this

filter.filter. Modify the webapp’s web.xmlModify the webapp’s web.xml

• Add filter definition to bottom of list of filters (if any):Add filter definition to bottom of list of filters (if any):<filter><filter>

<filter-name>Request Blocker</filter-name><filter-name>Request Blocker</filter-name><filter-class>com.develop.filters.RequestBlocker</filter-class><filter-class>com.develop.filters.RequestBlocker</filter-class></filter> </filter>

• Apply filter to any servlets/jsps by indicating the url-Apply filter to any servlets/jsps by indicating the url-pattern:pattern:

<filter-mapping><filter-mapping><filter-name>Request Blocker</filter-name><filter-name>Request Blocker</filter-name><url-pattern>/*</url-pattern><url-pattern>/*</url-pattern></filter-mapping> </filter-mapping>

Page 12: Servlet Filters

Filters can Modify BOTH the Filters can Modify BOTH the request and response objects!request and response objects!

Our facebook example modified the Our facebook example modified the request parameter…..lets look at an request parameter…..lets look at an example that modifies the response example that modifies the response parameter……parameter……

Page 13: Servlet Filters

Example 2: XSLTFilterExample 2: XSLTFilter

Automatically performs a transform Automatically performs a transform on an XML document returned the on an XML document returned the servlet it calls (chains to), rendering servlet it calls (chains to), rendering the document into HTML before the document into HTML before returning it to the caller. returning it to the caller.

Page 14: Servlet Filters

How XSLTFilter WorksHow XSLTFilter Works STEPS of doFilter()STEPS of doFilter()

1.1. Setup A SPECIAL response object we can use easily for translation:Setup A SPECIAL response object we can use easily for translation:• Instead of passing the response object to the next filter in the chain, XSLTFilter's call Instead of passing the response object to the next filter in the chain, XSLTFilter's call

to doFilter specifies a customized response object named to doFilter specifies a customized response object named wrappedRespwrappedResp To make it easy to replace the response object, the filter architecture provides a To make it easy to replace the response object, the filter architecture provides a

helper class, named HttpServletResponseWrapper, that wraps the original response helper class, named HttpServletResponseWrapper, that wraps the original response object, and simply passes through every method call. XSLTFilter creates an object, and simply passes through every method call. XSLTFilter creates an anonymous subclass of HttpServletResponseWrapper, overriding three methods: anonymous subclass of HttpServletResponseWrapper, overriding three methods: getOutputStream, getWriter, and setContentType. getOutputStream, getWriter, and setContentType.

The getOutputStream and getWriter methods use an instance of the nested helper The getOutputStream and getWriter methods use an instance of the nested helper class ByteArrayPrintWriter, named class ByteArrayPrintWriter, named pw.pw.

2.2. Call downstream filter or ServletCall downstream filter or Servlet• When a downstream filter or servlet writes into the "response," it actually writes into When a downstream filter or servlet writes into the "response," it actually writes into

the instance of pw (which is the writer for the the instance of pw (which is the writer for the wrappedResp wrappedResp object)object) AND this pw object AND this pw object is stored in the Filter class.is stored in the Filter class.

3.3. Change response type to “text/html”Change response type to “text/html” The setContentType method checks to see if the content being returned is "text/xml". The setContentType method checks to see if the content being returned is "text/xml".

If a downstream servlet or filter tries to set the content type to "text/xml", the If a downstream servlet or filter tries to set the content type to "text/xml", the overridden setContentType changes it to "text/html" instead, and sets a flag, overridden setContentType changes it to "text/html" instead, and sets a flag, xformNeeded[0], indicating that the transform needs to run. xformNeeded[0], indicating that the transform needs to run.

4.4. Translate current response from xml to htmlTranslate current response from xml to html After calling filerChain.doFilter, XSLTFilter checks to see if it needs to transform the After calling filerChain.doFilter, XSLTFilter checks to see if it needs to transform the

response. If it does, it takes the downstream response from response. If it does, it takes the downstream response from pwpw, and transforms it into , and transforms it into the "real" response, the "real" response, respresp. Of course, resp might not be the "real" response either, . Of course, resp might not be the "real" response either, because XSLTFilter might be downstream from yet another filter. because XSLTFilter might be downstream from yet another filter.

Transformation done w/ XSLT, which is loaded using the Java API for XML Parsing Transformation done w/ XSLT, which is loaded using the Java API for XML Parsing (JAXP) TransformerFactory class. Setting up the transform illustrates another filter (JAXP) TransformerFactory class. Setting up the transform illustrates another filter feature: initialization parameters. The XSLTFilter expects to be configured with an feature: initialization parameters. The XSLTFilter expects to be configured with an initialization parameter named "xslt" that specifies which transform to run. initialization parameter named "xslt" that specifies which transform to run.

Page 15: Servlet Filters

XSLTFilter codeXSLTFilter code//class com.develop.filters.XSLTFilter //class com.develop.filters.XSLTFilter

package com.develop.filters;package com.develop.filters;

import java.io.*; import java.io.*; import java.util.*; import java.util.*; import javax.servlet.*; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.http.*; import javax.xml.transform.*; import javax.xml.transform.*; import javax.xml.transform.stream.*; import javax.xml.transform.stream.*;

public class XSLTFilter implements Filter { public class XSLTFilter implements Filter { private ServletContext ctx; private ServletContext ctx; private String xslt; private String xslt; private TransformerFactory tf = TransformerFactory.newInstance(); private TransformerFactory tf = TransformerFactory.newInstance(); private Transformer xform; private Transformer xform;

private static class ByteArrayServletStream extends ServletOutputStream private static class ByteArrayServletStream extends ServletOutputStream { ByteArrayOutputStream baos; { ByteArrayOutputStream baos; ByteArrayServletStream(ByteArrayOutputStream baos) { this.baos = ByteArrayServletStream(ByteArrayOutputStream baos) { this.baos = baos; } baos; }

public void write(int param) throws java.io.IOException public void write(int param) throws java.io.IOException { baos.write(param); } } { baos.write(param); } }

Page 16: Servlet Filters

private static class ByteArrayPrintWriter { private static class ByteArrayPrintWriter {

private ByteArrayOutputStream baos = new ByteArrayOutputStream(); private ByteArrayOutputStream baos = new ByteArrayOutputStream(); private PrintWriter pw = new PrintWriter(baos); private PrintWriter pw = new PrintWriter(baos); private ServletOutputStream sos = new ByteArrayServletStream(baos); private ServletOutputStream sos = new ByteArrayServletStream(baos); public PrintWriter getWriter() public PrintWriter getWriter() { return pw; } { return pw; }

public ServletOutputStream getStream() public ServletOutputStream getStream() { return sos; } { return sos; }

byte[] toByteArray() byte[] toByteArray() { return baos.toByteArray(); } { return baos.toByteArray(); }

}}

public void init(FilterConfig filterConfig) throws ServletException { public void init(FilterConfig filterConfig) throws ServletException { ctx = filterConfig.getServletContext(); ctx = filterConfig.getServletContext(); xslt = filterConfig.getInitParameter("xslt"); xslt = filterConfig.getInitParameter("xslt"); ctx.log("Filter " + filterConfig.getFilterName() + " using xslt " + xslt); ctx.log("Filter " + filterConfig.getFilterName() + " using xslt " + xslt);

try { try { xform = tf.newTransformer(new StreamSource( ctx.getResourceAsStream(xslt))); } xform = tf.newTransformer(new StreamSource( ctx.getResourceAsStream(xslt))); }

catch (Exception e) catch (Exception e) { ctx.log("Could not intialize transform", e); throw new ServletException( "Could not { ctx.log("Could not intialize transform", e); throw new ServletException( "Could not

initialize transform", e); } initialize transform", e); } } }

Page 17: Servlet Filters

public void doFilter(javax.servlet.ServletRequest servletRequest, public void doFilter(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse, javax.servlet.FilterChain javax.servlet.ServletResponse servletResponse, javax.servlet.FilterChain filterChain) throws java.io.IOException, javax.servlet.ServletException { filterChain) throws java.io.IOException, javax.servlet.ServletException {

HttpServletRequest hsr = (HttpServletRequest)servletRequest; HttpServletRequest hsr = (HttpServletRequest)servletRequest; final HttpServletResponse resp = (HttpServletResponse)servletResponse; final HttpServletResponse resp = (HttpServletResponse)servletResponse;

ctx.log("Accessing filter for " + httpReqLine(hsr) + " " + hsr.getMethod()); ctx.log("Accessing filter for " + httpReqLine(hsr) + " " + hsr.getMethod());

final ByteArrayPrintWriter pw = new ByteArrayPrintWriter();final ByteArrayPrintWriter pw = new ByteArrayPrintWriter();final boolean[] xformNeeded = new boolean[1]; final boolean[] xformNeeded = new boolean[1]; //STEP 1 – SETUP SPECIAL RESPONSE OBJECT//STEP 1 – SETUP SPECIAL RESPONSE OBJECTHttpServletResponse HttpServletResponse wrappedRespwrappedResp = new HttpServletResponseWrapper(resp) { = new HttpServletResponseWrapper(resp) { public PrintWriter getWriter() { return public PrintWriter getWriter() { return pwpw.getWriter(); } .getWriter(); } public ServletOutputStream getOutputStream() { return pw.getStream(); } public ServletOutputStream getOutputStream() { return pw.getStream(); }

public void setContentType(String type) { public void setContentType(String type) { if (type.equals("text/xml")) if (type.equals("text/xml")) { ctx.log("Converting xml to html"); { ctx.log("Converting xml to html"); resp.setContentType("text/html"); resp.setContentType("text/html"); xformNeeded[0] = true; } xformNeeded[0] = true; } else { else { resp.setContentType(type);resp.setContentType(type); } } } } };};

//STEP 2 – call downstream filter or Servlet//STEP 2 – call downstream filter or ServletfilterChain.doFilter(servletRequest, wrappedResp); filterChain.doFilter(servletRequest, wrappedResp);

//STEP 3: set contenttype of response

Call chain to get xml data

Page 18: Servlet Filters

byte[] bytes = pw.toByteArray();byte[] bytes = pw.toByteArray();

if (bytes == null || (bytes.length == 0)) if (bytes == null || (bytes.length == 0)) { ctx.log("No content!"); } { ctx.log("No content!"); } if (xformNeeded[0] == true) if (xformNeeded[0] == true) { try { { try { //Note: This can be _very_ inefficient for large //Note: This can be _very_ inefficient for large //transforms such transforms should be pre- //transforms such transforms should be pre- //calculated. //calculated. ByteArrayOutputStream baos = new ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream(); xform.transform(new StreamSource(new xform.transform(new StreamSource(new ByteArrayInputStream(bytes)),ByteArrayInputStream(bytes)), new StreamResult(baos)); new StreamResult(baos));

byte[] xformBytes = baos.toByteArray(); /*This fixes a bug in the original published tip, which byte[] xformBytes = baos.toByteArray(); /*This fixes a bug in the original published tip, which did not set the content length to the _new_ length implied by the xform. */did not set the content length to the _new_ length implied by the xform. */

resp.setContentLength(xformBytes.length); resp.setContentLength(xformBytes.length); resp.getOutputStream().write(xformBytes);resp.getOutputStream().write(xformBytes);

ctx.log("XML -> HTML conversion completed"); ctx.log("XML -> HTML conversion completed"); } catch (Exception e) } catch (Exception e) { throw new ServletException("Unable to transform document", e); } { throw new ServletException("Unable to transform document", e); } } }

else { resp.getOutputStream().write(bytes); } else { resp.getOutputStream().write(bytes); } } }

public void destroy() { ctx.log("Destroying filter..."); }public void destroy() { ctx.log("Destroying filter..."); }

} }

Writing out the newlyTransformed xml to htmlData to response

STEP 4: Translate xml to HTML

Page 19: Servlet Filters

public String httpReqLine(HttpServletRequest req) { public String httpReqLine(HttpServletRequest req) { StringBuffer ret = req.getRequestURL(); StringBuffer ret = req.getRequestURL(); String query = req.getQueryString(); String query = req.getQueryString();

if (query != null) { ret.append("?").append(query); } if (query != null) { ret.append("?").append(query); } return ret.toString(); return ret.toString();

} }

//get header info//get header infopublic String getHeaders(HttpServletRequest req) throws IOException { public String getHeaders(HttpServletRequest req) throws IOException {

Enumeration en = req.getHeaderNames(); Enumeration en = req.getHeaderNames(); StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer(); while (en.hasMoreElements()) { while (en.hasMoreElements()) {

String name = (String) en.nextElement(); String name = (String) en.nextElement(); sb.append(name).append(": ").append( req.getHeader(name)).append("\sb.append(name).append(": ").append( req.getHeader(name)).append("\

n"); n"); } } return sb.toString(); return sb.toString();

} }

Page 20: Servlet Filters

XSLTransform Filter web.xml XSLTransform Filter web.xml partial filepartial file

<filter> <filter> <filter-name>XSLT Filter</filter-name> <filter-name>XSLT Filter</filter-name> <filter-class>com.develop.filters.XSLTFilter</filter-class> <filter-class>com.develop.filters.XSLTFilter</filter-class> <init-param> <init-param> <param-name>xslt</param-name> <param-name>xslt</param-name> <!-- Change the param-value to the XSLT you want to use --> <!-- Change the param-value to the XSLT you want to use --> <param-value>/xform2.xsl</param-value> <param-value>/xform2.xsl</param-value> </init-param> </init-param>

</filter> </filter>

<filter-mapping> <filter-mapping> <filter-name>XSLT Filter</filter-name> <filter-name>XSLT Filter</filter-name> <url-pattern>/*</url-pattern> <url-pattern>/*</url-pattern>

</filter-mapping> </filter-mapping>

NOTE: The transform is performed using XSLT, which is loaded using the Java API for XML Parsing (JAXP) TransformerFactory class. Setting up the transform illustrates another filter feature: initialization parameters. The XSLTFilter expects to be configured with an initialization parameter named "xslt" that specifies which transform to run.

Page 21: Servlet Filters

XSLTransform example….the restXSLTransform example….the rest

1.1. Make sure that your servlet engine is configured to set Make sure that your servlet engine is configured to set the content type for XML files. In Tomcat you will edit the the content type for XML files. In Tomcat you will edit the

{yourTomcat}/conf/web.xml {yourTomcat}/conf/web.xml <!-- add to the list of mime-mappings already present --> <!-- add to the list of mime-mappings already present --> <mime-mapping> <mime-mapping>

<extension>xml</extension> <extension>xml</extension> <mime-type>text/xml</mime-type> <mime-type>text/xml</mime-type>

</mime-mapping> </mime-mapping>

2.2. Install some XML and XSL files. The web.xml before Install some XML and XSL files. The web.xml before assumes that you are using xform2.xsl and next slide is assumes that you are using xform2.xsl and next slide is an Index.xml to do the filter on. Copy the files to an Index.xml to do the filter on. Copy the files to

{YourTomcat}/webapps/examples {YourTomcat}/webapps/examples

Page 22: Servlet Filters

Index.xml to do the translation onIndex.xml to do the translation on<?xml version="1.0" encoding="iso-8859-1"?> <?xml version="1.0" encoding="iso-8859-1"?> <!-- File Index.xml --> <!-- File Index.xml --> <tips> <tips> <author id="stu" fullName="Stuart Halloway"/> <author id="stu" fullName="Stuart Halloway"/> <author id="glen" fullName="Glen McCluskey"/> <author id="glen" fullName="Glen McCluskey"/> <tip title="Using the SAX API" <tip title="Using the SAX API"

author="stu" author="stu" htmlURL="http://java.sun.com/jdc/TechTips/2000/tt0627.html#tip2" htmlURL="http://java.sun.com/jdc/TechTips/2000/tt0627.html#tip2" textURL="http://java.sun.com/jdc/TechTips/txtarchive/June00_Stu.txt"> textURL="http://java.sun.com/jdc/TechTips/txtarchive/June00_Stu.txt">

</tip> </tip> <tip title="Random Access for Files" <tip title="Random Access for Files"

author="glen" author="glen" htmlURL="http://java.sun.com/jdc/TechTips/2000/tt0509.html#tip1" htmlURL="http://java.sun.com/jdc/TechTips/2000/tt0509.html#tip1" textURL="http://java.sun.com/jdc/TechTips/txtarchive/May00_GlenM.txt">textURL="http://java.sun.com/jdc/TechTips/txtarchive/May00_GlenM.txt">

</tip> </tip> </tips></tips>

<!-- File Xform2.xsl --> <!-- File Xform2.xsl --> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:template match="/"> <xsl:template match="/"> <HTML><BODY><H1>JDC Tech Tips Archive</H1> <xsl:apply-templates/> </BODY></HTML><HTML><BODY><H1>JDC Tech Tips Archive</H1> <xsl:apply-templates/> </BODY></HTML></xsl:template></xsl:template>

<!-- list the title of a tip --> <<!-- list the title of a tip --> <xsl:template match="tip"> xsl:template match="tip"> <br><xsl:apply-templates select="@*"/><xsl:value-of select="@title"/></br> <br><xsl:apply-templates select="@*"/><xsl:value-of select="@title"/></br> </xsl:template> </xsl:template>

<!-- create a link to any htmlURL --> <!-- create a link to any htmlURL --> <xsl:template match="@htmlURL"> <xsl:template match="@htmlURL"> <A HREF="/developer/JDCTechTips/2001/{.}"> HTML </A> | <A HREF="/developer/JDCTechTips/2001/{.}"> HTML </A> | </xsl:template> </xsl:template>

<!-- create a link to any textURL --> <!-- create a link to any textURL --> <xsl:template match="@textURL"> <xsl:template match="@textURL"> <A HREF="/developer/JDCTechTips/2001/{.}"> TEXT </A> | <A HREF="/developer/JDCTechTips/2001/{.}"> TEXT </A> | </xsl:template> </xsl:template>

<!-- ignore other attributes --> <!-- ignore other attributes --> <xsl:template match="@*"/> <xsl:template match="@*"/>

</xsl:stylesheet> </xsl:stylesheet>

This is the XSL for use in translating the xml to html

This is the XML: documentroot tag is tips, which has2 tips in it and 2 authors