I'll take a shot at explaining this, at a hopefully somewhat highish-level.
All this should be translated into online documentation, as well as
extensive in-class documentation.

GadgetServer forms the core of all server operation. It's constructed with
an Executor which provides whatever execution context you wish for Gadget
processing, eg. thread pools with varying sizes and queuing properties,
single-threaded operation, etc.

In addition, it's incumbent upon you to initialize each GadgetServer object
with the following (these used to be in the constructor; Kevin moved them
out.. I still prefer them all in ctor, but for this discussion it doesn't
matter):

setSpecCache(GadgetDataCache<GadgetSpec>)
- Supplies an object that manages storage of GadgetSpec objects by key. The
properties of this cache are up to the implementor: eviction strategy, size,
etc.
- Stores parsed (read-only) GadgetSpec objects, essentially a POJO
representation of Gadget XML.

setMessageBundleCache(GadgetDataCache<MessageBundle>)
- Same, but for MessageBundle objects, which themselves are POJO reps of
message bundle XML, eg.
http://www.google.com/ig/modules/docs_content/en_ALL.xml

A default (unsuitable for production use) cache implementation is provided
based on a HashMap, for instance. Others might plug in an implementation
based on memcached or another distributed mechanism.

setContentFetcher(RemoteContentFetcher)
- Sets the object used for retrieving URI resources from the net at large.
- A default impl is provided that uses java.net classes for direct content
retrieval.
- Not documented yet, but proposed: this object is suggested to *not* hide
another layer of caching underneath it, so that the nocache= parameter can
reliably be made to work (without mucking with the RemoteContentFetcher
interface)

setGadgetFeatureRegistry(GadgetFeatureRegistry)
- Supplies an object in which all <Require>/<Optional> GadgetFeature
implementations are stored.

[optional] setGadgetBlacklist(GadgetBlacklist)
- Provides a mechanism by which Gadgets are blacklisted from rendering.

>From here, the processGadget() method does essentially everything. It is
supplied:
- An ID that references a Gadget (currently only URI references are valid)
- UserPrefs that apply to the rendering call.
- The locale applicable to the request.
- Whether the processing call is being done on behalf of a Gadget render, or
on behalf of a Container seeking Gadget metadata (such as Iframe information
that points at a URL that in turn will render a Gadget)
- A bundle of miscellaneous optional flags that influence rendering behavior
eg. ignoreCache.

processGadget() returns a Gadget object. This object represents a
fully-processed GadgetSpec given the above context, and contains information
sufficient to fully describe a rendered (or to-be-rendered, in the Container
case) gadget.

What processGadget() does:
1. Enqueues a GadgetSpec "load from cache" task.
2. Enqueues a GadgetSpec "load from XML" task, with a dependency on #1.
3. Enqueues a GadgetSpec "save to cache" task, with a dependency on #2
(NOTE: this is currently bundled serially with #2 - this will change to
allow asynchronous cache writes)
4. Inspects the GadgetSpec to be processed, noting all the
<Require>/<Optional> features it has declared, and creates a dependency tree
of GadgetFeature processing tasks from them as follows.
  4a. For each feature, consults the GadgetFeatureRegistry for a
GadgetFeature by the requested name.
    4a.i. If not found and <Require>, sets an error to be emitted
(FEATURE_UNSUPPORTED).
    4a.ii. If not found an <Optional>, injects code into the Gadget output
object indicating that gadget.hasFeature("name") should return false.
    4a.iii. If found, moves on to 4b.
  4b. Creates a FeaturePrepare and FeatureProcess task, whose responsibility
it is to run the GadgetFeature.prepare(GadgetSpec) and
GadgetFeature.process(Gadget)
methods. These methods do actual feature processing. Each task is marked as
dependent on all the GadgetFeature's registered dependencies. These
dependencies are registered with the aptly named GadgetFeatureRegistry.
5. Starts main processing loop.
  5a. Loops through all enqueued tasks, sending all whose dependencies have
been completed to the Executor passed into the GadgetServer. (@
GadgetServer.java:142)
  5b. Waits until at 1 currently-running task has completed. (@
GadgetServer.java:152)
  5c. If the task failed, adds an error to be emitted (@GadgetServer.java:165)
and indicates to the remaining queue of to-be-completed tasks not to run (@
GadgetServer.java:182), since doing so would lead to unspecified behavior
and would inevitably fail anyway.
  5d. Go back to 5a until all tasks are completed. Note that the task is
marked as "done" in the dependencies-completed list in either case (@
GadgetServer.java:504)
6. Return the processed Gadget object.

There's a lot of scaffolding in place that facilitates creation of this
GadgetFeature graph and the context required to execute it, namely the
GadgetServer.WorkflowContext and GadgetServer.WorkflowTask subclasses. I'd
be happy to describe their operation in further detail if desired.

Hope this helps as a start. I'm sure much is missing - happy to fill in the
blanks where useful.

--John

On Tue, Jan 22, 2008 at 8:12 PM, Akash Xavier <[EMAIL PROTECTED]>
wrote:

> Yeah Brian is right.
> I am too waiting for the same... I got bored of reading the php code to
> figure out which way we are going. It would be nice if someone could
> explain
> how the java version works, so we can know what's done and what's to be
> done.
>
> On Jan 22, 2008 7:36 PM, Kevin Brown <[EMAIL PROTECTED]> wrote:
>
> > I'll explain it in detail in a few hours...right now I've got to drive
> > home
> > :)
> >
> > On Jan 22, 2008 6:13 PM, Brian McCallister <[EMAIL PROTECTED]> wrote:
> >
> > > Any chance someone familiar with the Java and JS in Shindig could
> > > explain the interactions enough that when I trace through I can follow
> > > intent rather than guessing?
> > >
> > > I want to change the PHP side to behave, to all appearances,
> > > identically to the Java so that the same javascript can be used. Aside
> > > from that, the PHP needs some gutting and cleaning :-)
> > >
> > > -Brian
> > >
> >
>
>
>
> --
> Akash Manohar
> [EMAIL PROTECTED]
>

Reply via email to