Context Discovery Components

From Eclipsepedia

Jump to: navigation, search

This page describes various XRI/XRDS/XDI based components of Higgins which are used for configuring context factories and discovering contexts. See also Context Discovery and ContextId.

Note that there is also another way of doing everything mentioned on this page. This other way uses the Configuration API instead of XRDS documents and is described on Context Discovery Components Without XRDS.

Contents

ConfigurationHandler for XRDS

ConfigurationHandlers are responsible for reading from a configuration source and for building a map. The ConfigurationHandler for XRDS is able to read configuration from an XRD service endpoint. It is based on the ConfigurationHandler for XML and therefore works very similar.

The ConfigurationHandler for XRDS is used by other XRI-related parts of Higgins, e.g. the IdASRegistry.

Relation to ConfigurationHandler for XML

The ConfigurationHandler for XRDS uses XML elements in the namespace http://higgins.eclipse.org/Configuration inside the XRDS <Service> element.

These elements are exactly the same as the ones used by the ConfigurationHandler for XML.

Example

Here is an example XRDS service endpoint, from which a configuration map can be constructed:

<Service priority="10" xmlns:hconf="http://higgins.eclipse.org/Configuration">

	<Type>$context+ldap</Type>
     	
	<hconf:Configuration
		xmlns="http://higgins.eclipse.org/Configuration"
		xmlns:hconf="http://higgins.eclipse.org/Configuration">
     
		<SettingHandlers>
			<SettingHandler Type="xsd:integer" Class="java.lang.Integer"
				Handler="org.eclipse.higgins.configuration.xml.IntegerHandler"/>
			<SettingHandler Type="hconf:map" Class="java.util.Map"
				Handler="org.eclipse.higgins.configuration.xml.MapHandler"/>
		</SettingHandlers>
				
		<Setting Name="TestComponentConfig" Type="hconf:map">
			<Setting Name="firstSetting" Type="xsd:integer">10</Setting>
			<Setting Name="secondSetting" Type="xsd:integer">20</Setting>
		</Setting>

	</hconf:Configuration>

</Service>

The following Java code could be used to build a configuration map from this service endpoint:

	Service sep = ...;	// obtain a service endpoint from somewhere

	ConfigurationHandler handler = new ConfigurationHandler();
	handler.setSEP(sep);
	handler.configure(null);
	Map configuration = handler.getSettings();
	
	if (((Integer) configuration.get("firstSetting").intValue()) == 10) { ... }

Discovery

The discovery component is responsible for retrieving XRDS documents and service endpoints. It makes use of the OpenXRI client and syntax packages to achieve this. The Discovery component can obtain XRDS documents and service endpoints in various ways, including from a stream, from a local file or via XRI resolution.

Example

The following code can retrieve an XRDS document and service endpoints from a local file:

	IDiscovery discovery = new FileDiscovery(new File("test.xrds"));

	XRDS xrds = discovery.discoverXRDS();
	List list = discovery.discoverAllServices();
	Service sep = discovery.discoverService(null, null, "/home");

IdASRegistry

The IdASRegistry is responsible for registering context factories. The following services are offered:

  • Initialize itself from an XRDS document. This can come from a local file, from XRI resolution or from other sources (see Discovery component). Each service endpoint in that XRDS document describes a context factory and includes one or more <Type> elements, which describe the context types that can be opened by the context factory.
  • Discover, instantiate and configure a context factory based on a ContextId. This is the core service of IdASRegistry.
  • Discover, instantiate and configure a context factory based on a context type (a String).
  • Enumerate all registered context factories.
  • Add an already instantiated and configured context factory to the registry. This is a secondary service and in most cases should not be necessary.

In order for a context factory to be automatically configured by the IdASRegistry, it must implement the IConfigurableComponent interface (see the Configuration component).

IdASRegistry uses the Discovery component to retrieve XRDS documents and service endpoints. Per default, it uses a local XRDS file to obtain the required information, but this can be changed to use XRI resolution instead.

IdASRegistry employs a cache, so that context factories can be re-used and do not have to be instantiated every time. This cache is very simple and by default enabled. If it is enabled, the context factory instances never become stale. The idea is that if the IdASRegistry is configured from a local file, you enable caching, since you don't expect the file to change. If you configure the IdASRegistry to initialize itself from a URI or XRI, you disable caching, so every time a context factory is requested, the XRDS is freshly discovered and a context factory chosen, instantiated and configured.

IdASRegistry uses the ConfigurationHandler for XRDS to read configuration data from service endpoints, which is then fed into newly instantiated context factories via the IConfigurableComponent interface.

By default, the IdASRegistry initializes itself from a file named "contextfactories.xrds" in the classpath, but this can be changed by calling setContextFactoryDiscovery() on the registry, passing it any implementation of the IDiscovery interface (see examples below).

Context Types

Context types are strings that establish the association between a ContextId and a context factory. IdASRegistry uses the context type to find a suitable context factory. See ContextTypes for a list of context types used in Higgins.

Example

The following is an example XRDS document from which the IdASRegistry can initialize itself. It contains definitions of two context factories along with context types and configuration data. The first context factory can instantiate contexts of two different types ($context+ldap and $context+jdbc). The second one can only instantiate contexts of a single type ($context+ldap), which is the usual case.

<XRDS xmlns="xri://$xrds">
	<XRD xmlns="xri://$xrd*($v*2.0)">
		<Query>*registry</Query>
		<Status code="100"/>  
		<Expires>2999-01-01T00:00:00.000Z</Expires>  
		<ProviderID>xri://@higgins</ProviderID>  
		<LocalID priority="10">!1</LocalID>  
		<CanonicalID priority="10">@!7F6F.F50.A4E4.1133!1</CanonicalID>  

		<Service priority="10" xmlns:hconf="http://higgins.eclipse.org/Configuration">

			<Type select="true">$context+ldap</Type>
			<Type select="true">$context+jdbc</Type>

			<hconf:Class>org.eclipse.higgins.markus.idas.registry.test.TestContextFactory1</hconf:Class>

			<hconf:Configuration xmlns="http://higgins.eclipse.org/Configuration" xmlns:hconf="http://higgins.eclipse.org/Configuration">

				<SettingHandlers>
					<SettingHandler Type="xsd:integer" Class="java.lang.Integer" Handler="org.eclipse.higgins.configuration.xml.IntegerHandler"/>
					<SettingHandler Type="xsd:string" Class="java.lang.String" Handler="org.eclipse.higgins.configuration.xml.StringHandler"/>
				</SettingHandlers>
				
				<Setting Name="TestComponentConfig" Type="htf:map">
					<Setting Name="value" Type="xsd:integer">10</Setting>
					<Setting Name="policy" Type="xsd:string">Hello World</Setting>
				</Setting>

			</hconf:Configuration>

		</Service>

		<Service priority="10" xmlns:hconf="http://higgins.eclipse.org/Configuration">

			<Type select="true">$context+ldap</Type>

			<hconf:Class>org.eclipse.higgins.markus.idas.registry.test.TestContextFactory2</hconf:Class>

			<hconf:Configuration xmlns="http://higgins.eclipse.org/Configuration" xmlns:hconf="http://higgins.eclipse.org/Configuration">

				<SettingHandlers>
					<SettingHandler Type="xsd:integer" Class="java.lang.Integer" Handler="org.eclipse.higgins.configuration.xml.IntegerHandler"/>
					<SettingHandler Type="xsd:string" Class="java.lang.String" Handler="org.eclipse.higgins.configuration.xml.StringHandler"/>
				</SettingHandlers>
				
				<Setting Name="TestComponentConfig2" Type="htf:map">
					<Setting Name="value" Type="xsd:integer">20</Setting>
					<Setting Name="policy" Type="xsd:string">Good Bye World</Setting>
				</Setting>

			</hconf:Configuration>

		</Service>
	</XRD>
</XRDS>

The following code demonstrates how the IdASRegistry can be used to get a context factory for a given context type. It is possible that for a given context type multiple context factories are found, in which case a list can be requested from IdASRegistry:

	IdASRegistry registry = IdASRegistry.getInstance();

	IContextFactory factory = registry.getContextFactory("$context+jdbc");
	List factories = registry.getContextFactories("$context+ldap");
	List allFactories = registry.getContextFactories();

	registry.registerContextFactory("$context+ldap", myExistingFactory);

  By default, the IdASRegistry is initialized from a file named "contextfactories.xrds" in the classpath. Maybe we want to initialize it in a different way:

	IdASRegistry registry = IdASRegistry.getInstance();

	registry.setContextFactoryDiscovery(new FileDiscovery("myregistry.xrds"));   // this reads the registry configuration from a local XRDS file
	registry.setContextFactoryDiscovery(new StreamDiscovery(myInputStream));   // this reads an XRDS file from a stream
	registry.setContextFactoryDiscovery(new YadisDiscovery("http://www.eclipse.org/higgins/myregistry.xrds"));  // this uses Yadis discovery to obtain an XRDS file
	registry.setContextFactoryDiscovery(new ResolutionDiscovery("@higgins*registry"));   // this performs XRI resolution to obtain an XRDS file

Or maybe we want to use a specific classloader to instantiate the context factories:

	registry.setClassLoader(myClassLoader);

We can disable caching, so every time a context factory is requested, the XRDS is freshly discovered and a context factory chosen, instantiated and configured.

	registry.setCaching(false);

IContextId

In Higgins, a ContextId is an identifier that uniquely identifies a Context. Higgins Identity Attribute Service is a service that can resolve a ContextId to a Context.

To model this, a new interface IContextId is introduced.

Technically, a ContextId can do the following things:

  • Given a ContextId one can find the sole context descriptor. This context descriptor contains:
    • 1..N context types (strings) (one is most common)
    • 0..N URIs
    • 0..N Configuration
  • If the container of the context descriptor is an XRDS document:
    • The context descriptor is a Service Endpoint (SEP).
    • Within the SEP the context type is represented by the XRD <Type> element.
    • Within the SEP the URI is represented by the <URI> element.
    • Within the SEP the Configuration is represented as described above.

Instantiating a Higgins Context object (instance of IContext) from a given ContextId involves three steps:

  1. The first step is to find the context descriptor.
  2. The next step is to use the context type to find a suitable context factory.
  3. The context is instantiated by the context factory. The factory may or may not make use of the other two pieces of information associated with a ContextId (URIs and a configuration map).

The first two steps above are managed by the IdASRegistry. IdASRegistry uses the Discovery component to retrieve XRDS documents and service endpoints. From this data, IdASRegistry is able to find a factory that can open a context of the desired type.

If the container of the context descriptor is an XRDS document then IContextId implementations use the ConfigurationHandler for XRDS to read configuration data from service endpoints.

ContextId Identifier Formats

A Higgins ContextId is a string that can take one of three formats:

  1. A local filename expressed natively or as a file: URI.
  2. A relative or absolute HTTP(S) URI.
  3. A relative or absolute XRI.

More details and examples about the format of this identifier can be found here: ContextId

Starting with a Higgins ContextId string you can obtain an implementation of the IContextId interface (see examples below). If the underlying data structure referenced by ContextId is an XRDS document, the following resolution rules apply:

  • For a local filename, the filename extension SHOULD be ".xrds". Note that a local filename may also be expressed as a file: URI.
  • For an HTTP(S) URI, resolution to an XRDS document is defined by section 4 of XRI Resolution 2.0 Working Draft 11.
  • For an XRI, resolution to an XRDS document is defined by the balance of XRI Resolution 2.0 Working Draft 11

Note to Markus: we will need to update the links above as we finalize XRI Resolution 2.0.

Definition

This is the definition of the IContextId interface, reflecting the requirements stated above.

	public interface IContextId {

		public String[] getTypes() throws IdASException;
		public URI[] getUris() throws IdASException;
		public Map getConfiguration() throws IdASException;
	}

To obtain an appropriate IContextId implementation from a given string/file/XRI/..., the class ContextIdFactory provides several helper methods.

Example

This is an example XRDS file that contains a descriptor (service endpoint) for one context. The <Type> element in the service endpoint is the context type, which is used by IdASRegistry to find a suitable context factory. In addition, in order for XRI service endpoint selection to be successful, a default <Type> must be present.

The contents of the <URI> and <Configuration> elements (both are optional) can be retrieved via the IContextId interface and are intended to be used by context factories to instantiate and configure the context.

<XRDS xmlns="xri://$xrds">
	<XRD xmlns="xri://$xrd*($v*2.0)">
		<Query>*mycontext</Query>
		<Status code="100"/>  
		<Expires>2999-01-01T00:00:00.000Z</Expires>  
		<ProviderID>xri://@</ProviderID>  
		<LocalID priority="10">!12345</LocalID>  
		<CanonicalID priority="10">@!12345</CanonicalID>  

		<Service priority="10" xmlns:hconf="http://higgins.eclipse.org/Configuration">

			<Type>$context+jdbc</Type>
			<Type match="default" />

			<URI>jdbc:postgresql://192.168.1.102/mydatabase</URI>

			<hconf:Configuration xmlns="http://higgins.eclipse.org/Configuration" xmlns:hconf="http://higgins.eclipse.org/Configuration">

				<SettingHandlers>
					<SettingHandler Type="xsd:string" Class="java.lang.String" Handler="org.eclipse.higgins.configuration.xml.StringHandler"/>
				</SettingHandlers>
				
				<Setting Name="TestContext" Type="htf:map">
					<Setting Name="username" Type="xsd:string">dbuser</Setting>
					<Setting Name="password" Type="xsd:string">dbpass</Setting>
				</Setting>

			</hconf:Configuration>

		</Service>

	</XRD>
</XRDS>

The following code demonstrates how to obtain an IContextId object from a context ID string, and how to use IdASRegistry to find a suitable IContextFactory:

	IdASRegistry registry = IdASRegistry.getInstance();

	IContextId contextId1 = ContextIdFactory.getInstance().fromFile("mycontext.xrds");    // construct a context ID from a local file
	IContextId contextId2 = ContextIdFactory.getInstance().fromUrl("http://myserver.org/yadisdoc.html");    // construct a context ID from a URL (using Yadis)
	IContextId contextId3 = ContextIdFactory.getInstance().fromXri("@higgins*somecontext");  // construct a context ID using XRI resolution
	IContextId contextId4 = ContextIdFactory.getInstance().fromString("@higgins*somecontext");  // try to auto-detect the kind of context ID

	IContextFactory factory = registry.getContextFactory(contextId1);

	IContext context = factory.createContext(contextId1);

If all you want is instantiate an IContext from a context ID, the following convenience method can be used:

	IdASRegistry registry = IdASRegistry.getInstance();

	IContext context = registry.createContext("@higgins*somecontext");

How to update your existing context provider

In order to integrate your context provider (context factory and context implementations) with these XRI/XRDS based components, the following guidelines may be helpful:

  • In order for the IdASRegistry to find your context factory, it needs a service endpoint in the XRDS document used by IdASRegistry. This service endpoint needs <Type> elements for all the context types your factory can instantiate. It can optionally have configuration elements (see examples on this page).
  • When the IdASRegistry finds and instantiates a context factory, it checks whether the factory implements the IConfigurableComponent interface. If yes, the discovered factory configuration will automatically be handed to the factory via the IConfigurableComponent.configure() method. So your context factory should implement this interface (if it does not already...)
  • To instantiate a context, an IContextId is used. From an IContextId you can get three things: Context type(s) (this is intended only to be used internally by the IdASRegistry), URIs and a configuration map (both the URIs and map are intended to be used by your context to configure itself).
  • Your context factory must be able to fully instantiate and configure an IContext based on the information that can be obtained from an IContextId
  • An IContextId is usually created from an XRDS document (retrieved from a URL, read from a file, constructed using XRI resolution, or other means). For testing purposes it is probably easiest to work with a local file. An IContextId can be obtained from a local XRDS file by calling ContextIdFactory.getInstance().fromFile("mycontext.xrds");
  • If anything on this page looks stupid, or if it does not meet the requirements of your use cases, tell Markus

Implications for other Higgins components

  • Does the IdASRegistry need to be able to store a number of pre-defined contexts in addition to context factories? I think no... Jim and others?
  • [Jim] Maybe it would be good to make IContextFactory define a getInstance method that is called, and thus each CP could control its own cache and staleness. I think this is something we don't need to address right now.