You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by Bob Jamison <rj...@lincom-asg.com> on 2001/04/24 18:10:43 UTC

Q: Future of Filter?

Hey, all, I have a minor question about TC4, if anyone knows,
cool, if not, oh, well.    ;-)

(Actually, I am probably just overlooking something obvious)

In the public drafts of 2.3 and in the Tomcat examples, I have
seen various specifications of Filter.  Is the spec going to
move toward Tomcat (since it is the testbed impl) or will Tomcat's
impl change?

For example, currently in the examples, it is defined as having 3 methods:

public void init(FilterConfig config);
public void doFilter(ServletRequest req,ServletResponse resp,FilterChain 
chain);
public void destroy();


While in the final draft it is:

public void FilterConfig getFilterConfig();
public void setFilterConfig(FilterConfig config);
public void doFilter(ServletRequest req,ServletResponse resp,FilterChain 
chain);


They are identical in function, except for destroy().
I can see some benefit in keeping destroy(),  since the Filter might
have allocated a lot of resources, (such as an XSLT transformer), but the
other differences  seem to be merely preference.

Just wondering, as I am still becoming acquainted with the new stuff in 2.3.



Bob


Re: Future of Filter?

Posted by Amy Roh <am...@apache.org>.
Servlet spec 2.3 has changed to support init(FilterConfig config) and
destroy() methods instead of getFilterConfig() and
setFilterConfig(FilterConfig config) after discussion to change filter cycle
to be similar to the servlet life cycle in the expert group.  The recent
changes will be reflected in the new Proposed Final Draft 2 (which will be
available to public very soon).  So TC4 is up to date with the recent spec.
:-)

Amy

----- Original Message -----
From: "Bob Jamison" <rj...@lincom-asg.com>
To: <to...@jakarta.apache.org>
Sent: Tuesday, April 24, 2001 9:10 AM
Subject: Q: Future of Filter?


> Hey, all, I have a minor question about TC4, if anyone knows,
> cool, if not, oh, well.    ;-)
>
> (Actually, I am probably just overlooking something obvious)
>
> In the public drafts of 2.3 and in the Tomcat examples, I have
> seen various specifications of Filter.  Is the spec going to
> move toward Tomcat (since it is the testbed impl) or will Tomcat's
> impl change?
>
> For example, currently in the examples, it is defined as having 3 methods:
>
> public void init(FilterConfig config);
> public void doFilter(ServletRequest req,ServletResponse resp,FilterChain
> chain);
> public void destroy();
>
>
> While in the final draft it is:
>
> public void FilterConfig getFilterConfig();
> public void setFilterConfig(FilterConfig config);
> public void doFilter(ServletRequest req,ServletResponse resp,FilterChain
> chain);
>
>
> They are identical in function, except for destroy().
> I can see some benefit in keeping destroy(),  since the Filter might
> have allocated a lot of resources, (such as an XSLT transformer), but the
> other differences  seem to be merely preference.
>
> Just wondering, as I am still becoming acquainted with the new stuff in
2.3.
>
>
>
> Bob
>


Re: Future of Filter?

Posted by Bob Jamison <rj...@lincom-asg.com>.
Oops!  Got the tags wrong; the filter names
should match.  One more error this week,
but who's counting?



> 
> <filter>
> <filter-name>XSLT Filter for Skin1</filter-name>
> <filter-class>XSLTFilter</filter-class>
> <init-param>
>   <param-name>xsltFileName</param-name>
>   <param-value>skin1.xsl</param-value>
> </init-param>
> </filter>
> 
> <filter-mapping>
> <filter-name>Skin1Command</filter-name>
> <servlet-name>command</servlet-name>
> </filter-mapping>


<filter>
<filter-name>XSLT Filter for Skin1</filter-name>
<filter-class>XSLTFilter</filter-class>
<init-param>
  <param-name>xsltFileName</param-name>
  <param-value>skin1.xsl</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>XSLT Filter for Skin1</filter-name>
<servlet-name>command</servlet-name>
</filter-mapping>


> 



Re: Future of Filter?

Posted by Bob Jamison <rj...@lincom-asg.com>.
Craig R. McClanahan wrote:

> 
> Yep, you've got the pattern down.  It's also legal to use
> HttpServletResponseWrapper if you're wrapping HTTP responses.  And, of
> course, you can wrap the request if you want to do input filtering, in
> pretty much the same manner.
> 
> Craig
> 
> 
> 


Ok, thanks for the help!  I finally got
my first Filter working, with a little
cajoling (and some begging)  ;-)

This is the typical XSL transform that I
plan to use on a set of generic servlets which
will produce XML only, with stylesheets giving
the pages 'skins.'

I know this initial implementation is not optimal,
but it works for now.  The XSLTOutputStream took
a bit of imagination.  It plugs in like this:



<filter>
  <filter-name>XSLT Filter for Skin1</filter-name>
  <filter-class>XSLTFilter</filter-class>
  <init-param>
    <param-name>xsltFileName</param-name>
    <param-value>skin1.xsl</param-value>
  </init-param>
</filter>

<filter-mapping>
  <filter-name>Skin1Command</filter-name>
  <servlet-name>command</servlet-name>
</filter-mapping>











Anyway, thanks again.




Bob
















================= BEGIN XSLTFilter ==================


import java.io.*;
import javax.servlet.*;

public class XSLTFilter implements Filter
{

FilterConfig filterConfig;
String xsltName;
ServletResponse xsltResponse;


//---##### Inner class ServletResponse
class XSLTResponse extends ServletResponseWrapper
{
OutputStream outs;
ServletOutputStream souts;

public ServletOutputStream getOutputStream()
{
  return souts;
}

public XSLTResponse(ServletResponse response,String xslFileName)
           throws ServletException,IOException
{
  super(response);
  outs = new XSLTOutputStream(response.getOutputStream(),xslFileName);
  souts = new ServletOutputStream()
    {
        public void write(int ch) throws IOException
        {
        outs.write(ch);
        }
    };
}
}
//---##### end inner class ServletResponse



public void init(FilterConfig val)
              throws ServletException
{
  filterConfig=val;
  xsltName=filterConfig.getInitParameter("xsltFileName");
  if (xsltName==null)
   throw new ServletException("XSLTFilter.init():no file name given for 
init-param 'xsltFileName'");
}

public void doFilter(ServletRequest request,ServletResponse 
response,FilterChain chain)
              throws IOException,ServletException
{
  if (xsltResponse==null)
   try
     {
     xsltResponse = new XSLTResponse(response,xsltName);
     }
   catch (Exception e)
     {
     throw new ServletException("XSLTFilter.doFilter():"+e);
     }
  chain.doFilter(request,xsltResponse);
}

public void destroy()
{
}


}


================= END XSLTFilter ==================










================= BEGIN XSLTOutputStream ==================

import java.io.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;


/**
* This class uses a very simple piping mechanism to "push" XML data through
* an XSL transform.
* @author Bob Jamison
* @date 25 Apr 01
*/
public class XSLTOutputStream extends FilterOutputStream
                             implements Runnable
{
OutputStream outputStream;
Transformer transformer;
PipedInputStream pins;
PipedOutputStream pouts;

public void run()
{
  try
   {
   transformer.transform(new StreamSource(pins),new 
StreamResult(outputStream));
   }
  catch (Exception e)
   {
   }
}

//Implement OutputStream things
/**
* Closes this output stream and releases any system resources
* associated with this stream. The general contract of <code>close</code>
* is that it closes the output stream. A closed stream cannot perform
* output operations and cannot be reopened.
* <p>
* @exception  IOException  if an I/O error occurs.
*/
public void close() throws IOException
{
  pouts.flush();
  pouts.close();
  //pins.close();
}

/**
* Flushes this output stream and forces any buffered output bytes
* to be written out. The general contract of <code>flush</code> is
* that calling it is an indication that, if any bytes previously
* written have been buffered by the implementation of the output
* stream, such bytes should immediately be written to their
* intended destination.
* <p>
* @exception  IOException  if an I/O error occurs.
*/
public void flush() throws IOException
{
  pouts.flush();
}

/**
* Writes <code>b.length</code> bytes from the specified byte array
* to this output stream. The general contract for <code>write(b)</code>
* is that it should have exactly the same effect as the call
* <code>write(b, 0, b.length)</code>.
*
* @param      b   the data.
* @exception  IOException  if an I/O error occurs.
* @see        java.io.OutputStream#write(byte[], int, int)
*/
public void write(byte[] b) throws IOException
{
  pouts.write(b);
}

/**
* Writes <code>len</code> bytes from the specified byte array
* starting at offset <code>off</code> to this output stream.
* The general contract for <code>write(b, off, len)</code> is that
* some of the bytes in the array <code>b</code> are written to the
* output stream in order; element <code>b[off]</code> is the first
* byte written and <code>b[off+len-1]</code> is the last byte written
* by this operation.
* <p>
* The <code>write</code> method of <code>OutputStream</code> calls
* the write method of one argument on each of the bytes to be
* written out. Subclasses are encouraged to override this method and
* provide a more efficient implementation.
* <p>
* If <code>b</code> is <code>null</code>, a
* <code>NullPointerException</code> is thrown.
* <p>
* If <code>off</code> is negative, or <code>len</code> is negative, or
* <code>off+len</code> is greater than the length of the array
* <code>b</code>, then an <tt>IndexOutOfBoundsException</tt> is thrown.
*
* @param      b     the data.
* @param      off   the start offset in the data.
* @param      len   the number of bytes to write.
* @exception  IOException  if an I/O error occurs. In particular,
*             an <code>IOException</code> is thrown if the output
*             stream is closed.
*/
public void write(byte[] b, int off, int len) throws IOException
{
  pouts.write(b,off,len);
}

/**
* Writes the specified byte to this output stream. The general
* contract for <code>write</code> is that one byte is written
* to the output stream. The byte to be written is the eight
* low-order bits of the argument <code>b</code>. The 24
* high-order bits of <code>b</code> are ignored.
* <p>
*
* @param      b   the <code>byte</code>.
* @exception  IOException  if an I/O error occurs. In particular,
*             an <code>IOException</code> may be thrown if the
*             output stream has been closed.
*/
public void write(int b) throws IOException
{
  pouts.write(b);
}

void setup(OutputStream outputStream, Transformer transformer)
                throws IOException
{
  this.transformer = transformer;
  this.outputStream = outputStream;
  pins = new PipedInputStream();
  pouts = new PipedOutputStream(pins);
  (new Thread(this)).start();
}

/**
* Creates an output stream that translates output according to the
* given XSLT Transformer.
*
* @param      outputStream  the existing XML stream to transform
* @param      transformer   the configured XSLT Transformer (see TRaX)
* @exception  IOException  if an I/O error occurs. In particular,
*             an <code>IOException</code> may be thrown if the
*             output stream has been closed.
*/
public XSLTOutputStream(OutputStream outputStream, Transformer transformer)
                 throws IOException
{
  super((OutputStream)null);
  setup(outputStream,transformer);
}

/**
* Creates an output stream that translates output according to the
* given XSLT source file..
*
* @param      outputStream  the existing XML stream to transform
* @param      xslFile       the name of the XSL stylesheet file
* @exception  TransformerException if there is a problem creating a
*             transformer from the named file
* @exception  IOException  if an I/O error occurs. In particular,
*             an <code>IOException</code> may be thrown if the
*             output stream has been closed.
*/
public XSLTOutputStream(OutputStream outputStream, String xslFile)
                throws IOException
{
  super((OutputStream)null);
  try
   {
   TransformerFactory factory = TransformerFactory.newInstance();
   Transformer transformer = factory.newTransformer(new 
StreamSource(xslFile));
   setup(outputStream,transformer);
   }
  catch (TransformerException e)
   {
   throw new IOException("XSLTOutputStreamConstructor:"+e);
   }
}

///### T E S T I N G
static boolean test(String xmlName,String xslName)
{
  try
   {
   FileInputStream ins = new FileInputStream(xmlName);
   XSLTOutputStream outs = new XSLTOutputStream(System.out,xslName);
   while (true)
     {
     int ch = ins.read();
     if (ch<0)
       break;
     outs.write(ch);
     }
   ins.close();
   outs.close();
   }
  catch (Exception e)
   {
   e.printStackTrace();
   return false;
   }
  return true;
}

public static void main(String argv[])
{
  if (argv.length==2)
   {
   test(argv[0],argv[1]);
   }
  else
   {
   System.out.println("usage: XSLOutputStream xmlFile xslFile");
   return;
   }
  }

}



================= END XSLTOutputStream ==================




Re: Future of Filter?

Posted by "Craig R. McClanahan" <cr...@apache.org>.

On Wed, 25 Apr 2001, Bob Jamison wrote:

> Amy Roh wrote:
> 
> > Servlet spec 2.3 has changed to support init(FilterConfig config) and
> > destroy() methods instead of getFilterConfig() and
> > setFilterConfig(FilterConfig config) after discussion to change filter cycle
> > to be similar to the servlet life cycle in the expert group.  The recent
> > changes will be reflected in the new Proposed Final Draft 2 (which will be
> > available to public very soon).  So TC4 is up to date with the recent spec.
> > :-)
> > 
> > Amy
> > 
> Thanks, that's what I suspected.
> 
> By the way, I did not find any examples that actually performed any
> filtering.

Inside the sources of the "examples" web app that comes with Tomcat 4.0,
there is a CompressionFilter that automatically applies GZIP compression
if the client says they can use it, and the response is over a
configurable size limit.

>  Would this be a common usage pattern for Filter?  :
> 

Yep, you've got the pattern down.  It's also legal to use
HttpServletResponseWrapper if you're wrapping HTTP responses.  And, of
course, you can wrap the request if you want to do input filtering, in
pretty much the same manner.

Craig


Re: Future of Filter?

Posted by Bob Jamison <rj...@lincom-asg.com>.
Amy Roh wrote:

> Servlet spec 2.3 has changed to support init(FilterConfig config) and
> destroy() methods instead of getFilterConfig() and
> setFilterConfig(FilterConfig config) after discussion to change filter cycle
> to be similar to the servlet life cycle in the expert group.  The recent
> changes will be reflected in the new Proposed Final Draft 2 (which will be
> available to public very soon).  So TC4 is up to date with the recent spec.
> :-)
> 
> Amy
> 
Thanks, that's what I suspected.

By the way, I did not find any examples that actually performed any
filtering.  Would this be a common usage pattern for Filter?  :




==== SNIP ====

public class MyFilter implements Filter
{

//---An inner class wrapper that does my filtering
class MyServletResponse extends ServletResponseWrapper
{
  public MyServletResponse(ServletResponse response)
  {
   super(response);
   //do stuff
  }
}
//---end inner class



public void doFilter(ServletRequest request,
                     ServletResponse response,
                     FilterChain chain)
                  throws IOException,ServletException
{
  MyServletResponse altResponse = new MyServletResponse(response);
  chain.doFilter(request,altResponse);
}

}

==== UN-SNIP ====




Something like that, maybe?



Anyway, thanks again.

Bob







Re: Future of Filter?

Posted by Amy Roh <am...@apache.org>.
Servlet spec 2.3 has changed to support init(FilterConfig config) and
destroy() methods instead of getFilterConfig() and
setFilterConfig(FilterConfig config) after discussion to change filter cycle
to be similar to the servlet life cycle in the expert group.  The recent
changes will be reflected in the new Proposed Final Draft 2 (which will be
available to public very soon).  So TC4 is up to date with the recent spec.
:-)

Amy

----- Original Message -----
From: "Bob Jamison" <rj...@lincom-asg.com>
To: <to...@jakarta.apache.org>
Sent: Tuesday, April 24, 2001 9:10 AM
Subject: Q: Future of Filter?


> Hey, all, I have a minor question about TC4, if anyone knows,
> cool, if not, oh, well.    ;-)
>
> (Actually, I am probably just overlooking something obvious)
>
> In the public drafts of 2.3 and in the Tomcat examples, I have
> seen various specifications of Filter.  Is the spec going to
> move toward Tomcat (since it is the testbed impl) or will Tomcat's
> impl change?
>
> For example, currently in the examples, it is defined as having 3 methods:
>
> public void init(FilterConfig config);
> public void doFilter(ServletRequest req,ServletResponse resp,FilterChain
> chain);
> public void destroy();
>
>
> While in the final draft it is:
>
> public void FilterConfig getFilterConfig();
> public void setFilterConfig(FilterConfig config);
> public void doFilter(ServletRequest req,ServletResponse resp,FilterChain
> chain);
>
>
> They are identical in function, except for destroy().
> I can see some benefit in keeping destroy(),  since the Filter might
> have allocated a lot of resources, (such as an XSLT transformer), but the
> other differences  seem to be merely preference.
>
> Just wondering, as I am still becoming acquainted with the new stuff in
2.3.
>
>
>
> Bob
>


Re: Q: Future of Filter?

Posted by "Craig R. McClanahan" <cr...@apache.org>.

On Tue, 24 Apr 2001, Bob Jamison wrote:

> Hey, all, I have a minor question about TC4, if anyone knows,
> cool, if not, oh, well.    ;-)
> 
> (Actually, I am probably just overlooking something obvious)
> 
> In the public drafts of 2.3 and in the Tomcat examples, I have
> seen various specifications of Filter.  Is the spec going to
> move toward Tomcat (since it is the testbed impl) or will Tomcat's
> impl change?
> 
> For example, currently in the examples, it is defined as having 3 methods:
> 
> public void init(FilterConfig config);
> public void doFilter(ServletRequest req,ServletResponse resp,FilterChain 
> chain);
> public void destroy();
> 
> 
> While in the final draft it is:
> 
> public void FilterConfig getFilterConfig();
> public void setFilterConfig(FilterConfig config);
> public void doFilter(ServletRequest req,ServletResponse resp,FilterChain 
> chain);
> 
> 
> They are identical in function, except for destroy().
> I can see some benefit in keeping destroy(),  since the Filter might
> have allocated a lot of resources, (such as an XSLT transformer), but the
> other differences  seem to be merely preference.
> 
> Just wondering, as I am still becoming acquainted with the new stuff in 2.3.
> 
> 
> 
> Bob
> 
> 

In "Proposed Final Draft 2" (coming soon) you will see that init() and
destroy() are the final answer.  This change was approved by the JSR-053
expert group after the "Proposed Final Draft" version was published, and
Tomcat was changed at that time.

There will be a few more minor changes in Tomcat 4.0 (not API related) to
reflect other clarifications that will be in PFD2.

Craig McClanahan