Package org.apache.ldap.server.schema.bootstrap

Source Code of org.apache.ldap.server.schema.bootstrap.BootstrapSchemaLoader

/*
*   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.ldap.server.schema.bootstrap;


import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;

import javax.naming.NamingException;

import org.apache.ldap.common.schema.AttributeType;
import org.apache.ldap.common.schema.DITContentRule;
import org.apache.ldap.common.schema.DITStructureRule;
import org.apache.ldap.common.schema.MatchingRule;
import org.apache.ldap.common.schema.MatchingRuleUse;
import org.apache.ldap.common.schema.NameForm;
import org.apache.ldap.common.schema.Normalizer;
import org.apache.ldap.common.schema.ObjectClass;
import org.apache.ldap.common.schema.Syntax;
import org.apache.ldap.common.schema.SyntaxChecker;
import org.apache.ldap.server.jndi.ServerDirObjectFactory;
import org.apache.ldap.server.jndi.ServerDirStateFactory;
import org.apache.ldap.server.schema.AttributeTypeRegistry;
import org.apache.ldap.server.schema.ComparatorRegistry;
import org.apache.ldap.server.schema.DITContentRuleRegistry;
import org.apache.ldap.server.schema.DITStructureRuleRegistry;
import org.apache.ldap.server.schema.MatchingRuleRegistry;
import org.apache.ldap.server.schema.MatchingRuleUseRegistry;
import org.apache.ldap.server.schema.NameFormRegistry;
import org.apache.ldap.server.schema.NormalizerRegistry;
import org.apache.ldap.server.schema.ObjectClassRegistry;
import org.apache.ldap.server.schema.ObjectFactoryRegistry;
import org.apache.ldap.server.schema.StateFactoryRegistry;
import org.apache.ldap.server.schema.SyntaxCheckerRegistry;
import org.apache.ldap.server.schema.SyntaxRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
* Class which handles bootstrap schema class file loading.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
* @version $Rev: 280870 $
*/
public class BootstrapSchemaLoader
{
    private static final Logger log = LoggerFactory.getLogger( BootstrapSchemaLoader.class );

    /** stores schemas of producers for callback access */
    private ThreadLocal schemas;
    /** stores registries associated with producers for callback access */
    private ThreadLocal registries;
    /** the callback that just calls register() */
    private final ProducerCallback cb = new ProducerCallback()
    {
        public void schemaObjectProduced( BootstrapProducer producer,
                                          String registryKey,
                                          Object schemaObject )
            throws NamingException
        {
            register( producer.getType(), registryKey, schemaObject );
        }
    };


    /**
     * Creates a BootstrapSchema loader.
     */
    public BootstrapSchemaLoader()
    {
        schemas = new ThreadLocal();
        registries = new ThreadLocal();
    }



    /**
     * Loads a set of schemas by loading and running all producers for each
     * dependent schema first.
     *
     * @param bootstrapSchemas Collection of {@link BootstrapSchema}s to load
     * @param registries the registries to fill with producer created objects
     * @throws NamingException if there are any failures during this process
     */
    public final void load( Collection bootstrapSchemas, BootstrapRegistries registries )
        throws NamingException
    {
        BootstrapSchema[] schemas = new BootstrapSchema[ bootstrapSchemas.size() ];
        schemas = ( BootstrapSchema[] ) bootstrapSchemas.toArray( schemas );
        HashMap loaded = new HashMap();
        HashMap notLoaded = new HashMap();

        for ( int ii = 0; ii < schemas.length; ii++ )
        {
            notLoaded.put( schemas[ii].getSchemaName(), schemas[ii] );
        }
       
        BootstrapSchema schema;
       
        // Create system schema and kick it off by loading system which
        // will never depend on anything.
        schema = new SystemSchema();
        load( schema, registries );
        notLoaded.remove( schema.getSchemaName() ); // Remove if user specified it.
        loaded.put( schema.getSchemaName(), schema );

        Iterator list = notLoaded.values().iterator();
        while ( list.hasNext() )
        {
            schema = ( BootstrapSchema ) list.next();
            loadDepsFirst( new Stack(), notLoaded, schema, registries );
            list = notLoaded.values().iterator();
        }
    }


    /**
     * Recursive method which loads schema's with their dependent schemas first
     * and tracks what schemas it has seen so the recursion does not go out of
     * control with depenency cycle detection.
     *
     * @param beenthere stack of schema names we have visited and have yet to load
     * @param notLoaded hash of schemas keyed by name which have yet to be loaded
     * @param schema the current schema we are attempting to load
     * @param registries the set of registries to use while loading
     * @throws NamingException if there is a cycle detected and/or another
     * failure results while loading, producing and or registering schema objects
     */
    public final void loadDepsFirst( Stack beenthere, HashMap notLoaded,
                                     BootstrapSchema schema,
                                     BootstrapRegistries registries )
        throws NamingException
    {
        beenthere.push( schema.getSchemaName() );
        String[] deps = schema.getDependencies();

        // if no deps then load this guy and return
        if ( deps == null || deps.length == 0 )
        {
            load( schema, registries );
            notLoaded.remove( schema.getSchemaName() );
            beenthere.pop();
            return;
        }

        /*
         * We got deps and need to load them before this schema.  We go through
         * all deps loading them with their deps first if they have not been
         * loaded.
         */
        for ( int ii = 0; ii < deps.length; ii++ )
        {
            if ( ! notLoaded.containsKey( deps[ii] ) )
            {
                continue;
            }

            BootstrapSchema dep = ( BootstrapSchema ) notLoaded.get( deps[ii] );

            if ( beenthere.contains( dep.getSchemaName() ) )
            {
                // push again so we show the cycle in output
                beenthere.push( dep.getSchemaName() );
                throw new NamingException( "schema dependency cycle detected: "
                    + beenthere );
            }

            loadDepsFirst( beenthere, notLoaded, dep, registries );
        }

        // We have loaded all our deps so we can load this schema
        load( schema, registries );
        notLoaded.remove( schema.getSchemaName() );
        beenthere.pop();
    }


    /**
     * Loads a schema by loading and running all producers for te schema.
     *
     * @param schema the schema to load
     * @param registries the registries to fill with producer created objects
     * @throws NamingException if there are any failures during this process
     */
    public final void load( BootstrapSchema schema, BootstrapRegistries registries )
        throws NamingException
    {
        this.registries.set( registries );
        this.schemas.set( schema );

        List producers = ProducerTypeEnum.list();
        for ( int ii = 0; ii < producers.size(); ii++ )
        {
            ProducerTypeEnum producerType = ( ProducerTypeEnum ) producers.get( ii );
            BootstrapProducer producer = getProducer( schema, producerType.getName() );
            producer.produce( registries, cb );
        }
    }


    // ------------------------------------------------------------------------
    // Utility Methods
    // ------------------------------------------------------------------------


    /**
     * Registers objects
     *
     * @param type the type of the producer which determines the type of object produced
     * @param id the primary key identifying the created object in a registry
     * @param schemaObject the object being registered
     * @throws NamingException if there are problems when registering the object
     * in any of the registries
     */
    private void register( ProducerTypeEnum type, String id,
                           Object schemaObject ) throws NamingException
    {
        BootstrapSchema schema = ( BootstrapSchema ) this.schemas.get();
        BootstrapRegistries registries = ( BootstrapRegistries ) this.registries.get();

        switch( type.getValue() )
        {
            case( ProducerTypeEnum.NORMALIZER_PRODUCER_VAL ):
                Normalizer normalizer = ( Normalizer ) schemaObject;
                NormalizerRegistry normalizerRegistry;
                normalizerRegistry = registries.getNormalizerRegistry();
                normalizerRegistry.register( schema.getSchemaName(), id, normalizer );
                break;
            case( ProducerTypeEnum.COMPARATOR_PRODUCER_VAL ):
                Comparator comparator = ( Comparator ) schemaObject;
                ComparatorRegistry comparatorRegistry;
                comparatorRegistry = registries.getComparatorRegistry();
                comparatorRegistry.register( schema.getSchemaName(), id, comparator );
                break;
            case( ProducerTypeEnum.SYNTAX_CHECKER_PRODUCER_VAL ):
                SyntaxChecker syntaxChecker = ( SyntaxChecker ) schemaObject;
                SyntaxCheckerRegistry syntaxCheckerRegistry;
                syntaxCheckerRegistry = registries.getSyntaxCheckerRegistry();
                syntaxCheckerRegistry.register( schema.getSchemaName(), id, syntaxChecker );
                break;
            case( ProducerTypeEnum.SYNTAX_PRODUCER_VAL ):
                Syntax syntax = ( Syntax ) schemaObject;
                SyntaxRegistry syntaxRegistry = registries.getSyntaxRegistry();
                syntaxRegistry.register( schema.getSchemaName(), syntax );
                break;
            case( ProducerTypeEnum.MATCHING_RULE_PRODUCER_VAL ):
                MatchingRule matchingRule = ( MatchingRule ) schemaObject;
                MatchingRuleRegistry matchingRuleRegistry;
                matchingRuleRegistry = registries.getMatchingRuleRegistry();
                matchingRuleRegistry.register( schema.getSchemaName(), matchingRule );
                break;
            case( ProducerTypeEnum.ATTRIBUTE_TYPE_PRODUCER_VAL ):
                AttributeType attributeType = ( AttributeType ) schemaObject;
                AttributeTypeRegistry attributeTypeRegistry;
                attributeTypeRegistry = registries.getAttributeTypeRegistry();
                attributeTypeRegistry.register( schema.getSchemaName(), attributeType );
                break;
            case( ProducerTypeEnum.OBJECT_CLASS_PRODUCER_VAL ):
                ObjectClass objectClass = ( ObjectClass ) schemaObject;
                ObjectClassRegistry objectClassRegistry;
                objectClassRegistry = registries.getObjectClassRegistry();
                objectClassRegistry.register( schema.getSchemaName(), objectClass );
                break;
            case( ProducerTypeEnum.MATCHING_RULE_USE_PRODUCER_VAL ):
                MatchingRuleUse matchingRuleUse = ( MatchingRuleUse ) schemaObject;
                MatchingRuleUseRegistry matchingRuleUseRegistry;
                matchingRuleUseRegistry = registries.getMatchingRuleUseRegistry();
                matchingRuleUseRegistry.register( schema.getSchemaName(), matchingRuleUse );
                break;
            case( ProducerTypeEnum.DIT_CONTENT_RULE_PRODUCER_VAL ):
                DITContentRule ditContentRule = ( DITContentRule ) schemaObject;
                DITContentRuleRegistry ditContentRuleRegistry;
                ditContentRuleRegistry = registries.getDitContentRuleRegistry();
                ditContentRuleRegistry.register( schema.getSchemaName(), ditContentRule );
                break;
            case( ProducerTypeEnum.NAME_FORM_PRODUCER_VAL ):
                NameForm nameForm = ( NameForm ) schemaObject;
                NameFormRegistry nameFormRegistry;
                nameFormRegistry = registries.getNameFormRegistry();
                nameFormRegistry.register( schema.getSchemaName(), nameForm );
                break;
            case( ProducerTypeEnum.DIT_STRUCTURE_RULE_PRODUCER_VAL ):
                DITStructureRule ditStructureRule = ( DITStructureRule ) schemaObject;
                DITStructureRuleRegistry ditStructureRuleRegistry;
                ditStructureRuleRegistry = registries.getDitStructureRuleRegistry();
                ditStructureRuleRegistry.register( schema.getSchemaName(), ditStructureRule );
                break;
            case( ProducerTypeEnum.STATE_FACTORY_PRODUCER_VAL ):
                ServerDirStateFactory stateFactory = ( ServerDirStateFactory ) schemaObject;
                StateFactoryRegistry stateFactoryRegistry;
                stateFactoryRegistry = registries.getStateFactoryRegistry();
                stateFactoryRegistry.register( stateFactory );
                break;
            case( ProducerTypeEnum.OBJECT_FACTORY_PRODUCER_VAL ):
                ServerDirObjectFactory objectFactory = ( ServerDirObjectFactory ) schemaObject;
                ObjectFactoryRegistry objectFactoryRegistry;
                objectFactoryRegistry = registries.getObjectFactoryRegistry();
                objectFactoryRegistry.register( objectFactory );
                break;
            default:
                throw new IllegalStateException( "ProducerTypeEnum is broke!" );
        }
    }


    /**
     * Attempts first to try to load the target class for the Producer,
     * then tries for the default if the target load fails.
     *
     * @param schema the bootstrap schema
     * @param producerBase the producer's base name
     * @throws NamingException if there are failures loading classes
     */
    private BootstrapProducer getProducer( BootstrapSchema schema, String producerBase )
        throws NamingException
    {
        Class clazz = null;
        boolean failedTargetLoad = false;
        String defaultClassName;
        String targetClassName = schema.getBaseClassName() + producerBase;

        try
        {
            clazz = Class.forName( targetClassName );
        }
        catch ( ClassNotFoundException e )
        {
            failedTargetLoad = true;
            log.debug( "Failed to load '" + targetClassName + "'.  Trying the alternative.", e );
        }

        if ( failedTargetLoad )
        {
            defaultClassName = schema.getDefaultBaseClassName() + producerBase;

            try
            {
                clazz = Class.forName( defaultClassName );
            }
            catch ( ClassNotFoundException e )
            {
                NamingException ne = new NamingException( "Failed to load " +
                    producerBase + " for " + schema.getSchemaName()
                    + " schema using following classes: "  + targetClassName
                    + ", " + defaultClassName );
                ne.setRootCause( e );
                throw ne;
            }
        }

        try
        {
            return ( BootstrapProducer ) clazz.newInstance();
        }
        catch ( IllegalAccessException e )
        {
            NamingException ne = new NamingException( "Failed to create " + clazz );
            ne.setRootCause( e );
            throw ne;
        }
        catch ( InstantiationException e )
        {
            NamingException ne = new NamingException( "Failed to create " + clazz );
            ne.setRootCause( e );
            throw ne;
        }
    }
}
TOP

Related Classes of org.apache.ldap.server.schema.bootstrap.BootstrapSchemaLoader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.