Package org.apache.hivemind.impl

Source Code of org.apache.hivemind.impl.RegistryBuilder

// Copyright 2004, 2005 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.hivemind.impl;

import java.util.Iterator;
import java.util.List;
import java.util.Locale;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hivemind.ErrorHandler;
import org.apache.hivemind.Registry;
import org.apache.hivemind.definition.ConfigurationPointDefinition;
import org.apache.hivemind.definition.DefinitionMessages;
import org.apache.hivemind.definition.ModuleDefinition;
import org.apache.hivemind.definition.Occurances;
import org.apache.hivemind.definition.RegistryDefinition;
import org.apache.hivemind.definition.RegistryDefinitionPostProcessor;
import org.apache.hivemind.definition.impl.RegistryDefinitionImpl;
import org.apache.hivemind.events.RegistryInitializationListener;
import org.apache.hivemind.internal.RegistryInfrastructure;

/**
* Class used to build a {@link org.apache.hivemind.Registry} from a {@link org.apache.hivemind.definition.RegistryDefinition}.
*
* A note about threadsafety: The assumption is that a single thread will access the RegistryBuilder
* at one time (typically, a startup class within some form of server or application). Code here and
* in many of the related classes is divided into construction-time logic and runtime logic. Runtime
* logic is synchronized and threadsafe. Construction-time logic is not threadsafe. Once the
* registry is fully constructed, it is not allowed to invoke those methods (though, at this time,
* no checks occur).
* <p>
* Runtime methods, such as {@link org.apache.hivemind.impl.ModuleImpl#getService(String, Class)}
* are fully threadsafe.
*
* @author Howard Lewis Ship
*/
public final class RegistryBuilder
{
    private static final Log LOG = LogFactory.getLog(RegistryBuilder.class);

    static
    {
        if (!LOG.isErrorEnabled())
        {
            System.err
                    .println("********************************************************************************");
            System.err
                    .println("* L O G G I N G   C O N F I G U R A T I O N   E R R O R                        *");
            System.err
                    .println("* ---------------------------------------------------------------------------- *");
            System.err
                    .println("* Logging is not enabled for org.apache.hivemind.impl.RegistryBuilder.         *");
            System.err
                    .println("* Errors during HiveMind module descriptor parsing and validation may not be   *");
            System.err
                    .println("* logged. This may result in difficult-to-trace runtime exceptions, if there   *");
            System.err
                    .println("* are errors in any of your module descriptors. You should enable error        *");
            System.err
                    .println("* logging for the org.apache.hivemind and hivemind loggers.                    *");
            System.err
                    .println("********************************************************************************");
        }
    }

    /**
     * Delegate used for handling errors.
     */

    private ErrorHandler _errorHandler;

    private RegistryDefinition _registryDefinition;

    /**
     * Constructs a new instance that starts with a empty {@link RegistryDefinition} which can be
     * requested by {@link #getRegistryDefinition()}.
     */
    public RegistryBuilder()
    {
        this(new RegistryDefinitionImpl(), new DefaultErrorHandler());
    }
   
    /**
     * Constructs a new instance that starts with the provided {@link RegistryDefinition}.
     * The definition can still be altered afterwards.
     */
   public RegistryBuilder(RegistryDefinition registryDefinition)
    {
        this(registryDefinition, new DefaultErrorHandler());
    }

    public RegistryBuilder(ErrorHandler errorHandler)
    {
        this(new RegistryDefinitionImpl(), errorHandler);
    }
   
    public RegistryBuilder(RegistryDefinition registryDefinition, ErrorHandler errorHandler)
    {
        _registryDefinition = registryDefinition;
        _errorHandler = errorHandler;
    }

    /**
     * @return  the contained registry definition
     */
    public RegistryDefinition getRegistryDefinition()
    {
        return _registryDefinition;
    }
    /**
     * Constructs the registry from its {@link RegistryDefinition}. Default locale is used.
     * @see #constructRegistry(Locale)
     */
    public Registry constructRegistry()
    {
        return constructRegistry();
    }
   
    /**
     * Constructs the registry from its {@link RegistryDefinition}.
     * @param locale  the locale used for translating resources
     */
    public Registry constructRegistry(Locale locale)
    {
        // Add Core HiveMind services like ClassFactory
        CoreServicesProvider coreServicesProvider = new CoreServicesProvider();
        coreServicesProvider.process(_registryDefinition, _errorHandler);
       
        // Try to resolve all so far unresolved extensions
        ExtensionResolver extensionResolver = new ExtensionResolver(_registryDefinition, _errorHandler);
        extensionResolver.resolveExtensions();
       
        checkDependencies(_registryDefinition);
        checkContributionCounts(_registryDefinition);
       
        // Notify post processors
        for (Iterator i = _registryDefinition.getPostProcessors().iterator(); i.hasNext();)
        {
            RegistryDefinitionPostProcessor processor = (RegistryDefinitionPostProcessor) i.next();

            processor.postprocess(_registryDefinition, _errorHandler);
        }

        RegistryInfrastructureConstructor constructor = new RegistryInfrastructureConstructor(_errorHandler, LOG, locale);
        RegistryInfrastructure infrastructure = constructor
                .constructRegistryInfrastructure(_registryDefinition);

        // Notify initialization listeners
        for (Iterator i = _registryDefinition.getRegistryInitializationListeners().iterator(); i.hasNext();)
        {
            RegistryInitializationListener listener = (RegistryInitializationListener) i.next();

            listener.registryInitialized(infrastructure);
        }
       
        infrastructure.startup();

        return new RegistryImpl(infrastructure);
    }
   
    /**
     * Constructs the registry from a specified {@link RegistryDefinition}.
     * @param definition  the registry definition
     * @param errorHandler  errorHandler used for handling recoverable errors
     * @param locale  the locale used for translating resources
     * @return  the registry
     */
    public static Registry constructRegistry(RegistryDefinition definition, ErrorHandler errorHandler,
            Locale locale)
    {
        RegistryBuilder builder = new RegistryBuilder(definition, errorHandler);
        return builder.constructRegistry(locale);
    }

    /**
     * Checks if all dependencies of modules are present.
     */
    private void checkDependencies(RegistryDefinition definition)
    {
        for (Iterator iterModules = definition.getModules().iterator(); iterModules.hasNext();)
        {
            ModuleDefinition module = (ModuleDefinition) iterModules.next();
           
            for (Iterator iterDependencies = module.getDependencies().iterator(); iterDependencies.hasNext();)
            {
                String requiredModuleId = (String) iterDependencies.next();
                checkModuleDependency(definition, module, requiredModuleId);
            }
        }
       
    }

    private void checkModuleDependency(RegistryDefinition definition, ModuleDefinition sourceModule, String requiredModuleId)
    {
        ModuleDefinition requiredModule = (ModuleDefinition) definition.getModule(requiredModuleId);
        if (requiredModule == null)
        {
            // TODO: Include Location in Dependencies
            _errorHandler.error(
                    LOG,
                    DefinitionMessages.dependencyOnUnknownModule(requiredModuleId),
                    null,
                    null);
            return;
        }
    }
   
    /**
     * Checks that each configuration extension point has the right number of contributions.
     */
    public void checkContributionCounts(RegistryDefinition definition)
    {
        for (Iterator iterModules = definition.getModules().iterator(); iterModules.hasNext();)
        {
            ModuleDefinition module = (ModuleDefinition) iterModules.next();
           
            for (Iterator iterConfigurations = module.getConfigurationPoints().iterator(); iterConfigurations.hasNext();)
            {
                ConfigurationPointDefinition cpd = (ConfigurationPointDefinition) iterConfigurations.next();
                checkContributionCounts(module, cpd);
            }
        }
    }
   
    private void checkContributionCounts(ModuleDefinition definingModule, ConfigurationPointDefinition configurationPoint)
    {
        Occurances expected = configurationPoint.getExpectedContributions();

        int actual = configurationPoint.getContributions().size();

        if (expected.inRange(actual))
            return;

        _errorHandler.error(LOG, DefinitionMessages.wrongNumberOfContributions(
                definingModule, configurationPoint,
                actual,
                expected), configurationPoint.getLocation(), null);
    }

    /**
     * Automatically loads hivemind modules on the classpath which are
     * provided by {@link RegistryProvider}s which are defined in Manifest-Files.
     */
    public void autoDetectModules()
    {
        RegistryProviderAutoDetector detector = new RegistryProviderAutoDetector(new DefaultClassResolver());
        List providers = detector.getProviders();
        for (Iterator iterProviders = providers.iterator(); iterProviders.hasNext();)
        {
            RegistryProvider provider = (RegistryProvider) iterProviders.next();
            provider.process(getRegistryDefinition(), _errorHandler);
        }
    }

    /**
     * Constructs a default registry based on just the modules visible to the thread context class
     * loader (this is sufficient is the majority of cases), and using the default locale. If you
     * have different error handling needs, or wish to pick up HiveMind modules
     * for non-standard locations, you must create a RegistryBuilder instance yourself.
     */
    public static Registry constructDefaultRegistry()
    {
        RegistryBuilder builder = new RegistryBuilder();
        builder.autoDetectModules();
        return builder.constructRegistry(Locale.getDefault());
    }

    public ErrorHandler getErrorHandler()
    {
        return _errorHandler;
    }

}
TOP

Related Classes of org.apache.hivemind.impl.RegistryBuilder

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.