directory-api mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Emmanuel Lecharny <>
Subject Re: Some naming issue
Date Mon, 30 Nov 2009 16:08:30 GMT
On Mon, Nov 30, 2009 at 3:59 PM, Matthew Swift <> wrote:
> On 30/11/09 11:15, Emmanuel Lecharny wrote:
>> Hi,
>> while reviewing the proposed names, I find Schema a bit problematic
>> when it comes to cover all the schemaObjects as a whole. Openldap and
>> ADS can use more than one schema (typically, core, system, ...). At
>> this point, naming the system in charge of all the schemas something
>> like 'SchemaHandler' or 'SchemaManager' would be better...
>> thoughts ?
> Our SDK prototype supports multiple schema, each one is an instance of
> "Schema".

So I guess you have a way to manipulate all those supported Schema as
a whole. What's the name for this container ?

Since a Schema is a big heavily used object but relatively static
> we have made the class immutable. In order to create a new Schema we provide
> a SchemaBuilder class with methods like "addAttributeType", etc. Once the
> Schema is built the application converts the builder to a schema instance as
> follows:
>   SchemaBuilder builder = new SchemaBuilder();
>   builder.addAttributeType(...);
>   builder.addObjectClass(...);
>   ...
>   Schema schema = builder.toSchema();

We handle these operations quite the same, except that the schema is
not immutable per se. However, as the schemas *must* be consistent in
order to be used in the server, we don't allow modifcations that could
break the consistency. What we do (but it's implementation dependent),
is to clone the registries (the container where all the schemaObjects
are loaded), do the modification into this cloned object, chekc the
result, and if it's ok, we apply the same modification to the original

Btw, the global container for us is the SchemaManager, which hold what
we call a Registries, itself holding some xxxRegistry (a registry per
SchemaObject). We can inject more than one Schema in the
SchemaManager, and globally enable or disable a schema.

> We also provide a version of the toSchema() method which supports storage of
> error messages (e.g. missing elements):
>   List<String> messages = new LinkedList<String>();
>   Schema schema = builder.toSchema(messages);
>   for (String message : messages) {
>      // Display errors to user
>   }
> Why do we need to handle errors like this? Well because schema definitions
> may not be complete and we don't want this to prevent a client from
> proceeding or fixing the broken schema. In particular, RFC4512#4.4 states:
>       Clients SHOULD NOT assume that a published subschema is complete,
>       that the server supports all of the schema elements it publishes, or
>       that the server does not support an unpublished element.

Same here, for some othe rreasons : we need to provide Studio a way to
get *all* the errors we have in the Schemas, in order to display all
of them.

> So far in our prototype SDK we haven't needed a SchemaManager. We provide
> access to the singleton Schema objects directly from the Schema class (e.g.
> Schema.getCoreSchema(), Schema.getDefaultSchema(), etc).

Singleton ? Yuk !!! Does not fit at all if you want to embed more than
one instance of the server : typically something one can do when
writing a VD !

It also breaks the RFC : a single server might define more than one
set of Schemas for a specific branch in the tree. (RFC 4512, par. 4.2)

> For other schema (e.g. schema retrieved from a server) we were going to
> provide factory methods in the Connection/AsynchronousConnection interface
> (actually we haven't got these yet - I was going to do them today). Here's
> the idea (we'd have async versions in our AsynchronousConnection interface):

We still have to discuss all those Connection sync/Async aspects...

>   public interface Connection {
>      // Common LDAP operations.
>      Result add(AddRequest request) throws ErrorResultException;
>      ...
>      // Special LDAP operations.
>      Schema getSchemaForEntry(String dn, List<String> errors) throws
>   ErrorResultException;
>      Schema getSchemaForEntry(DN dn, List<String> errors) throws
>   ErrorResultException;
>      RootDSE getRootDSE() throws ErrorResultException;
>   }
> This would allow the Connection implementation to manage its schemas. For
> example, implementations may choose to look up schemas on demand and/or
> cache them.

I have to think about it. At first sight, IMO, if an entry has a
subschemaSubentry op attr, then it's not necessary to express the fact
that we want its schema to be loaded : it should be loade d in any

> Something we'd like to support is an "LDIF connection" - a virtual LDAP
> connection to an LDIF file. Basically we read an LDIF file into memory and
> allow client apps to "connect" to it and perform normal LDAP operations
> against it. The LDIF connection would have a faked up RootDSE and perhaps a
> faked up schema or one provided during construction of the LDIF connection.
> LDIF connections would be great when performing offline upgrades of the
> server - the upgrade tool can load the server config.ldif into memory and
> modify it without needing any of the server infrastructure available (thus
> avoiding "chicken and egg" problems).

I would rather think about it as a 'local server', storing data in a
LDIF format. As soon as you have a way to describe your storage
format, then no need to expose it to the user. We have modified our
schema handling this way : the schemas are stored as LDIF, and we have
a specific partition for this part of the server, whcih storage is
described as LDIF based. From the user POV, it's totally transparent.
We just have to tell the server that this 'partition' (a branch in the
DIT) is ldif backed, and associate a LdifLoader to the server for this

But this is implementation dependent again :)

What I mean is that we should *never* expose the underlying storage to the user.

> One problem with multiple schema support is decoding search result entries.
> We should decode the search result entry using the schema identified in its
> subschemaSubentry operational attribute. However, there are various
> problems:

That's for sure. But if you don't have any, then you will use the
default schemas.

>   * The subschemaSubentry attribute may not be supported by the
>     server, it may be filtered by the server (e.g. access control), or
>     it may not have been requested by the client. In the latter case,
>     we could add the attribute to the list of attributes requested in
>     every search request but that's a bit naughty in my opinion.

If a server does not support SSSE, there is a problem anyways...
Should we support them ? Whcih server does not support this part of
the RFC ?

>   * The subschemaSubentry attribute could occur anywhere in the list
>     of attributes returned in the entry requiring two passes in order
>     to decode the returned entry :-( This is not very efficient.
Hmmm... You have the very same problem with the ObjectClass, which is
obviously needed too. I don't see that as an issue...

> I haven't quite figured out the best approach for schema discovery so far -
> certainly using the subschemaSubentry operational attribute seems quite
> cumbersome. We could implement LDAP connections such that they *optionally*
> perform a search for all subschema sub-entries in the server immediately
> after bind.

Well, IMHO, SSSE is the way to go, and too bad for the crippled
servers which don't support it :)

> I think schema support and especially multiple schema support is hard.

I hear you !!! It's one of the most complex part of LDAP, that's for sure !

> decoding a DN becomes complicate because individual RDN components may be
> associated with different schema! Yuck! :-(

Bleh :/ Feel the same :)

Emmanuel L├ęcharny

View raw message