Archie

Overview

Archie is a "hierarchical object storage" toolkit - in fact, "Archie" stands for "hierarchy". The Ubik distributed computing framework uses Archie to support its JNDI implementation.

Features

  • Objects are bound to names in a hierarchical datastructure;
  • hierarchy traversal strategies are decoupled from datastructure (allows implementing you own strategies);
  • interface-based design: roll your own (you could for example easily back your implementation with an object-oriented database);
  • convenient in lots of situations (isn't Log4j using such a hierarchy internally? internationalization could also be a candidate...);
  • provides a basic JNDI implementation that can easily be augmented if needed.

Design

Get the following and you're off:

  • A hierarchy is a tree of Nodes.
  • A hierarchy has a single root Node.
  • Nodes of a given type are instantiated by a NodeFactory.
  • A NameParser parses strings into Names.
  • A Name is composed of one to many NamePart(s).
  • The "local name" of a node is modeled as a NamePart. The local name of a node is unique in the context of that node's parent.
  • The "absolute path" of a node is in fact its full path in the node hierarchy; that path is the node's full-qualified Name.
  • You can manipulate nodes yourself, but most of the time you'll use an Archie instance to do so.

Learning by Example

The examples below should prove a thorough enough introduction. For more details, see the javadoc and the test cases.

Archie API

Creating a Hierarchie from Scratch

import org.sapia.archie.*
import org.sapia.archie.impl.DefaultNodeFactory;

...

  NodeFactory fac = new DefaultNodeFactory();
  
  // note that the Archie class only needs the root node. 
  // the Node interface provides all the functionality that
  // the Archie class needs to create, lookup and remove nodes.
  Archie arch = new Archie(fac.newNode());
..

Binding an Object

NameParser parser = arch.getNameParser();
  
  
  Name name = parser.parse("some/path/foo");
  
  // No, class Foo is not in the API, don't look for it...  
  arch.bind(name, new Foo());

Looking Up

With archie, you can lookup objects, nodes, and you can use/implement lookup strategies.

NameParser parser = arch.getNameParser();
  
  // looking up an object...
  Name name = parser.parse("some/path/foo");
  Foo f = (Foo)arch.lookup(name);
  
  // looking up a node...
  Name name = parser.parse("some/path");
  Node node = arch.lookupNode(name);  
  f = (Foo)node.getValue(parser.parseNamePart("foo"));
  
  // using some lookup strategy: this one would lookup
  // a value at a given node - under a given name, and 
  // go up to the parent nodes if no value would be found
  // at that node, under that name.
  ReverseLookupStrategy reverse = new ReverseLookupStrategy();
  Foo f = (Foo)reverse.lookup(n, arch.getRoot());

Removing an Object

NameParser parser = arch.getNameParser();
  Name name = parser.parse("some/path/foo");
  
  // No, class Foo is not in the API, don't look for it...  
  arch.unbind(name);

You get the picture... see the javadoc for more info.

JNDI

Archie provides a basic JNDI implementation (not yet supporting the Referenceable interface, links, listeners, etc.

Usage

The following snippet illustrates how to obtain a JNDI context implemented on top of Archie:

import org.sapia.archie.impl.DefaultNodeFactory;
import org.sapia.archie.jndi.JndiContext;
import javax.naming.Context;
..
  NodeFactory fac = new DefaultNodeFactory();
  Context ctx = new JndiContext(fac);
...

From then on, you use the JNDI API as you do normally. Of course, instantiating a JNDI Context like this is not standard practice. Rather, you should implement your own InitialContextFactory.

Conclusion

Use Archie to store objects hierarchically. Implement your own lookup strategies, you own nodes, etc. Or use Archie as the basis for a JNDI provider.