It is important to understand how resolver works when you want to create a proxy agent. A proxy agent is an agent that works behind the scenes to examine a document request, a document response, or both with a view to transforming the document in some way. So, the key items of interest for an agent are: how do I make sure I have the right kind of document, how do I get at its content, and how do I make sure that the transformation is done at the right time?
These are the two main opportunities for an agent to interact with the
resolver
: during the initial document request, or when
the response to that request is received. Most agents are interested
in intercepting the response; it is then that an actual document is
being returned. Usually, an agent will be performing some kind of
processing on the document content. When a request is made, the only
information that is available to an agent is the url of the document
being requested.
Two examples of proxy agents are:
The diagram below shows how the pia's algorithm works.
When the PIA starts up, it creates the resolver
and
registers all agents listed in the START-UP.html
file.
As other agents are installed, they will also be registered with the
resolver
; consequently, the resolver
always
knows about all available agents.
As the first step in the processing cycle, an object called the
Accepter
accepts a request and creates a
Machine
object and a Transaction
object. The
machine keeps track of where the request came from, which will also be
the place where the ultimate response will be coming back to. The
Transaction
object represents http requests and
responses.
Once the Transaction
is created it is pushed on to the
Resolver
stack. The Resolver
does its work
inside a thread, and each Transaction
also starts up its
own thread. Within its thread, the Resolver
is taking
Transaction
s off an internal stack. For each
Transaction
, the Resolver
goes through its
list of registered agents and looks at each agent's criteria to
determine whether there is a match. If an agent's features match, the
agent's actOn method is called and the Resolver
notifies
the Transaction
that it should resolve itself.
Meanwhile, the Transaction
also has its own thread.
Within its thread, the Transaction
goes through its
handlers, and for each handler, calls its handle method. At least one
must return true, otherwise the Transaction
will satisfy
itself by sending its content to the stream defined by its
"toMachine". So, where do these handlers come from?
Resolver
examines a request
Transaction
, if the request includes an agent's name, the
Resolver
places the agent on the
Transaction
's list of handlers.Transaction
's list of
handlers. For example the Cache agent pushes itself onto its
Transaction
's handler list so that when the actual
document is received in the form of a response, the agent can decide
whether to cache it or not. Basically, the agent adds itself to a
handler list so that further processing can occur when the document
contents have been retrieved.
A Transaction
could have any number of handlers, but in
practice, is usually has zero or one. For each handler it returns
true and the Transaction
exits, or is satisfied. In
instances where there are no handlers or no handlers that return true,
the defaultHandle
method is called. By default, this
method generates a response, which is to send the content to the
machine from which the request originated. In effect, it tells the
destination machine to handle the request. If an agent handles the
request, it creates the response and sets itself as the originating
machine.
Resolver
Resolver
algorithm.
initialize
MethodResolver
. The static Criterion.toMatch
method is used to specify the features to match against. For example,
an agent that wants to intercept all pages that are of type html will
use the Criterion.toMatch("IsHtml", true)
. A
number of criteria can be specified in this manner; however, it should
be noted that these will be and'ed together, so it is important that
they do not cancel each other out.
A list of available features to match on are located in the
pia/src/java/org/risource/tf
subdirectory. They are
UnaryFunctor
subclasses that work essentially as function
pointers would in C++. It is straightforward to extend this
collection of classes as the need arises. Standard features to match
against are either the IsRequest
or
IsResponse
feature, depending on which part of the
processing cycle you wish to intercept.
actOn
MethodactOn
method is used when an agent needs to modify
the Transaction
--typically by modifying the
Transaction
's Content
object. This
Content
object contains the document input and output
stream. It is this data that can be transformed in some way, and
replaced in the Transaction
or added to a new
Transaction
. The newly transformed content will then be
displayed in the browser.
In the Cache agent, the actOn
method is used to handle
both requests and responses. If the Transaction
is a
request for a document, the Cache agent checks the cache. If the
document is in the cache, it returns the cached version. Otherwise
the document is passed on for normal processing.
When the Transaction
is a response, the
actOn
method adds a tap to the data stream. The tap for
this agent, creates a FileOutputStream
for writing the
data to file (in order to cache it). The agent addTap
method gets the contentObject
from the
Transaction
(an object of type Content
) and
adds the tap to this object with the FileOutputStream
as
an argument. When the contentNotifyWhen
method is
called, the Cache agent's updateContent
method is called.
This writes the document to the FileOutputStream
and also
makes an entry in a hashtable linking the cached document file to the
document url.
handle
MethodTransaction
that
has already been matched by an actOn
method. For example
the actOn
method may have intercepted a document request
and done some preliminary processing in anticipation of doing further
processing on the document content when a document response is
received. The actOn
method will have placed the agent on
the Transaction
's handler queue so that its handle method
can be called. For example, the Cache agent sets a flag in the
request actOn
method to indicate whether the data can be
read from the cache rather from the actual URL. It uses the
handle
method to read a cached document from file and
creates a new content object from the file data rather than from the
source specified by the user.
respond
Methodrespond
method
to create the Transaction
that responds to that request.
For example, in the Camera agent, the respond method intercepts a
request for a camera image. The method checks whether the URL includes
a gif extension. If it does, it creates a response
Transaction
, reads the camera image data from file, and
sets the Content
object to the image data, and starts the
processing thread.