You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2006/11/02 20:22:00 UTC

svn commit: r470483 - in /directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core: configuration/ schema/

Author: elecharny
Date: Thu Nov  2 11:21:59 2006
New Revision: 470483

URL: http://svn.apache.org/viewvc?view=rev&rev=470483
Log:
Applied Norval patch for dynamic schemas

Added:
    directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/configuration/SchemaLoader.java
    directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/schema/FileSystemSchemaLoader.java
    directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/schema/RegistrySchemaProducer.java
    directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/schema/SchemaFromFileConverter.java
    directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/schema/SchemaFromSearchConverter.java
    directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/schema/SchemaProducer.java

Added: directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/configuration/SchemaLoader.java
URL: http://svn.apache.org/viewvc/directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/configuration/SchemaLoader.java?view=auto&rev=470483
==============================================================================
--- directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/configuration/SchemaLoader.java (added)
+++ directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/configuration/SchemaLoader.java Thu Nov  2 11:21:59 2006
@@ -0,0 +1,20 @@
+package org.apache.directory.server.core.configuration;
+
+import org.apache.directory.server.core.schema.bootstrap.BootstrapRegistries;
+import org.apache.directory.server.core.schema.Registries;
+
+import java.util.Collection;
+
+
+/**
+ * Can be implemented by classes wishing to load schemas dynamically at server startup (refer to
+ * {@link org.apache.directory.server.core.configuration.StartupConfiguration#getSchemaLoaders()}).
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev: 437012 $, $Date: 2006-08-26 09:25:30 +1000 (Sat, 26 Aug 2006) $
+ */
+public interface SchemaLoader
+{
+    /** Load schemas into provided registries, and then return them. */
+    public Collection loadSchemas(final StartupConfiguration startupConfiguration, final Registries registries);
+}

Added: directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/schema/FileSystemSchemaLoader.java
URL: http://svn.apache.org/viewvc/directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/schema/FileSystemSchemaLoader.java?view=auto&rev=470483
==============================================================================
--- directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/schema/FileSystemSchemaLoader.java (added)
+++ directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/schema/FileSystemSchemaLoader.java Thu Nov  2 11:21:59 2006
@@ -0,0 +1,142 @@
+package org.apache.directory.server.core.schema;
+
+
+import java.util.*;
+import java.io.File;
+import java.io.FilenameFilter;
+
+import org.apache.directory.server.core.configuration.StartupConfiguration;
+import org.apache.directory.server.core.configuration.SchemaLoader;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ *   Allows a filesystem directory name can be specified, in which case it will be scanned for OpenLDAP
+ * formatted .schema files and their contents returned. This is a more dynamic alternative (but works in
+ * addition to) the scheme were schemas are built into the release via the Maven2 plug-in.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev: 437012 $
+ */
+public class FileSystemSchemaLoader implements SchemaLoader
+{
+    private static final Logger log = LoggerFactory.getLogger( FileSystemSchemaLoader.class );
+
+    private final String        directoryName;
+    private final String        fileNameRegex;
+    private final List          fileNames;
+
+
+    // ------------------------------------------------------------------------
+    // Constructor
+    // ------------------------------------------------------------------------
+
+    /** Calls <code>FileSystemSchemaLoader(null, (String)null)</code>. */
+    public FileSystemSchemaLoader()
+    {
+        this(null, (String)null);
+    }
+
+    /**
+     *   Loads all files in specified directory that match the specified regex, after they have been
+     * sort alphabetically. Note that you must ensure, using lexicographical ordering, that schema files
+     * are loaded before any files that are dependant on them.
+     *
+     * @param directoryName     Directory to be read, if null the "./" will be used.
+     * @param fileNameRegex     Regular expression which file names need to match, if null
+     *      then <code>".*_openldap.schema"</code> will be used.
+     */
+    public FileSystemSchemaLoader(final String directoryName, final String fileNameRegex)
+    {
+        this.directoryName = directoryName;
+        this.fileNameRegex = fileNameRegex;
+        this.fileNames = null;
+    }
+
+    /**
+     *   Loads named files under the specified directory in strict order.
+     *
+     * @param directoryName     Directory to be read, if null the "./" will be used.
+     * @param fileNames         Names of files under directoryName to load, in order (a schema
+     *      file must appear before any files that are dependant on it).
+     */
+    public FileSystemSchemaLoader(final String   directoryName, final List fileNames)
+    {
+        this.directoryName = directoryName;
+        this.fileNames = fileNames;
+        fileNameRegex = null;
+    }
+
+    public String getDirectoryName()
+    {
+        return directoryName;
+    }
+
+    public Collection loadSchemas(final StartupConfiguration startupConfiguration, final Registries registries)
+    {
+        final File          schemaDir;
+        final File[]        schemaFiles;
+        final List          files;
+        final Collection    schemas;
+
+        if (directoryName == null)
+            return null;
+
+        schemaDir = new File(directoryName);
+        if (!schemaDir.isDirectory())
+            return null;
+
+        if (fileNameRegex != null)
+        {
+            schemaFiles = schemaDir.listFiles(new FilenameFilter() {
+                public boolean accept(final File dir, final String name)
+                {
+                    return name.matches(fileNameRegex);
+                }
+            });
+            if (schemaFiles == null)
+                return null;
+            Arrays.sort(schemaFiles);
+            files = Arrays.asList(schemaFiles);
+        }
+        else
+        {
+            if ((fileNames == null) || fileNames.isEmpty())
+                return null;
+            files = new ArrayList(fileNames.size());
+            for (Iterator it = fileNames.iterator(); it.hasNext();)
+            {
+                final String    fl = (String) it.next();
+
+                files.add(new File(schemaDir, fl));
+            }
+        }
+
+        if (log.isInfoEnabled())
+            log.info("about to read " + files.size() + " schema files");
+        schemas = new ArrayList(files.size());
+        for (Iterator it = files.iterator(); it.hasNext();)
+        {
+            final File                      schemaFile = (File) it.next();
+            final String                    schemaName;
+            final SchemaFromFileConverter   schema;
+
+            schemaName = schemaFile.getName().replaceFirst("_[^_]*", "");
+            try
+            {
+                schema = new SchemaFromFileConverter(schemaName, schemaFile);
+                schema.convert(registries);
+                if (log.isInfoEnabled())
+                    log.info("read schema from '" + schemaFile + '\'');
+                schemas.add(schemas);
+            }
+            catch (Exception e)
+            {
+                log.error("failed reading schema from '" + schemaFile + '\'', e);
+            }
+        }
+        return (schemas.isEmpty() ? null : schemas);
+    }
+}

Added: directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/schema/RegistrySchemaProducer.java
URL: http://svn.apache.org/viewvc/directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/schema/RegistrySchemaProducer.java?view=auto&rev=470483
==============================================================================
--- directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/schema/RegistrySchemaProducer.java (added)
+++ directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/schema/RegistrySchemaProducer.java Thu Nov  2 11:21:59 2006
@@ -0,0 +1,456 @@
+package org.apache.directory.server.core.schema;
+
+import org.apache.directory.shared.ldap.schema.*;
+
+import javax.naming.NamingException;
+import java.util.Comparator;
+
+/**
+ *   An abstract producer implementation which doesn't make explicit reference
+ * to "bootstrap".
+ * todo: Based on org.apache.ldap.server.schema.bootstrap.AbstractBootstrapProducer
+ *      rev 226451 which should be recoded to use this more generic class.
+ */
+public abstract class RegistrySchemaProducer
+{
+    /** a reused empty String array */
+    protected static final String[] EMPTY = new String[0];
+
+    protected RegistrySchemaProducer()
+    {
+    }
+
+    protected static RegistrySchemaProducer.ConceteSchemaSyntax
+        newSyntax( String oid, Registries registries )
+    {
+        return new RegistrySchemaProducer.ConceteSchemaSyntax( oid, registries.getSyntaxCheckerRegistry() );
+    }
+
+    protected static RegistrySchemaProducer.ConcreteSchemaAttributeType
+        newAttributeType( String oid, Registries registries )
+    {
+        return new RegistrySchemaProducer.ConcreteSchemaAttributeType( oid, registries );
+    }
+
+    protected static RegistrySchemaProducer.ConcreteSchemaObjectClass
+        newObjectClass( String oid, Registries registries )
+    {
+        return new RegistrySchemaProducer.ConcreteSchemaObjectClass( oid, registries );
+    }
+
+    protected static RegistrySchemaProducer.ConcreteSchemaMatchingRule
+        newMatchingRule( String oid, Registries registries )
+    {
+        return new RegistrySchemaProducer.ConcreteSchemaMatchingRule( oid, registries );
+    }
+
+
+    /**
+     * A mutable Syntax for the bootstrap phase that uses the
+     * syntaxCheckerRegistry to dynamically resolve syntax checkers.
+     */
+    public static class ConceteSchemaSyntax extends AbstractSyntax
+    {
+        final SyntaxCheckerRegistry registry;
+
+
+        protected ConceteSchemaSyntax( String oid, SyntaxCheckerRegistry registry )
+        {
+            super( oid );
+            this.registry = registry;
+        }
+
+
+        public void setDescription( String description )
+        {
+            super.setDescription( description );
+        }
+
+
+        public void setHumanReadible( boolean isHumanReadible )
+        {
+            super.setHumanReadible( isHumanReadible );
+        }
+
+
+        public void setNames( String[] names )
+        {
+            super.setNames( names );
+        }
+
+
+        public SyntaxChecker getSyntaxChecker( ) throws NamingException
+        {
+            return registry.lookup( getOid() );
+        }
+
+
+        public boolean isObsolete()
+        {
+            return false;
+        }
+    }
+
+
+    public static class ConcreteSchemaMatchingRule extends AbstractMatchingRule
+    {
+        final SyntaxRegistry syntaxRegistry;
+        final NormalizerRegistry normalizerRegistry;
+        final ComparatorRegistry comparatorRegistry;
+        String syntaxOid;
+
+
+        protected ConcreteSchemaMatchingRule( String oid, Registries registries )
+        {
+            super( oid );
+            this.syntaxRegistry = registries.getSyntaxRegistry();
+            this.normalizerRegistry = registries.getNormalizerRegistry();
+            this.comparatorRegistry = registries.getComparatorRegistry();
+        }
+
+
+        public void setNames( String[] names )
+        {
+            super.setNames( names );
+        }
+
+        public void setSyntaxOid( String syntaxOid )
+        {
+            this.syntaxOid = syntaxOid;
+        }
+
+        public void setDescription( String description )
+        {
+            super.setDescription( description );
+        }
+
+        public void setObsolete( boolean isObsolete )
+        {
+            super.setObsolete( isObsolete );
+        }
+
+
+        // accessors
+
+
+        public Syntax getSyntax() throws NamingException
+        {
+            return syntaxRegistry.lookup( syntaxOid );
+        }
+
+        public Comparator getComparator() throws NamingException
+        {
+            return comparatorRegistry.lookup( getOid() );
+        }
+
+        public Normalizer getNormalizer() throws NamingException
+        {
+            return normalizerRegistry.lookup( getOid() );
+        }
+    }
+
+
+    /**
+     * A concrete mutable attributeType implementation for bootstrapping which
+     * uses registries for dynamically resolving dependent objects.
+     */
+    public static class ConcreteSchemaAttributeType extends AbstractAttributeType
+    {
+        private static final long serialVersionUID = 4050205236738471984L;
+
+        private final SyntaxRegistry syntaxRegistry;
+        private final MatchingRuleRegistry matchingRuleRegistry;
+        private final AttributeTypeRegistry attributeTypeRegistry;
+        private String superiorId;
+        private String equalityId;
+        private String substrId;
+        private String orderingId;
+        private String syntaxId;
+
+
+        protected ConcreteSchemaAttributeType( String oid, Registries registries )
+        {
+            super( oid );
+
+            syntaxRegistry = registries.getSyntaxRegistry();
+            matchingRuleRegistry = registries.getMatchingRuleRegistry();
+            attributeTypeRegistry = registries.getAttributeTypeRegistry();
+        }
+
+        public void setSuperiorId( String superiorId )
+        {
+            this.superiorId = superiorId;
+        }
+
+        public AttributeType getSuperior() throws NamingException
+        {
+            if ( superiorId == null )
+            {
+                return null;
+            }
+
+            return this.attributeTypeRegistry.lookup( superiorId );
+        }
+
+        public void setNames( String[] names )
+        {
+            super.setNames( names );
+        }
+
+        public MatchingRule getEquality() throws NamingException
+        {
+            if ( equalityId != null )
+            {
+                return this.matchingRuleRegistry.lookup( equalityId );
+            }
+
+            if ( superiorId != null )
+            {
+                return getSuperior().getEquality();
+            }
+
+            return null;
+        }
+
+        public void setEqualityId( String equalityId )
+        {
+            this.equalityId = equalityId;
+        }
+
+        public MatchingRule getSubstr() throws NamingException
+        {
+            if ( substrId != null )
+            {
+                return this.matchingRuleRegistry.lookup( substrId );
+            }
+
+            if ( superiorId != null )
+            {
+                return getSuperior().getSubstr();
+            }
+
+            return null;
+        }
+
+        public void setSubstrId( String substrId )
+        {
+            this.substrId = substrId;
+        }
+
+        public MatchingRule getOrdering() throws NamingException
+        {
+            if ( orderingId != null )
+            {
+                return this.matchingRuleRegistry.lookup( orderingId );
+            }
+
+            if ( superiorId != null )
+            {
+                return getSuperior().getOrdering();
+            }
+
+            return null;
+        }
+
+        public void setOrderingId( String orderingId )
+        {
+            this.orderingId = orderingId;
+        }
+
+        public void setSyntaxId( String syntaxId )
+        {
+            this.syntaxId = syntaxId;
+        }
+
+        public Syntax getSyntax() throws NamingException
+        {
+            if ( syntaxId != null )
+            {
+                return this.syntaxRegistry.lookup( syntaxId );
+            }
+
+            if ( superiorId != null )
+            {
+                return getSuperior().getSyntax();
+            }
+
+            return null;
+        }
+
+        public void setSingleValue( boolean singleValue )
+        {
+            super.setSingleValue( singleValue );
+        }
+
+        public void setCollective( boolean collective )
+        {
+            super.setCollective( collective );
+        }
+
+        public void setCanUserModify( boolean canUserModify )
+        {
+            super.setCanUserModify( canUserModify );
+        }
+
+        public void setObsolete( boolean obsolete )
+        {
+            super.setObsolete( obsolete );
+        }
+
+        public void setDescription( String description )
+        {
+            super.setDescription( description );
+        }
+
+        public void setUsage( UsageEnum usage )
+        {
+            super.setUsage( usage );
+        }
+
+        public void setLength( int length )
+        {
+            super.setLength( length );
+        }
+    }
+
+
+    /**
+     * A concrete mutable objectClass implementation for bootstrapping which
+     * uses registries for dynamically resolving dependent objects.
+     */
+    public static class ConcreteSchemaObjectClass extends AbstractSchemaObject
+        implements ObjectClass
+    {
+        private final ObjectClassRegistry objectClassRegistry;
+        private final AttributeTypeRegistry attributeTypeRegistry;
+
+        private String[] superClassIds = RegistrySchemaProducer.EMPTY;
+        private ObjectClass[] superClasses;
+        private ObjectClassTypeEnum type = ObjectClassTypeEnum.STRUCTURAL;
+
+        private String[] mayListIds = RegistrySchemaProducer.EMPTY;
+        private AttributeType[] mayList;
+
+        private String[] mustListIds = RegistrySchemaProducer.EMPTY;
+        private AttributeType[] mustList;
+
+
+        /**
+         * Creates a mutable ObjectClass for the bootstrap process.
+         *
+         * @param oid the OID of the new objectClass
+         * @param registries the bootstrap registries to use for resolving dependent objects
+         */
+        protected ConcreteSchemaObjectClass( String oid, Registries registries )
+        {
+            super( oid );
+
+            objectClassRegistry = registries.getObjectClassRegistry();
+            attributeTypeRegistry = registries.getAttributeTypeRegistry();
+        }
+
+
+        // --------------------------------------------------------------------
+        // ObjectClass Accessors
+        // --------------------------------------------------------------------
+
+
+        public ObjectClass[] getSuperClasses() throws NamingException
+        {
+            if ( superClasses == null )
+            {
+                superClasses = new ObjectClass[superClassIds.length];
+            }
+
+            for( int ii = 0; ii < superClassIds.length; ii++ )
+            {
+                superClasses[ii] = objectClassRegistry.lookup( superClassIds[ii] );
+            }
+
+            return superClasses;
+        }
+
+
+        public void setSuperClassIds( String[] superClassIds )
+        {
+            this.superClassIds = superClassIds;
+        }
+
+
+        public ObjectClassTypeEnum getType()
+        {
+            return type;
+        }
+
+
+        public void setType( ObjectClassTypeEnum type )
+        {
+            this.type = type;
+        }
+
+
+        public AttributeType[] getMustList() throws NamingException
+        {
+            if ( mustList == null )
+            {
+                mustList = new AttributeType[mustListIds.length];
+            }
+
+            for( int ii = 0; ii < mustListIds.length; ii++ )
+            {
+                mustList[ii] = attributeTypeRegistry.lookup( mustListIds[ii] );
+            }
+
+            return mustList;
+        }
+
+
+        public void setMustListIds( String[] mustListIds )
+        {
+            this.mustListIds = mustListIds;
+        }
+
+
+        public AttributeType[] getMayList() throws NamingException
+        {
+            if ( mayList == null )
+            {
+                mayList = new AttributeType[mayListIds.length];
+            }
+
+            for( int ii = 0; ii < mayListIds.length; ii++ )
+            {
+                mayList[ii] = attributeTypeRegistry.lookup( mayListIds[ii] );
+            }
+
+            return mayList;
+        }
+
+
+        public void setMayListIds( String[] mayListIds )
+        {
+            this.mayListIds = mayListIds;
+        }
+
+
+        // --------------------------------------------------------------------
+        // SchemaObject Mutators
+        // --------------------------------------------------------------------
+
+
+        public void setObsolete( boolean obsolete )
+        {
+            super.setObsolete( obsolete );
+        }
+
+        public void setNames( String[] names )
+        {
+            super.setNames( names );
+        }
+
+        public void setDescription( String description )
+        {
+            super.setDescription( description );
+        }
+    }
+}

Added: directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/schema/SchemaFromFileConverter.java
URL: http://svn.apache.org/viewvc/directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/schema/SchemaFromFileConverter.java?view=auto&rev=470483
==============================================================================
--- directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/schema/SchemaFromFileConverter.java (added)
+++ directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/schema/SchemaFromFileConverter.java Thu Nov  2 11:21:59 2006
@@ -0,0 +1,184 @@
+package org.apache.directory.server.core.schema;
+
+import org.apache.directory.server.core.tools.schema.AttributeTypeLiteral;
+import org.apache.directory.server.core.tools.schema.ObjectClassLiteral;
+import org.apache.directory.server.core.tools.schema.OpenLdapSchemaParser;
+import org.apache.directory.shared.ldap.schema.SchemaUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.naming.NamingException;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+
+/**
+ *   Wrapper that can parse an OpenLDAP format schema and help register the
+ * contents with the ApacheDS
+ * {@link org.apache.directory.server.core.schema.SchemaService}.
+ */
+public class SchemaFromFileConverter extends SchemaProducer
+{
+    private static final Logger log = LoggerFactory.getLogger(SchemaFromFileConverter.class);
+
+    private final String        schemaName;
+    private final File          schemaFile;
+    private final InputStream   schemaStream;
+
+    public SchemaFromFileConverter(final String schemaName, final File schemaFile)
+    {
+        this.schemaName = schemaName;
+        this.schemaFile = schemaFile;
+        schemaStream = null;
+    }
+
+    public SchemaFromFileConverter(final String schemaName, final InputStream schemaStream)
+    {
+        this.schemaName = schemaName;
+        this.schemaFile = null;
+        this.schemaStream = schemaStream;
+    }
+
+    public void convert(final Registries registries) throws NamingException, IOException, ParseException
+    {
+        final OpenLdapSchemaParser      parser = new OpenLdapSchemaParser();
+
+        if (schemaFile != null)
+            parser.parse(schemaFile);
+        else
+            parser.parse(schemaStream);
+        convertAttributeTypes(registries, parser.getAttributeTypes());
+        convertObjectClasses(registries, parser.getObjectClassTypes());
+    }
+
+
+    /**
+     *   Take in list() result on schema attribute type container and register
+     * types in global registry.
+     *
+     * @param toRegistries  Registry to be populated.
+     * @throws javax.naming.NamingException
+     */
+    public void convertAttributeTypes(final Registries toRegistries, final Collection attributeTypeLiterals)
+        throws NamingException
+    {
+        final AttributeTypeRegistry attributeTypeRegistry;
+        final ArrayList             skipped = new ArrayList();
+        int                         good = 0;
+
+        attributeTypeRegistry = toRegistries.getAttributeTypeRegistry();
+        for (Iterator it = attributeTypeLiterals.iterator(); it.hasNext();)
+        {
+            final AttributeTypeLiteral          in = (AttributeTypeLiteral) it.next();
+            final String                        oid = in.getOid();
+            final String                        name;
+            final ConcreteSchemaAttributeType   out;
+
+            name = in.getNames()[0];
+            if (attributeTypeRegistry.hasAttributeType(oid))
+            {
+                skipped.add(name + " : " + oid);
+                continue;
+            }
+            out = newAttributeType(oid, toRegistries);
+            out.setDescription(in.getDescription());
+            out.setEqualityId(in.getEquality());
+            out.setLength(in.getLength());
+            out.setNames(in.getNames());
+            out.setOrderingId(in.getOrdering());
+            out.setSubstrId(in.getSubstr());
+            out.setSuperiorId(in.getSuperior());
+            out.setSyntaxId(in.getSyntax());
+            out.setUsage(in.getUsage());
+
+            if (SchemaFromFileConverter.log.isDebugEnabled())
+                SchemaFromFileConverter.log.debug("converting attributeType[" + good + "]: " + oid
+                    + "=" + name);
+            good++;
+            attributeTypeRegistry.register(schemaName, out);
+        }
+        SchemaFromFileConverter.log.info("'" + schemaName + "': registered " + good + " attributeTypes (skipped "
+                + skipped.size() + ")");
+        if (! skipped.isEmpty())
+        {
+            int     i = 0;
+
+            Collections.sort(skipped);
+            for (Iterator it = skipped.iterator(); it.hasNext(); i++)
+            {
+                final String    skip = (String)it.next();
+
+                SchemaFromFileConverter.log.error("skipped attributeType[" + i + "]: " + skip);
+            }
+        }
+    }
+
+    private void convertObjectClasses(final Registries toRegistries, final Collection objectClassLiterals)
+    {
+        final ObjectClassRegistry   objectClassRegistry;
+        final ArrayList             skipped = new ArrayList();
+        int                         good = 0;
+
+        objectClassRegistry = toRegistries.getObjectClassRegistry();
+
+        for (Iterator it = objectClassLiterals.iterator(); it.hasNext();)
+        {
+            final ObjectClassLiteral        in = (ObjectClassLiteral) it.next();
+            final String                    oid = in.getOid();
+            final String                    name;
+            final ConcreteSchemaObjectClass out;
+
+            name = in.getNames()[0];
+            if (objectClassRegistry.hasObjectClass(oid))
+            {
+                skipped.add(name + " : " + oid);
+                continue;
+            }
+            if (SchemaFromFileConverter.log.isDebugEnabled())
+                SchemaFromFileConverter.log.debug("converting objectClass[" + good + "]: " + oid
+                    + "=" + name);
+            good++;
+                // @note Code copied from ./plugin/src/main/java/org/apache/ldap/server/tools/schema/ObjectClasses.template
+            out = newObjectClass(oid, toRegistries);
+            out.setDescription(in.getDescription());
+            out.setNames(in.getNames());
+            out.setType(in.getClassType());
+            out.setMayListIds(in.getMay());
+            out.setMustListIds(in.getMust());
+            out.setSuperClassIds(in.getSuperiors());
+            out.setObsolete(in.isObsolete());
+
+            try
+            {
+                    // avoid case where external schema attempts to register
+                    //  OC with bad references
+                SchemaUtils.render(out);
+                objectClassRegistry.register(schemaName, out);
+            }
+            catch (NamingException e)
+            {
+                log.error("failed validation objectClass: " + name + ": " + e);
+                skipped.add(name + " : " + oid + " [failed]");
+            }
+        }
+        log.info("'" + schemaName + "': registered " + good + " objectClasss (skipped "
+            + skipped.size() + ")");
+        if (! skipped.isEmpty())
+        {
+            int     i = 0;
+
+            Collections.sort(skipped);
+            for (Iterator it = skipped.iterator(); it.hasNext(); i++)
+            {
+                final String    skip = (String)it.next();
+
+                SchemaFromFileConverter.log.error("skipped objectClass[" + i + "]: " + skip);
+            }
+        }
+    }
+}

Added: directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/schema/SchemaFromSearchConverter.java
URL: http://svn.apache.org/viewvc/directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/schema/SchemaFromSearchConverter.java?view=auto&rev=470483
==============================================================================
--- directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/schema/SchemaFromSearchConverter.java (added)
+++ directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/schema/SchemaFromSearchConverter.java Thu Nov  2 11:21:59 2006
@@ -0,0 +1,455 @@
+package org.apache.directory.server.core.schema;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.directory.server.core.schema.global.GlobalRegistries;
+import org.apache.directory.shared.ldap.schema.UsageEnum;
+import org.apache.directory.shared.ldap.schema.ObjectClassTypeEnum;
+import org.apache.directory.shared.ldap.schema.SchemaUtils;
+
+import javax.naming.NameClassPair;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.DirContext;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ *   Wrapper that can parse an OpenLDAP format schema and help register the
+ * contents with the ApacheDS
+ * {@link SchemaService}.
+ */
+public class SchemaFromSearchConverter extends RegistrySchemaProducer
+{
+    private static final Logger log = LoggerFactory.getLogger(SchemaFromSearchConverter.class);
+
+    private final String        schemaName;
+    private final DirContext    schema;
+    private static final String ATTR_DEFS = "AttributeDefinition";
+    private static final String OBJ_CLASS_DEFS = "ClassDefinition";
+    private static final String SYNTAX_DEFS = "SyntaxDefinition";
+    private static final String MATCHING_RULE_DEFS = "MatchingRule";
+
+    /** Common schema attributes defined for an "Object Class". */
+    public static final String  OID_ATTR = "NUMERICOID";
+    public static final String  NAME_ATTR = "NAME";
+    public static final String  DESC_ATTR = "DESC";
+    public static final String  OBSOLETE_ATTR = "OBSOLETE";
+    public static final String  SUP_ATTR = "SUP";
+
+    /** Schema attributes defined for an "Attribute Type". */
+    public static final String  AT_EQUALITY_ATTR = "EQUALITY";
+    public static final String  AT_ORDERING_ATTR = "ORDERING";
+    public static final String  AT_SUBSTRING_ATTR = "SUBSTRING";
+    public static final String  AT_SYNTAX_ATTR = "SYNTAX";
+    public static final String  AT_SINGLE_VALUE_ATTR = "SINGLE-VALUE";
+    public static final String  AT_COLLECTIVE_ATTR = "COLLECTIVE";
+    public static final String  AT_NO_USER_MODIFICATION_ATTR = "NO-USER-MODIFICATION";
+    public static final String  AT_USAGE_ATTR = "USAGE";
+
+    /** Schema attributes defined for an "Object Class". */
+    public static final String  OC_ABSTRACT_ATTR = "ABSTRACT";
+    public static final String  OC_STRUCTURAL_ATTR = "STRUCTURAL";
+    public static final String  OC_AUXILIARY_ATTR = "AUXILIARY";
+    public static final String  OC_MUST_ATTR = "MUST";
+    public static final String  OC_MAY_ATTR = "MAY";
+
+    /** Schema attributes defined for a "Matching Rule". */
+    public static final String  RL_SYNTAX = "SYNTAX";
+
+    private final static String[]   EMPTY = new String[0];
+
+    public SchemaFromSearchConverter(final String schemaName, final DirContext schema)
+    {
+        this.schemaName = schemaName;
+        this.schema = schema;
+    }
+
+    public void convert(final GlobalRegistries registries)
+            throws NamingException
+    {
+        convertAttributeTypes(registries);
+        convertObjectClasses(registries);
+        convertSyntaxDefs(registries);
+        convertMatchingRuleDefs(registries);
+//        registries.getSyntaxRegistry();
+//        registries.getMatchingRuleRegistry();
+//        registries.getDitStructureRuleRegistry();
+    }
+
+
+    /**
+     *   Take in list() result on schema attribute type container and register
+     * types in global registry.
+     *
+     * @param toRegistries  Registry to be populated.
+     * @throws NamingException
+     */
+    public void convertAttributeTypes(final GlobalRegistries toRegistries)
+        throws NamingException
+    {
+        final AttributeTypeRegistry attributeTypeRegistry;
+        final ArrayList             skipped = new ArrayList();
+        int                         good = 0;
+        final DirContext            attrTypes;
+        final NamingEnumeration     atPairs;
+
+        attrTypes = (DirContext)schema.lookup(ATTR_DEFS);
+        atPairs = schema.list(ATTR_DEFS);
+
+        attributeTypeRegistry = toRegistries.getAttributeTypeRegistry();
+        while (atPairs.hasMore())
+        {
+            final NameClassPair pair = (NameClassPair)atPairs.next();
+            final Attributes    atSchemaAttrs;
+            final String[]      names;
+            final String        name;
+            final String        id;
+            final String        usage;
+            final ConcreteSchemaAttributeType at;
+
+            atSchemaAttrs = attrTypes.getAttributes(pair.getName());
+            id = getValueAsString(atSchemaAttrs, OID_ATTR);
+            names = getValueAsStringArray(atSchemaAttrs, NAME_ATTR);
+            name = (names != null ? names[0] : "***unknown***");
+            if ("eTGlobalUserContainerName".equals(name))
+                log.info("*** GOT: " + "eTGlobalUserContainerName");
+            if (attributeTypeRegistry.hasAttributeType(id))
+            {
+                skipped.add(name + " : " + id);
+                continue;
+            }
+            if (log.isDebugEnabled())
+                log.debug("converting attributeType[" + good + "]: " + id
+                    + "=" + name);
+            good++;
+                // @note Code copied from ./plugin/src/main/java/org/apache/ldap/server/tools/schema/AttributeTypes.template
+            at = newAttributeType(id, toRegistries);
+            at.setNames(names);
+            at.setDescription(getValueAsString(atSchemaAttrs, DESC_ATTR));
+            at.setCanUserModify(! getValueAsBoolean(atSchemaAttrs,
+                    AT_NO_USER_MODIFICATION_ATTR));
+            at.setSingleValue(getValueAsBoolean(atSchemaAttrs,
+                    AT_SINGLE_VALUE_ATTR));
+            at.setCollective(getValueAsBoolean(atSchemaAttrs,
+                    AT_COLLECTIVE_ATTR));
+            at.setObsolete(getValueAsBoolean(atSchemaAttrs, OBSOLETE_ATTR));
+            usage = getValueAsString(atSchemaAttrs, AT_USAGE_ATTR);
+            if (usage != null)
+                at.setUsage(UsageEnum.getUsage(usage));
+            at.setSuperiorId(getValueAsString(atSchemaAttrs, SUP_ATTR));
+            at.setEqualityId(getValueAsString(atSchemaAttrs,
+                    AT_EQUALITY_ATTR));
+            at.setSubstrId(getValueAsString(atSchemaAttrs, AT_SUBSTRING_ATTR));
+            at.setOrderingId(getValueAsString(atSchemaAttrs, AT_ORDERING_ATTR));
+            at.setSyntaxId(getValueAsString(atSchemaAttrs, AT_SYNTAX_ATTR));
+
+            attributeTypeRegistry.register(schemaName, at);
+        }
+        log.info("'" + schemaName + "': registered " + good + " attributeTypes (skipped "
+                + skipped.size() + ")");
+        if (! skipped.isEmpty())
+        {
+            int     i = 0;
+
+            Collections.sort(skipped);
+            for (Iterator it = skipped.iterator(); it.hasNext(); i++)
+            {
+                final String    skip = (String)it.next();
+
+                log.error("skipped attributeType[" + i + "]: " + skip);
+            }
+        }
+    }
+
+    private void convertObjectClasses(final GlobalRegistries toRegistries) throws NamingException
+    {
+        final ObjectClassRegistry   objectClassRegistry;
+        final ArrayList             skipped = new ArrayList();
+        int                         good = 0;
+        final DirContext            objClasses;
+        final NamingEnumeration     ocPairs;
+
+        objClasses = (DirContext)schema.lookup(OBJ_CLASS_DEFS);
+        ocPairs = schema.list(OBJ_CLASS_DEFS);
+        objectClassRegistry = toRegistries.getObjectClassRegistry();
+
+        while (ocPairs.hasMoreElements())
+        {
+            final NameClassPair pair = (NameClassPair)ocPairs.next();
+            final Attributes    ocSchemaAttrs;
+            final String[]      names;
+            final String        name;
+            final String        id;
+            final ConcreteSchemaObjectClass     oc;
+            final ObjectClassTypeEnum           type;
+
+            ocSchemaAttrs = objClasses.getAttributes(pair.getName());
+            id = getValueAsString(ocSchemaAttrs, OID_ATTR);
+            names = getValueAsStringArray(ocSchemaAttrs, NAME_ATTR);
+            name = (names != null ? names[0] : "***unknown***");
+            if (objectClassRegistry.hasObjectClass(id))
+            {
+                skipped.add(name + " : " + id);
+                continue;
+            }
+            if (log.isDebugEnabled())
+                log.debug("converting objectClass[" + good + "]: " + id
+                    + "=" + name);
+            good++;
+                // @note Code copied from ./plugin/src/main/java/org/apache/ldap/server/tools/schema/ObjectClasses.template
+            oc = newObjectClass(id, toRegistries);
+                    // set names
+            oc.setNames(names);
+            oc.setDescription(getValueAsString(ocSchemaAttrs, DESC_ATTR));
+            oc.setObsolete(getValueAsBoolean(ocSchemaAttrs, OBSOLETE_ATTR));
+                    // set superior objectClasses
+            oc.setSuperClassIds(getValueAsStringArray(ocSchemaAttrs, SUP_ATTR));
+
+            if (getValueAsBoolean(ocSchemaAttrs, OC_ABSTRACT_ATTR))
+                type = ObjectClassTypeEnum.ABSTRACT;
+            else if (getValueAsBoolean(ocSchemaAttrs, OC_STRUCTURAL_ATTR))
+                type = ObjectClassTypeEnum.STRUCTURAL;
+            else if (getValueAsBoolean(ocSchemaAttrs, OC_AUXILIARY_ATTR))
+                type = ObjectClassTypeEnum.AUXILIARY;
+            else
+                type = null;
+            if (type != null)
+                oc.setType(type);
+
+            oc.setMustListIds(getValueAsStringArray(ocSchemaAttrs,
+                    OC_MUST_ATTR));
+            oc.setMayListIds(getValueAsStringArray(ocSchemaAttrs,
+                    OC_MAY_ATTR));
+
+            try
+            {
+                    // avoid case where external schema attempts to register
+                    //  OC with bad references
+                SchemaUtils.render(oc);
+                objectClassRegistry.register(schemaName, oc);
+            }
+            catch (NamingException e)
+            {
+                log.error("failed validation objectClass: " + name);
+                skipped.add(name + " : " + id + " [failed]");
+            }
+        }
+        log.info("'" + schemaName + "': registered " + good + " objectClasss (skipped "
+            + skipped.size() + ")");
+        if (! skipped.isEmpty())
+        {
+            int     i = 0;
+
+            Collections.sort(skipped);
+            for (Iterator it = skipped.iterator(); it.hasNext(); i++)
+            {
+                final String    skip = (String)it.next();
+
+                log.error("skipped objectClass[" + i + "]: " + skip);
+            }
+        }
+    }
+
+    private void convertSyntaxDefs(final GlobalRegistries toRegistries)
+            throws NamingException
+    {
+        final SyntaxRegistry        syntaxRegistry;
+        final ArrayList             skipped = new ArrayList();
+        int                         good = 0;
+        final DirContext            syntaxes;
+        final NamingEnumeration     synPairs;
+        final Pattern               humanPat;
+        final Pattern               notPat;
+
+        syntaxes = (DirContext)schema.lookup(SYNTAX_DEFS);
+        synPairs = schema.list(SYNTAX_DEFS);
+
+        syntaxRegistry = toRegistries.getSyntaxRegistry();
+        humanPat = Pattern.compile("human", Pattern.CASE_INSENSITIVE);
+        notPat = Pattern.compile("not", Pattern.CASE_INSENSITIVE);
+        while (synPairs.hasMore())
+        {
+            final NameClassPair pair = (NameClassPair)synPairs.next();
+            final Attributes    synSchemaAttrs;
+            String[]            names;
+            final String        name;
+            final String        id;
+            final ConceteSchemaSyntax syn;
+
+            synSchemaAttrs = syntaxes.getAttributes(pair.getName());
+            id = getValueAsString(synSchemaAttrs, OID_ATTR);
+            names = getValueAsStringArray(synSchemaAttrs, NAME_ATTR);
+            if ((names == null) || (names.length == 0))
+            {
+                name = id;
+                names = new String[] { name };
+            }
+            else
+                name = names[0] + ":" + id;
+            if (syntaxRegistry.hasSyntax(id))
+            {
+                skipped.add(name);
+                continue;
+            }
+            if (log.isDebugEnabled())
+                log.debug("converting syntax[" + good + "]: " + name);
+            good++;
+            syn = newSyntax(id, toRegistries);
+            syn.setNames(names);
+
+                // end mandatory attrs according to RFC
+
+                // doesn't seem to be a standard attr name for human readable
+            final NamingEnumeration iDs = synSchemaAttrs.getIDs();
+            while (iDs.hasMoreElements())
+            {
+                final String    nm = (String)iDs.nextElement();
+                Matcher         m = humanPat.matcher(nm);
+
+                if (m.matches())
+                {
+                    boolean   b = getValueAsBoolean(synSchemaAttrs, nm);
+
+                    m = notPat.matcher(nm);
+                    if (m.matches())
+                        b = !b;
+                    syn.setHumanReadible(!b);
+                    break;
+                }
+            }
+            syntaxRegistry.register(schemaName, syn);
+        }
+        log.info("'" + schemaName + "': registered " + good + " syntaxes (skipped "
+                + skipped.size() + ")");
+        if (! skipped.isEmpty())
+        {
+            int     i = 0;
+
+            Collections.sort(skipped);
+            for (Iterator it = skipped.iterator(); it.hasNext(); i++)
+            {
+                final String    skip = (String)it.next();
+
+                log.error("skipped syntax[" + i + "]: " + skip);
+            }
+        }
+    }
+
+    private void convertMatchingRuleDefs(final GlobalRegistries toRegistries)
+            throws NamingException
+    {
+        final MatchingRuleRegistry  ruleRegistry;
+        final ArrayList             skipped = new ArrayList();
+        int                         good = 0;
+        final DirContext            rules;
+        final NamingEnumeration     rulePairs;
+
+        try
+        {
+                // todo Use some more flexible rule to identify these rules
+                //  (called dITStructureRule in CA directory)
+            rules = (DirContext)schema.lookup(MATCHING_RULE_DEFS);
+        }
+        catch (NamingException e)
+        {
+            log.warn("no section " + MATCHING_RULE_DEFS + " found in schema");
+            return;
+        }
+        rulePairs = schema.list(MATCHING_RULE_DEFS);
+
+        ruleRegistry = toRegistries.getMatchingRuleRegistry();
+        while (rulePairs.hasMore())
+        {
+            final NameClassPair pair = (NameClassPair)rulePairs.next();
+            final Attributes    ruleSchemaAttrs;
+            final String[]      names;
+            final String        name;
+            final String        id;
+            final ConcreteSchemaMatchingRule rule;
+
+            ruleSchemaAttrs = rules.getAttributes(pair.getName());
+            id = getValueAsString(ruleSchemaAttrs, OID_ATTR);
+            names = getValueAsStringArray(ruleSchemaAttrs, NAME_ATTR);
+            name = (names != null ? names[0] : id);
+            if (ruleRegistry.hasMatchingRule(id))
+            {
+                skipped.add(name + " : " + "*** unknown ***");
+                continue;
+            }
+            if (log.isDebugEnabled())
+                log.debug("converting rule[" + good + "]: " + id
+                    + "=" + name);
+            good++;
+            rule = newMatchingRule(id, toRegistries);
+            rule.setNames(names);
+            rule.setDescription(getValueAsString(ruleSchemaAttrs, DESC_ATTR));
+            rule.setObsolete(getValueAsBoolean(ruleSchemaAttrs, OBSOLETE_ATTR));
+            rule.setSyntaxOid(getValueAsString(ruleSchemaAttrs, RL_SYNTAX));
+            ruleRegistry.register(schemaName, rule);
+        }
+        log.info("'" + schemaName + "': registered " + good + " attributeTypes (skipped "
+                + skipped.size() + ")");
+        if (! skipped.isEmpty())
+        {
+            int     i = 0;
+
+            Collections.sort(skipped);
+            for (Iterator it = skipped.iterator(); it.hasNext(); i++)
+            {
+                final String    skip = (String)it.next();
+
+                log.error("skipped attributeType[" + i + "]: " + skip);
+            }
+        }
+    }
+
+    private String[] getValueAsStringArray(final Attributes atSchemaAttrs,
+            final String attrName) throws NamingException
+    {
+        final Attribute         attr;
+        final String[]          arr;
+        final NamingEnumeration enm;
+
+        attr = atSchemaAttrs.get(attrName);
+        if (attr == null)
+            return EMPTY;
+        arr = new String[attr.size()];
+        enm = attr.getAll();
+        for (int i = 0; enm.hasMoreElements(); i++)
+        {
+            final String    s = (String)enm.nextElement();
+
+            arr[i] = s;
+        }
+        return arr;
+    }
+
+    private boolean getValueAsBoolean(final Attributes atSchemaAttrs,
+            final String attrName) throws NamingException
+    {
+        final Attribute     attr;
+
+        attr = atSchemaAttrs.get(attrName);
+        if (attr == null)
+            return false;
+        return Boolean.valueOf((String)attr.get()).booleanValue();
+    }
+
+    private String getValueAsString(final Attributes atSchemaAttrs,
+            final String attrName) throws NamingException
+    {
+        final Attribute     attr;
+
+        attr = atSchemaAttrs.get(attrName);
+        if (attr == null)
+            return null;
+        return (String)attr.get();
+    }
+
+}

Added: directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/schema/SchemaProducer.java
URL: http://svn.apache.org/viewvc/directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/schema/SchemaProducer.java?view=auto&rev=470483
==============================================================================
--- directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/schema/SchemaProducer.java (added)
+++ directory/branches/apacheds-schema/apacheds/core/src/main/java/org/apache/directory/server/core/schema/SchemaProducer.java Thu Nov  2 11:21:59 2006
@@ -0,0 +1,473 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.directory.server.core.schema;
+
+
+import org.apache.directory.shared.ldap.schema.*;
+
+import javax.naming.NamingException;
+import java.util.Comparator;
+
+/**
+ *   An abstract producer implementation which doesn't make explicit reference
+ * to "bootstrap".
+ * todo: Based on org.apache.ldap.server.schema.bootstrap.AbstractBootstrapProducer
+ *      rev 226451 which should be recoded to use this more generic class.
+ */
+public abstract class SchemaProducer
+{
+    /** a reused empty String array */
+    protected static final String[] EMPTY = new String[0];
+
+    protected SchemaProducer()
+    {
+    }
+
+    protected static ConceteSchemaSyntax
+        newSyntax( String oid, Registries registries )
+    {
+        return new ConceteSchemaSyntax( oid, registries.getSyntaxCheckerRegistry() );
+    }
+
+    protected static ConcreteSchemaAttributeType
+        newAttributeType( String oid, Registries registries )
+    {
+        return new ConcreteSchemaAttributeType( oid, registries );
+    }
+
+    protected static ConcreteSchemaObjectClass
+        newObjectClass( String oid, Registries registries )
+    {
+        return new ConcreteSchemaObjectClass( oid, registries );
+    }
+
+    protected static ConcreteSchemaMatchingRule
+        newMatchingRule( String oid, Registries registries )
+    {
+        return new ConcreteSchemaMatchingRule( oid, registries );
+    }
+
+
+    /**
+     * A mutable Syntax for the bootstrap phase that uses the
+     * syntaxCheckerRegistry to dynamically resolve syntax checkers.
+     */
+    public static class ConceteSchemaSyntax extends AbstractSyntax
+    {
+        final SyntaxCheckerRegistry registry;
+
+
+        protected ConceteSchemaSyntax( String oid, SyntaxCheckerRegistry registry )
+        {
+            super( oid );
+            this.registry = registry;
+        }
+
+
+        public void setDescription( String description )
+        {
+            super.setDescription( description );
+        }
+
+
+        public void setHumanReadible( boolean isHumanReadible )
+        {
+            super.setHumanReadible( isHumanReadible );
+        }
+
+
+        public void setNames( String[] names )
+        {
+            super.setNames( names );
+        }
+
+
+        public SyntaxChecker getSyntaxChecker( ) throws NamingException
+        {
+            return registry.lookup( getOid() );
+        }
+
+
+        public boolean isObsolete()
+        {
+            return false;
+        }
+    }
+
+
+    public static class ConcreteSchemaMatchingRule extends AbstractMatchingRule
+    {
+        final SyntaxRegistry syntaxRegistry;
+        final NormalizerRegistry normalizerRegistry;
+        final ComparatorRegistry comparatorRegistry;
+        String syntaxOid;
+
+
+        protected ConcreteSchemaMatchingRule( String oid, Registries registries )
+        {
+            super( oid );
+            this.syntaxRegistry = registries.getSyntaxRegistry();
+            this.normalizerRegistry = registries.getNormalizerRegistry();
+            this.comparatorRegistry = registries.getComparatorRegistry();
+        }
+
+
+        public void setNames( String[] names )
+        {
+            super.setNames( names );
+        }
+
+        public void setSyntaxOid( String syntaxOid )
+        {
+            this.syntaxOid = syntaxOid;
+        }
+
+        public void setDescription( String description )
+        {
+            super.setDescription( description );
+        }
+
+        public void setObsolete( boolean isObsolete )
+        {
+            super.setObsolete( isObsolete );
+        }
+
+
+        // accessors
+
+
+        public Syntax getSyntax() throws NamingException
+        {
+            return syntaxRegistry.lookup( syntaxOid );
+        }
+
+        public Comparator getComparator() throws NamingException
+        {
+            return comparatorRegistry.lookup( getOid() );
+        }
+
+        public Normalizer getNormalizer() throws NamingException
+        {
+            return normalizerRegistry.lookup( getOid() );
+        }
+    }
+
+
+    /**
+     * A concrete mutable attributeType implementation for bootstrapping which
+     * uses registries for dynamically resolving dependent objects.
+     */
+    public static class ConcreteSchemaAttributeType extends AbstractAttributeType
+    {
+        private static final long serialVersionUID = 4050205236738471984L;
+
+        private final SyntaxRegistry syntaxRegistry;
+        private final MatchingRuleRegistry matchingRuleRegistry;
+        private final AttributeTypeRegistry attributeTypeRegistry;
+        private String superiorId;
+        private String equalityId;
+        private String substrId;
+        private String orderingId;
+        private String syntaxId;
+
+
+        protected ConcreteSchemaAttributeType( String oid, Registries registries )
+        {
+            super( oid );
+
+            syntaxRegistry = registries.getSyntaxRegistry();
+            matchingRuleRegistry = registries.getMatchingRuleRegistry();
+            attributeTypeRegistry = registries.getAttributeTypeRegistry();
+        }
+
+        public void setSuperiorId( String superiorId )
+        {
+            this.superiorId = superiorId;
+        }
+
+        public AttributeType getSuperior() throws NamingException
+        {
+            if ( superiorId == null )
+            {
+                return null;
+            }
+
+            return this.attributeTypeRegistry.lookup( superiorId );
+        }
+
+        public void setNames( String[] names )
+        {
+            super.setNames( names );
+        }
+
+        public MatchingRule getEquality() throws NamingException
+        {
+            if ( equalityId != null )
+            {
+                return this.matchingRuleRegistry.lookup( equalityId );
+            }
+
+            if ( superiorId != null )
+            {
+                return getSuperior().getEquality();
+            }
+
+            return null;
+        }
+
+        public void setEqualityId( String equalityId )
+        {
+            this.equalityId = equalityId;
+        }
+
+        public MatchingRule getSubstr() throws NamingException
+        {
+            if ( substrId != null )
+            {
+                return this.matchingRuleRegistry.lookup( substrId );
+            }
+
+            if ( superiorId != null )
+            {
+                return getSuperior().getSubstr();
+            }
+
+            return null;
+        }
+
+        public void setSubstrId( String substrId )
+        {
+            this.substrId = substrId;
+        }
+
+        public MatchingRule getOrdering() throws NamingException
+        {
+            if ( orderingId != null )
+            {
+                return this.matchingRuleRegistry.lookup( orderingId );
+            }
+
+            if ( superiorId != null )
+            {
+                return getSuperior().getOrdering();
+            }
+
+            return null;
+        }
+
+        public void setOrderingId( String orderingId )
+        {
+            this.orderingId = orderingId;
+        }
+
+        public void setSyntaxId( String syntaxId )
+        {
+            this.syntaxId = syntaxId;
+        }
+
+        public Syntax getSyntax() throws NamingException
+        {
+            if ( syntaxId != null )
+            {
+                return this.syntaxRegistry.lookup( syntaxId );
+            }
+
+            if ( superiorId != null )
+            {
+                return getSuperior().getSyntax();
+            }
+
+            return null;
+        }
+
+        public void setSingleValue( boolean singleValue )
+        {
+            super.setSingleValue( singleValue );
+        }
+
+        public void setCollective( boolean collective )
+        {
+            super.setCollective( collective );
+        }
+
+        public void setCanUserModify( boolean canUserModify )
+        {
+            super.setCanUserModify( canUserModify );
+        }
+
+        public void setObsolete( boolean obsolete )
+        {
+            super.setObsolete( obsolete );
+        }
+
+        public void setDescription( String description )
+        {
+            super.setDescription( description );
+        }
+
+        public void setUsage( UsageEnum usage )
+        {
+            super.setUsage( usage );
+        }
+
+        public void setLength( int length )
+        {
+            super.setLength( length );
+        }
+    }
+
+
+    /**
+     * A concrete mutable objectClass implementation for bootstrapping which
+     * uses registries for dynamically resolving dependent objects.
+     */
+    public static class ConcreteSchemaObjectClass extends AbstractSchemaObject
+        implements ObjectClass
+    {
+        private final ObjectClassRegistry objectClassRegistry;
+        private final AttributeTypeRegistry attributeTypeRegistry;
+
+        private String[] superClassIds = EMPTY;
+        private ObjectClass[] superClasses;
+        private ObjectClassTypeEnum type = ObjectClassTypeEnum.STRUCTURAL;
+
+        private String[] mayListIds = EMPTY;
+        private AttributeType[] mayList;
+
+        private String[] mustListIds = EMPTY;
+        private AttributeType[] mustList;
+
+
+        /**
+         * Creates a mutable ObjectClass for the bootstrap process.
+         *
+         * @param oid the OID of the new objectClass
+         * @param registries the bootstrap registries to use for resolving dependent objects
+         */
+        protected ConcreteSchemaObjectClass( String oid, Registries registries )
+        {
+            super( oid );
+
+            objectClassRegistry = registries.getObjectClassRegistry();
+            attributeTypeRegistry = registries.getAttributeTypeRegistry();
+        }
+
+
+        // --------------------------------------------------------------------
+        // ObjectClass Accessors
+        // --------------------------------------------------------------------
+
+
+        public ObjectClass[] getSuperClasses() throws NamingException
+        {
+            if ( superClasses == null )
+            {
+                superClasses = new ObjectClass[superClassIds.length];
+            }
+
+            for( int ii = 0; ii < superClassIds.length; ii++ )
+            {
+                superClasses[ii] = objectClassRegistry.lookup( superClassIds[ii] );
+            }
+
+            return superClasses;
+        }
+
+
+        public void setSuperClassIds( String[] superClassIds )
+        {
+            this.superClassIds = superClassIds;
+        }
+
+
+        public ObjectClassTypeEnum getType()
+        {
+            return type;
+        }
+
+
+        public void setType( ObjectClassTypeEnum type )
+        {
+            this.type = type;
+        }
+
+
+        public AttributeType[] getMustList() throws NamingException
+        {
+            if ( mustList == null )
+            {
+                mustList = new AttributeType[mustListIds.length];
+            }
+
+            for( int ii = 0; ii < mustListIds.length; ii++ )
+            {
+                mustList[ii] = attributeTypeRegistry.lookup( mustListIds[ii] );
+            }
+
+            return mustList;
+        }
+
+
+        public void setMustListIds( String[] mustListIds )
+        {
+            this.mustListIds = mustListIds;
+        }
+
+
+        public AttributeType[] getMayList() throws NamingException
+        {
+            if ( mayList == null )
+            {
+                mayList = new AttributeType[mayListIds.length];
+            }
+
+            for( int ii = 0; ii < mayListIds.length; ii++ )
+            {
+                mayList[ii] = attributeTypeRegistry.lookup( mayListIds[ii] );
+            }
+
+            return mayList;
+        }
+
+
+        public void setMayListIds( String[] mayListIds )
+        {
+            this.mayListIds = mayListIds;
+        }
+
+
+        // --------------------------------------------------------------------
+        // SchemaObject Mutators
+        // --------------------------------------------------------------------
+
+
+        public void setObsolete( boolean obsolete )
+        {
+            super.setObsolete( obsolete );
+        }
+
+        public void setNames( String[] names )
+        {
+            super.setNames( names );
+        }
+
+        public void setDescription( String description )
+        {
+            super.setDescription( description );
+        }
+    }
+}