Interfacing PTMK with Jigsaw and HotJava

This document describes the environment where the kernel (PTMK) is run in my project. In short, PTMK is implemented as an "IngoingFilter" under Jigsaw HTTP Client package, and Jigsaw Client package is run under HotJava web browser.
        HotJava  
----------------------------
   Jigsaw Client package
----------------------------
PICS Trust Mgt Kernel (PTMK)
----------------------------
  Profile-0.9 Interpreter

HotJava

Sun's HotJava is a full-blown web browser written entirely in Java language. It is now in its 1.0-prebata release. HotJava is chosen because it interfaces nicely with Jigsaw Client API.

To use Jigsaw Client package under HotJava, all you need to do is to change java.protocol.handler.pkgs property to w3c.www.protocol before launching HotJava.

Jigsaw HTTP Client Package

Jigsaw is originally designed as a web server, whose purpose is to provide a basis for experimenting new server-side features. Recently it is extended to provide a HTTP Client API.

The API is very simple: it takes in a Request (generally a URL) and returns a Reply (the content of the URL). In general, this HTTP Client API serves similar function as the standard java.net.URLConnect class, but this API is much more robust and modular.

A typical loop inside the Jigsaw Client looks like the following:

       | Request from Caller       ^ Reply to Caller
      \ /                          |
-------------------------------------- 
|          HttpManager               |
--------------------------------------
       |   Request                 ^
      \ /                          |
------------------  Reply          |
| IngoingFilters |---------------> |
------------------                 |
       |   Request                 |
      \ /                          |
-------------------                |
| HttpConnection  |                |
-------------------                |
       |   Request, Reply          |
      \ /                          |
-------------------    Reply       |
| OutgoingFilters |--------------> |
-------------------                |
       |                           |
       -----------------------------

PTMK (the kernel) as an IngoingFilter

Under this architecture, the kernel can be implemented as a filter. It will be an IngoingFilter for both performance reason and security reason; you don't want to fetch the document and later realize you don't need it, and you don't want cache filter to return the document before PTMK has a chance to speak.

To be a valid instance of a Jigsaw filter, you need to implement three methods: Initialization, ingoingFilter, and outgoingFilter. In PTMKFilter, Initialization defines the default interpreter and script to run, as well as various callback. IngoingFilter sets the statement list, invoke the interpreter and examine the returned statement list. OutgoingFilter does nothing in this case.

Here are some pseudo-codes for class PTMKFilter .

Fetch Callback

It is trickier to define a proper fetch callback when PTMK is treated as a filter in Jigsaw Client package. So I devote the rest of the document on this. Below are my observations: Based on these observations, fetch callback should simply calls the HttpManager recursively, but with one difference: it will not call the PTMKFilter to prevent infinite loop. And now you get all the features such as caching, and cookie handling for free.

Here are some pseudo-codes for Fetch Callback .

Other Concerns

Next Step


Appendix: pseudo code for PTMKFilter

public class PTMKFilter implements PropRequestFilter {

    public void initialize(HttpManager manager) {
      // set default profile interpreter
      // set default script (policy) for the interpreter
      // set the fetch callback
      // set the default ptmk_cb

      // install as a global filter
      this.manager = manager;
      manager.setFilter(this);
      manager.setAllowUserInteraction(true);
    }

    // the kernel
    public Reply ingoingFilter(Request request) {
	return null;

      // generate the initial two statements and the statement list.
      Statement userRequest = new Statement("USER", 
                               "("+Request.getMethod()+" "+ Request.getURL()", 
                               "http://actions-v1");
      Statement userProfile = new Statement("application",
                                this.defaultScript,
                                "http://labels");
      StatementList stmtList = new StatementList();

      // put both statements in the statement list.  UR and UP are the IDs
      // of the statement in the statement list.
      int UR = stmtList.add(userRequest);
      int UP = stmtList.add(userProfile);

      // provides pointer to the user request and the script for the 
      // interpreter
      stmtList.ptrUserRequest = UR;
      stmtList.ptrUserProfile = UP;
      
      // invoke the interpreter
      StatementList replyStmtList = this.defaultInterpreter.eval(stmtList);
      
      // generateReply looks at the statement list, returns null
      // if the request is granted, or returns a "sorry, viewing URL is
      // not allowed" Reply if not.
      return(generateReply(replyStmtList));
    }

    // do nothing
    public Reply outgoingFilter(Request request, Reply reply) 
	throws HttpException
    {
       return(null);
    }
}

Appendix: pseudo code for Fetch Callback

public InputStream fetch_callback(String url) {

   // Get the manager
   HttpManager manager = HttpManager.getManager();

   // exclude PTMKFilter
   RequestFilter filter = getGlobalFilter(PTMKFilter);
   manager.setFilter(null, *, filter);

   // create the request
   Request request = manager.createRequest();
   request.setURL(new URL(args[0]));
   request.setMethod("GET");

   // run the request and return the reply
   Reply     reply   = manager.runRequest(request);
   return(reply.getInputStream());
}