This tutorial assumes that your are familiar with Jigsaw architecture, and that you have read both the configuration and the resource tutorials. It will explain you the last major concept of Jigsaw you should be aware of: resource filters.
Note: In Jigsaw2.0, filters must be attached to frames, NOT resources!
As was said in the architectural overview of Jigsaw, each HTTP request ends up performed by some target resource and frame instance. For the sake of simplicity, we didn't mentioned at that time, that frame classes provided with the Jigsaw server inherits from the FramedResource class. All instances of this class are able to manage a set of frames that can be filters: these filters, which are to be instances of sub-classes of ResourceFilter, are called-back twice during request processing:
The remaining of this tutorial will walk through the code of the CounterFilter. This filter just counts the number of hits to its target resource. Before going any further, you should again make sure you have understand the resource tutorial. This tutorial has two sections: the first one will describe our filter's code, and the second one will explain how to attach it to a frame of the target resource.
// CounterFilter.java // $Id: writing-filters.html,v 1.5 2000/03/10 16:49:16 bmahe Exp $ // (c) COPYRIGHT MIT and INRIA, 1996. // Please first read the full copyright statement in file COPYRIGHT.html package org.w3c.jigsaw.filters; import org.w3c.tools.resources.*; import org.w3c.jigsaw.http.*; import org.w3c.jigsaw.resources.*; /** * Count the number of hits to the target. * This resource maintains the number of hits to some target resource, as * one of its persistent attribute. * It will decorate the request on the way in with a fake field * <code>org.w3c.jigsaw.filters.CounterFilter.count</code>, that will * hold the current hit counts for the target resource to use. */ public class CounterFilter extends ResourceFilter { /** * The name of the piece if state that receives the hit count value. * To get to the hit-count, use the <code>getState</code> method of * Request, with the following key. */ public static final String STATE_COUNT = "org.w3c.jigsaw.filters.CounterFilter.count"; /** * Attribute index - The counter attribute. */ protected static int ATTR_COUNTER = -1 ; static { Attribute a = null ; Class cls = null ; try { cls = Class.forName("org.w3c.jigsaw.filters.CounterFilter") ; } catch (Exception ex) { ex.printStackTrace() ; System.exit(1) ; } // Declare the counter attribute a = new IntegerAttribute("counter" , new Integer(0) , Attribute.EDITABLE) ; ATTR_COUNTER = AttributeRegistry.registerAttribute(cls, a) ; } }
We can now implement the ingoingFilter method of our filter, which is as simple as you might expect:
// CounterFilter.java // $Id: writing-filters.html,v 1.5 2000/03/10 16:49:16 bmahe Exp $ // (c) COPYRIGHT MIT and INRIA, 1996. // Please first read the full copyright statement in file COPYRIGHT.html package org.w3c.jigsaw.filters; import org.w3c.tools.resources.*; import org.w3c.jigsaw.http.*; import org.w3c.jigsaw.resources.*; /** * Count the number of hits to the target. * This resource maintains the number of hits to some target resource, as * one of its persistent attribute. * It will decorate the request on the way in with a fake field * <code>org.w3c.jigsaw.filters.CounterFilter.count</code>, that will * hold the current hit counts for the target resource to use. */ public class CounterFilter extends ResourceFilter { /** * The name of the piece if state that receives the hit count value. * To get to the hit-count, use the <code>getState</code> method of * Request, with the following key. */ public static final String STATE_COUNT = "org.w3c.jigsaw.filters.CounterFilter.count"; /** * Attribute index - The counter attribute. */ protected static int ATTR_COUNTER = -1 ; static { Attribute a = null ; Class cls = null ; try { cls = Class.forName("org.w3c.jigsaw.filters.CounterFilter") ; } catch (Exception ex) { ex.printStackTrace() ; System.exit(1) ; } // Declare the counter attribute a = new IntegerAttribute("counter" , new Integer(0) , Attribute.EDITABLE) ; ATTR_COUNTER = AttributeRegistry.registerAttribute(cls, a) ; } /** * We count all accesses, even the one that failed. * We also define the * <code>org.w3c.jigsaw.filters.CounterFilter.count</code> * request state as the number of hits on that resource (stored as * an Integer instance). * @param request The request being processed. * @return Always <strong>null</strong>. */ public synchronized ReplyInterface ingoingFilter(RequestInterface req) { Request request = (Request) req; int i = getInt (ATTR_COUNTER, 0) + 1; setInt(ATTR_COUNTER, i) ; if(! request.hasState(STATE_COUNT)) request.setState(STATE_COUNT, new Integer(i)) ; return null; } }
Note that the counter value will be made persistent across servers invocation by the Jigsaw runtime. To be clear, this means that you can shutdown the server, and restart it: the count will keep up to date. Now, enough coding, let's play with our filter, the next section explains how to attach an instance of the filter to some target resource.
Now, we can access /User (point your browser to /User).
Reload the filter's editor...the value is now 1.