// Copyright 2006-2014 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.tapestry5.ioc.internal;

import org.apache.tapestry5.func.F;
import org.apache.tapestry5.func.Flow;
import org.apache.tapestry5.func.Mapper;
import org.apache.tapestry5.func.Predicate;
import org.apache.tapestry5.ioc.*;
import org.apache.tapestry5.ioc.annotations.Local;
import org.apache.tapestry5.ioc.def.*;
import org.apache.tapestry5.ioc.internal.services.PerthreadManagerImpl;
import org.apache.tapestry5.ioc.internal.services.RegistryShutdownHubImpl;
import org.apache.tapestry5.ioc.internal.util.*;
import org.apache.tapestry5.ioc.modules.TapestryIOCModule;
import org.apache.tapestry5.ioc.services.*;
import org.apache.tapestry5.ioc.util.AvailableValues;
import org.apache.tapestry5.ioc.util.UnknownValueException;
import org.apache.tapestry5.services.UpdateListenerHub;
import org.slf4j.Logger;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.*;

@SuppressWarnings("all")
public class RegistryImpl implements Registry, InternalRegistry, ServiceProxyProvider
{
    private static final String SYMBOL_SOURCE_SERVICE_ID = "SymbolSource";

    private static final String REGISTRY_SHUTDOWN_HUB_SERVICE_ID = "RegistryShutdownHub";

    static final String PERTHREAD_MANAGER_SERVICE_ID = "PerthreadManager";

    private static final String SERVICE_ACTIVITY_SCOREBOARD_SERVICE_ID = "ServiceActivityScoreboard";

    /**
     * The set of marker annotations for a builtin service.
     */
    private final static Set<Class> BUILTIN = CollectionFactory.newSet();

    // Split create/assign to appease generics gods
    static
    {
        BUILTIN.add(Builtin.class);
    }


    static final String PLASTIC_PROXY_FACTORY_SERVICE_ID = "PlasticProxyFactory";

    static final String LOGGER_SOURCE_SERVICE_ID = "LoggerSource";
    
    private final OneShotLock lock = new OneShotLock();

    private final OneShotLock eagerLoadLock = new OneShotLock();

    private final Map<String, Object> builtinServices = CollectionFactory.newCaseInsensitiveMap();

    private final Map<String, Class> builtinTypes = CollectionFactory.newCaseInsensitiveMap();

    private final RegistryShutdownHubImpl registryShutdownHub;

    private final LoggerSource loggerSource;

    /**
     * Map from service id to the Module that contains the service.
     */
    private final Map<String, Module> serviceIdToModule = CollectionFactory.newCaseInsensitiveMap();

    private final Map<String, ServiceLifecycle2> lifecycles = CollectionFactory.newCaseInsensitiveMap();

    private final PerthreadManager perthreadManager;

    private final PlasticProxyFactory proxyFactory;

    private final ServiceActivityTracker tracker;

    private SymbolSource symbolSource;

    private final Map<Module, Set<ServiceDef2>> moduleToServiceDefs = CollectionFactory.newMap();

    /**
     * From marker type to a list of marked service instances.
     */
    private final Map<Class, List<ServiceDef2>> markerToServiceDef = CollectionFactory.newMap();

    private final Set<ServiceDef2> allServiceDefs = CollectionFactory.newSet();

    private final OperationTracker operationTracker;

    private final TypeCoercerProxy typeCoercerProxy = new TypeCoercerProxyImpl(this);

    private final Map<Class<? extends Annotation>, Annotation> cachedAnnotationProxies = CollectionFactory.newConcurrentMap();

    private final Set<Runnable> startups = CollectionFactory.newSet();
    
    private DelegatingServiceConfigurationListener serviceConfigurationListener;
    
    /**
     * Constructs the registry from a set of module definitions and other resources.
     *
     * @param moduleDefs
     *         defines the modules (and builders, decorators, etc., within)
     * @param proxyFactory
     *         used to create new proxy objects
     * @param loggerSource
     *         used to obtain Logger instances
     * @param operationTracker
     */
    public RegistryImpl(Collection<ModuleDef2> moduleDefs, PlasticProxyFactory proxyFactory,
                        LoggerSource loggerSource, OperationTracker operationTracker)
    {
        assert moduleDefs != null;
        assert proxyFactory != null;
        assert loggerSource != null;
        assert operationTracker != null;

        this.loggerSource = loggerSource;
        this.operationTracker = operationTracker;

        this.proxyFactory = proxyFactory;
        
        serviceConfigurationListener = new DelegatingServiceConfigurationListener(
                loggerForBuiltinService(ServiceConfigurationListener.class.getSimpleName()));
        
        Logger logger = loggerForBuiltinService(PERTHREAD_MANAGER_SERVICE_ID);

        PerthreadManagerImpl ptmImpl = new PerthreadManagerImpl(logger);

        perthreadManager = ptmImpl;

        final ServiceActivityTrackerImpl scoreboardAndTracker = new ServiceActivityTrackerImpl(perthreadManager);

        tracker = scoreboardAndTracker;

        logger = loggerForBuiltinService(REGISTRY_SHUTDOWN_HUB_SERVICE_ID);

        registryShutdownHub = new RegistryShutdownHubImpl(logger);
        ptmImpl.registerForShutdown(registryShutdownHub);

        lifecycles.put("singleton", new SingletonServiceLifecycle());

        registryShutdownHub.addRegistryShutdownListener(new Runnable()
        {
            @Override
            public void run()
            {
                scoreboardAndTracker.shutdown();
            }
        });

        for (ModuleDef2 def : moduleDefs)
        {
            logger = this.loggerSource.getLogger(def.getLoggerName());

            Module module = new ModuleImpl(this, tracker, def, proxyFactory, logger);

            Set<ServiceDef2> moduleServiceDefs = CollectionFactory.newSet();

            for (String serviceId : def.getServiceIds())
            {
                ServiceDef2 serviceDef = module.getServiceDef(serviceId);

                moduleServiceDefs.add(serviceDef);
                allServiceDefs.add(serviceDef);

                Module existing = serviceIdToModule.get(serviceId);

                if (existing != null)
                    throw new RuntimeException(IOCMessages.serviceIdConflict(serviceId,
                            existing.getServiceDef(serviceId), serviceDef));

                serviceIdToModule.put(serviceId, module);

                // The service is defined but will not have gone further than that.
                tracker.define(serviceDef, Status.DEFINED);

                for (Class marker : serviceDef.getMarkers())
                    InternalUtils.addToMapList(markerToServiceDef, marker, serviceDef);
            }

            moduleToServiceDefs.put(module, moduleServiceDefs);

            addStartupsInModule(def, module, logger);
        }

        addBuiltin(SERVICE_ACTIVITY_SCOREBOARD_SERVICE_ID, ServiceActivityScoreboard.class, scoreboardAndTracker);
        addBuiltin(LOGGER_SOURCE_SERVICE_ID, LoggerSource.class, this.loggerSource);
        addBuiltin(PERTHREAD_MANAGER_SERVICE_ID, PerthreadManager.class, perthreadManager);
        addBuiltin(REGISTRY_SHUTDOWN_HUB_SERVICE_ID, RegistryShutdownHub.class, registryShutdownHub);
        addBuiltin(PLASTIC_PROXY_FACTORY_SERVICE_ID, PlasticProxyFactory.class, proxyFactory);

        validateContributeDefs(moduleDefs);
        
        serviceConfigurationListener.setDelegates(getService(ServiceConfigurationListenerHub.class).getListeners());

        scoreboardAndTracker.startup();

        SerializationSupport.setProvider(this);
        
    }

    private void addStartupsInModule(ModuleDef2 def, final Module module, final Logger logger)
    {
        for (final StartupDef startup : def.getStartups())
        {

            startups.add(new Runnable()
            {
                @Override
                public void run()
                {
                    startup.invoke(module, RegistryImpl.this, RegistryImpl.this, logger);
                }
            });
        }
    }

    /**
     * Validate that each module's ContributeDefs correspond to an actual service.
     */
    private void validateContributeDefs(Collection<ModuleDef2> moduleDefs)
    {
        for (ModuleDef2 module : moduleDefs)
        {
            Set<ContributionDef> contributionDefs = module.getContributionDefs();

            for (ContributionDef cd : contributionDefs)
            {
                String serviceId = cd.getServiceId();

                ContributionDef3 cd3 = InternalUtils.toContributionDef3(cd);

                // Ignore any optional contribution methods; there's no way to validate that
                // they contribute to a known service ... that's the point of @Optional

                if (cd3.isOptional())
                {
                    continue;
                }

                // Otherwise, check that the service being contributed to exists ...

                if (cd3.getServiceId() != null)
                {
                    if (!serviceIdToModule.containsKey(serviceId))
                    {
                        throw new IllegalArgumentException(
                                IOCMessages.contributionForNonexistentService(cd));
                    }
                } else if (!isContributionForExistentService(module, cd3))
                {
                    throw new IllegalArgumentException(
                            IOCMessages.contributionForUnqualifiedService(cd3));
                }
            }
        }

    }

    /**
     * Invoked when the contribution method didn't follow the naming convention and so doesn't identify
     * a service by id; instead there was an @Contribute to identify the service interface.
     */
    @SuppressWarnings("all")
    private boolean isContributionForExistentService(ModuleDef moduleDef, final ContributionDef2 cd)
    {
        final Set<Class> contributionMarkers = new HashSet(cd.getMarkers());

        boolean localOnly = contributionMarkers.contains(Local.class);

        Flow<ServiceDef2> serviceDefs = localOnly ? getLocalServiceDefs(moduleDef) : F.flow(allServiceDefs);

        contributionMarkers.retainAll(getMarkerAnnotations());
        contributionMarkers.remove(Local.class);

        // Match services with the correct interface AND having as markers *all* the marker annotations

        Flow<ServiceDef2> filtered = serviceDefs.filter(F.and(new Predicate<ServiceDef2>()
                                                              {
                                                                  @Override
                                                                  public boolean accept(ServiceDef2 object)
                                                                  {
                                                                      return object.getServiceInterface().equals(cd.getServiceInterface());
                                                                  }
                                                              }, new Predicate<ServiceDef2>()
                                                              {
                                                                  @Override
                                                                  public boolean accept(ServiceDef2 serviceDef)
                                                                  {
                                                                      return serviceDef.getMarkers().containsAll(contributionMarkers);
                                                                  }
                                                              }
        ));

        // That's a lot of logic; the good news is it will short-circuit as soon as it finds a single match,
        // thanks to the laziness inside Flow.

        return !filtered.isEmpty();
    }

    private Flow<ServiceDef2> getLocalServiceDefs(final ModuleDef moduleDef)
    {
        return F.flow(moduleDef.getServiceIds()).map(new Mapper<String, ServiceDef2>()
        {
            @Override
            public ServiceDef2 map(String value)
            {
                return InternalUtils.toServiceDef2(moduleDef.getServiceDef(value));
            }
        });
    }

    /**
     * It's not unreasonable for an eagerly-loaded service to decide to start a thread, at which
     * point we raise issues
     * about improper publishing of the Registry instance from the RegistryImpl constructor. Moving
     * eager loading of
     * services out to its own method should ensure thread safety.
     */
    @Override
    public void performRegistryStartup()
    {
        if (JDKUtils.JDK_1_5)
        {
            throw new RuntimeException("Your JDK version is too old."
                    + " Tapestry requires Java 1.6 or newer since version 5.4.");
        }
        eagerLoadLock.lock();

        List<EagerLoadServiceProxy> proxies = CollectionFactory.newList();

        for (Module m : moduleToServiceDefs.keySet())
            m.collectEagerLoadServices(proxies);

        // TAPESTRY-2267: Gather up all the proxies before instantiating any of them.

        for (EagerLoadServiceProxy proxy : proxies)
        {
            proxy.eagerLoadService();
        }

        for (Runnable startup : startups) {
            startup.run();
        }

        startups.clear();

        getService("RegistryStartup", Runnable.class).run();

        cleanupThread();
    }

    @Override
    public Logger getServiceLogger(String serviceId)
    {
        Module module = serviceIdToModule.get(serviceId);

        assert module != null;

        return loggerSource.getLogger(module.getLoggerName() + "." + serviceId);
    }

    private Logger loggerForBuiltinService(String serviceId)
    {
        return loggerSource.getLogger(TapestryIOCModule.class + "." + serviceId);
    }

    private <T> void addBuiltin(final String serviceId, final Class<T> serviceInterface, T service)
    {
        builtinTypes.put(serviceId, serviceInterface);
        builtinServices.put(serviceId, service);

        // Make sure each of the builtin services is also available via the Builtin annotation
        // marker.

        ServiceDef2 serviceDef = new ServiceDef2()
        {
            @Override
            public ObjectCreator createServiceCreator(ServiceBuilderResources resources)
            {
                return null;
            }

            @Override
            public Set<Class> getMarkers()
            {
                return BUILTIN;
            }

            @Override
            public String getServiceId()
            {
                return serviceId;
            }

            @Override
            public Class getServiceInterface()
            {
                return serviceInterface;
            }

            @Override
            public String getServiceScope()
            {
                return ScopeConstants.DEFAULT;
            }

            @Override
            public boolean isEagerLoad()
            {
                return false;
            }

            @Override
            public boolean isPreventDecoration()
            {
                return true;
            }
            
            @Override
            public int hashCode()
            {
                final int prime = 31;
                int result = 1;
                result = prime * result + ((serviceId == null) ? 0 : serviceId.hashCode());
                return result;
            }

            @Override
            public boolean equals(Object obj)
            {
                if (this == obj) { return true; }
                if (obj == null) { return false; }
                if (!(obj instanceof ServiceDefImpl)) { return false; }
                ServiceDef other = (ServiceDef) obj;
                if (serviceId == null)
                {
                    if (other.getServiceId() != null) { return false; }
                }
                else if (!serviceId.equals(other.getServiceId())) { return false; }
                return true;
            }
            
        };

        for (Class marker : serviceDef.getMarkers())
        {
            InternalUtils.addToMapList(markerToServiceDef, marker, serviceDef);
            allServiceDefs.add(serviceDef);
        }

        tracker.define(serviceDef, Status.BUILTIN);
    }

    @Override
    public synchronized void shutdown()
    {
        lock.lock();

        registryShutdownHub.fireRegistryDidShutdown();

        SerializationSupport.clearProvider(this);
    }

    @Override
    public <T> T getService(String serviceId, Class<T> serviceInterface)
    {
        lock.check();

        T result = checkForBuiltinService(serviceId, serviceInterface);
        if (result != null)
            return result;

        // Checking serviceId and serviceInterface is overkill; they have been checked and rechecked
        // all the way to here.

        Module containingModule = locateModuleForService(serviceId);

        return containingModule.getService(serviceId, serviceInterface);
    }

    private <T> T checkForBuiltinService(String serviceId, Class<T> serviceInterface)
    {
        Object service = builtinServices.get(serviceId);

        if (service == null)
            return null;

        try
        {
            return serviceInterface.cast(service);
        } catch (ClassCastException ex)
        {
            throw new RuntimeException(IOCMessages.serviceWrongInterface(serviceId, builtinTypes.get(serviceId),
                    serviceInterface));
        }
    }

    @Override
    public void cleanupThread()
    {
        lock.check();

        perthreadManager.cleanup();
    }

    private Module locateModuleForService(String serviceId)
    {
        Module module = serviceIdToModule.get(serviceId);

        if (module == null)
            throw new UnknownValueException(String.format("Service id '%s' is not defined by any module.", serviceId),
                    new AvailableValues("Defined service ids", serviceIdToModule));

        return module;
    }

    @Override
    public <T> Collection<T> getUnorderedConfiguration(ServiceDef3 serviceDef, Class<T> objectType)
    {
        lock.check();

        final Collection<T> result = CollectionFactory.newList();

        for (Module m : moduleToServiceDefs.keySet())
            addToUnorderedConfiguration(result, objectType, serviceDef, m);
        
        if (!isServiceConfigurationListenerServiceDef(serviceDef))
        {
            serviceConfigurationListener.onUnorderedConfiguration(serviceDef, result);
        }

        return result;
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T> List<T> getOrderedConfiguration(ServiceDef3 serviceDef, Class<T> objectType)
    {
        lock.check();

        String serviceId = serviceDef.getServiceId();
        Logger logger = getServiceLogger(serviceId);

        Orderer<T> orderer = new Orderer<T>(logger);
        Map<String, OrderedConfigurationOverride<T>> overrides = CollectionFactory.newCaseInsensitiveMap();

        // TAP5-2129. NOTICE: if someday an ordering between modules is added, this should be reverted
        // or a notice added to the documentation.
        List<Module> modules = new ArrayList<Module>(moduleToServiceDefs.keySet());
        Collections.sort(modules, new ModuleComparator());
        
        for (Module m : modules)
            addToOrderedConfiguration(orderer, overrides, objectType, serviceDef, m);

        // An ugly hack ... perhaps we should introduce a new builtin service so that this can be
        // accomplished in the normal way?

        if (serviceId.equals("MasterObjectProvider"))
        {
            ObjectProvider contribution = new ObjectProvider()
            {
                @Override
                public <T> T provide(Class<T> objectType, AnnotationProvider annotationProvider, ObjectLocator locator)
                {
                    return findServiceByMarkerAndType(objectType, annotationProvider, null);
                }
            };

            orderer.add("ServiceByMarker", (T) contribution);
        }

        for (OrderedConfigurationOverride<T> override : overrides.values())
            override.apply();

        final List<T> result = orderer.getOrdered();
        
        if (!isServiceConfigurationListenerServiceDef(serviceDef))
        {
            serviceConfigurationListener.onOrderedConfiguration(serviceDef, result);
        }
        
        return result;
    }
    
    private boolean isServiceConfigurationListenerServiceDef(ServiceDef serviceDef)
    {
        return serviceDef.getServiceId().equalsIgnoreCase(ServiceConfigurationListener.class.getSimpleName());
    }

    @Override
    public <K, V> Map<K, V> getMappedConfiguration(ServiceDef3 serviceDef, Class<K> keyType, Class<V> objectType)
    {
        lock.check();

        // When the key type is String, then a case insensitive map is used.

        Map<K, V> result = newConfigurationMap(keyType);
        Map<K, ContributionDef> keyToContribution = newConfigurationMap(keyType);
        Map<K, MappedConfigurationOverride<K, V>> overrides = newConfigurationMap(keyType);

        for (Module m : moduleToServiceDefs.keySet())
            addToMappedConfiguration(result, overrides, keyToContribution, keyType, objectType, serviceDef, m);

        for (MappedConfigurationOverride<K, V> override : overrides.values())
        {
            override.apply();
        }

        if (!isServiceConfigurationListenerServiceDef(serviceDef))
        {
            serviceConfigurationListener.onMappedConfiguration(serviceDef, result);
        }
        
        return result;
    }

    @SuppressWarnings("unchecked")
    private <K, V> Map<K, V> newConfigurationMap(Class<K> keyType)
    {
        if (keyType.equals(String.class))
        {
            Map<String, K> result = CollectionFactory.newCaseInsensitiveMap();

            return (Map<K, V>) result;
        }

        return CollectionFactory.newMap();
    }

    private <K, V> void addToMappedConfiguration(Map<K, V> map, Map<K, MappedConfigurationOverride<K, V>> overrides,
                                                 Map<K, ContributionDef> keyToContribution, Class<K> keyClass, Class<V> valueType, ServiceDef3 serviceDef,
                                                 final Module module)
    {
        String serviceId = serviceDef.getServiceId();
        Set<ContributionDef2> contributions = module.getContributorDefsForService(serviceDef);

        if (contributions.isEmpty())
            return;

        Logger logger = getServiceLogger(serviceId);

        final ServiceResources resources = new ServiceResourcesImpl(this, module, serviceDef, proxyFactory, logger);

        for (final ContributionDef def : contributions)
        {
            final MappedConfiguration<K, V> validating = new ValidatingMappedConfigurationWrapper<K, V>(valueType,
                    resources, typeCoercerProxy, map, overrides, serviceId, def, keyClass, keyToContribution);

            String description = "Invoking " + def;

            logger.debug(description);

            operationTracker.run(description, new Runnable()
            {
                @Override
                public void run()
                {
                    def.contribute(module, resources, validating);
                }
            });
        }
    }

    private <T> void addToUnorderedConfiguration(Collection<T> collection, Class<T> valueType, ServiceDef3 serviceDef,
                                                 final Module module)
    {
        String serviceId = serviceDef.getServiceId();
        Set<ContributionDef2> contributions = module.getContributorDefsForService(serviceDef);

        if (contributions.isEmpty())
            return;

        Logger logger = getServiceLogger(serviceId);

        final ServiceResources resources = new ServiceResourcesImpl(this, module, serviceDef, proxyFactory, logger);

        for (final ContributionDef def : contributions)
        {
            final Configuration<T> validating = new ValidatingConfigurationWrapper<T>(valueType, resources,
                    typeCoercerProxy, collection, serviceId);

            String description = "Invoking " + def;

            logger.debug(description);

            operationTracker.run(description, new Runnable()
            {
                @Override
                public void run()
                {
                    def.contribute(module, resources, validating);
                }
            });
        }
    }

    private <T> void addToOrderedConfiguration(Orderer<T> orderer,
                                               Map<String, OrderedConfigurationOverride<T>> overrides, Class<T> valueType, ServiceDef3 serviceDef,
                                               final Module module)
    {
        String serviceId = serviceDef.getServiceId();
        Set<ContributionDef2> contributions = module.getContributorDefsForService(serviceDef);

        if (contributions.isEmpty())
            return;

        Logger logger = getServiceLogger(serviceId);

        final ServiceResources resources = new ServiceResourcesImpl(this, module, serviceDef, proxyFactory, logger);

        for (final ContributionDef def : contributions)
        {
            final OrderedConfiguration<T> validating = new ValidatingOrderedConfigurationWrapper<T>(valueType,
                    resources, typeCoercerProxy, orderer, overrides, def);

            String description = "Invoking " + def;

            logger.debug(description);

            operationTracker.run(description, new Runnable()
            {
                @Override
                public void run()
                {
                    def.contribute(module, resources, validating);
                }
            });
        }
    }

    @Override
    public <T> T getService(Class<T> serviceInterface)
    {
        lock.check();

        return getServiceByTypeAndMarkers(serviceInterface);
    }

    @Override
    public <T> T getService(Class<T> serviceInterface, Class<? extends Annotation>... markerTypes)
    {
        lock.check();

        return getServiceByTypeAndMarkers(serviceInterface, markerTypes);
    }

    private <T> T getServiceByTypeAlone(Class<T> serviceInterface)
    {
        List<String> serviceIds = findServiceIdsForInterface(serviceInterface);

        if (serviceIds == null)
            serviceIds = Collections.emptyList();

        switch (serviceIds.size())
        {
            case 0:

                throw new RuntimeException(IOCMessages.noServiceMatchesType(serviceInterface));

            case 1:

                String serviceId = serviceIds.get(0);

                return getService(serviceId, serviceInterface);

            default:

                Collections.sort(serviceIds);

                throw new RuntimeException(IOCMessages.manyServiceMatches(serviceInterface, serviceIds));
        }
    }

    private <T> T getServiceByTypeAndMarkers(Class<T> serviceInterface, Class<? extends Annotation>... markerTypes)
    {
        if (markerTypes.length == 0)
        {
            return getServiceByTypeAlone(serviceInterface);
        }

        AnnotationProvider provider = createAnnotationProvider(markerTypes);

        Set<ServiceDef2> matches = CollectionFactory.newSet();
        List<Class> markers = CollectionFactory.newList();

        findServiceDefsMatchingMarkerAndType(serviceInterface, provider, null, markers, matches);

        return extractServiceFromMatches(serviceInterface, markers, matches);
    }

    private AnnotationProvider createAnnotationProvider(Class<? extends Annotation>... markerTypes)
    {
        final Map<Class<? extends Annotation>, Annotation> map = CollectionFactory.newMap();

        for (Class<? extends Annotation> markerType : markerTypes)
        {
            map.put(markerType, createAnnotationProxy(markerType));
        }

        return new AnnotationProvider()
        {
            @Override
            public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
            {
                return annotationClass.cast(map.get(annotationClass));
            }
        };
    }

    private <A extends Annotation> Annotation createAnnotationProxy(final Class<A> annotationType)
    {
        Annotation result = cachedAnnotationProxies.get(annotationType);

        if (result == null)
        {
            // We create a JDK proxy because its pretty quick and easy.

            InvocationHandler handler = new InvocationHandler()
            {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
                {
                    if (method.getName().equals("annotationType"))
                    {
                        return annotationType;
                    }

                    return method.invoke(proxy, args);
                }
            };

            result = (Annotation) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                    new Class[]{annotationType},
                    handler);

            cachedAnnotationProxies.put(annotationType, result);
        }

        return result;
    }

    private List<String> findServiceIdsForInterface(Class serviceInterface)
    {
        List<String> result = CollectionFactory.newList();

        for (Module module : moduleToServiceDefs.keySet())
            result.addAll(module.findServiceIdsForInterface(serviceInterface));

        for (Map.Entry<String, Object> entry : builtinServices.entrySet())
        {
            if (serviceInterface.isInstance(entry.getValue()))
                result.add(entry.getKey());
        }

        Collections.sort(result);

        return result;
    }

    @Override
    public ServiceLifecycle2 getServiceLifecycle(String scope)
    {
        lock.check();

        ServiceLifecycle result = lifecycles.get(scope);

        if (result == null)
        {
            ServiceLifecycleSource source = getService("ServiceLifecycleSource", ServiceLifecycleSource.class);

            result = source.get(scope);
        }

        if (result == null)
            throw new RuntimeException(IOCMessages.unknownScope(scope));

        return InternalUtils.toServiceLifecycle2(result);
    }

    @Override
    public List<ServiceDecorator> findDecoratorsForService(ServiceDef3 serviceDef)
    {
        lock.check();

        assert serviceDef != null;
        
        Logger logger = getServiceLogger(serviceDef.getServiceId());

        Orderer<ServiceDecorator> orderer = new Orderer<ServiceDecorator>(logger, true);

        for (Module module : moduleToServiceDefs.keySet())
        {
            Set<DecoratorDef> decoratorDefs = module.findMatchingDecoratorDefs(serviceDef);

            if (decoratorDefs.isEmpty())
                continue;

            ServiceResources resources = new ServiceResourcesImpl(this, module, serviceDef, proxyFactory, logger);

            for (DecoratorDef decoratorDef : decoratorDefs)
            {
                ServiceDecorator decorator = decoratorDef.createDecorator(module, resources);
                try
                {
                    orderer.add(decoratorDef.getDecoratorId(), decorator, decoratorDef.getConstraints());
                }
                catch (IllegalArgumentException e) {
                    throw new RuntimeException(String.format(
                            "Service %s has two different decorators methods named decorate%s in different module classes. "
                            + "You can solve this by renaming one of them and annotating it with @Match(\"%2$s\").", 
                            serviceDef.getServiceId(), decoratorDef.getDecoratorId()));
                }
            }
        }

        return orderer.getOrdered();
    }

    @Override
    public List<ServiceAdvisor> findAdvisorsForService(ServiceDef3 serviceDef)
    {
        lock.check();

        assert serviceDef != null;

        Logger logger = getServiceLogger(serviceDef.getServiceId());

        Orderer<ServiceAdvisor> orderer = new Orderer<ServiceAdvisor>(logger);

        for (Module module : moduleToServiceDefs.keySet())
        {
            Set<AdvisorDef> advisorDefs = module.findMatchingServiceAdvisors(serviceDef);

            if (advisorDefs.isEmpty())
                continue;

            ServiceResources resources = new ServiceResourcesImpl(this, module, serviceDef, proxyFactory, logger);

            for (AdvisorDef advisorDef : advisorDefs)
            {
                ServiceAdvisor advisor = advisorDef.createAdvisor(module, resources);

                orderer.add(advisorDef.getAdvisorId(), advisor, advisorDef.getConstraints());
            }
        }

        return orderer.getOrdered();
    }

    @Override
    public <T> T getObject(Class<T> objectType, AnnotationProvider annotationProvider, ObjectLocator locator,
                           Module localModule)
    {
        lock.check();

        AnnotationProvider effectiveProvider = annotationProvider != null ? annotationProvider
                : new NullAnnotationProvider();

        // We do a check here for known marker/type combinations, so that you can use a marker
        // annotation
        // to inject into a contribution method that contributes to MasterObjectProvider.
        // We also force a contribution into MasterObjectProvider to accomplish the same thing.

        T result = findServiceByMarkerAndType(objectType, annotationProvider, localModule);

        if (result != null)
            return result;

        MasterObjectProvider masterProvider = getService(IOCConstants.MASTER_OBJECT_PROVIDER_SERVICE_ID,
                MasterObjectProvider.class);

        return masterProvider.provide(objectType, effectiveProvider, locator, true);
    }

    private Collection<ServiceDef2> filterByType(Class<?> objectType, Collection<ServiceDef2> serviceDefs)
    {
        Collection<ServiceDef2> result = CollectionFactory.newSet();

        for (ServiceDef2 sd : serviceDefs)
        {
            if (objectType.isAssignableFrom(sd.getServiceInterface()))
            {
                result.add(sd);
            }
        }

        return result;
    }

    @SuppressWarnings("unchecked")
    private <T> T findServiceByMarkerAndType(Class<T> objectType, AnnotationProvider provider, Module localModule)
    {
        if (provider == null)
            return null;

        Set<ServiceDef2> matches = CollectionFactory.newSet();
        List<Class> markers = CollectionFactory.newList();

        findServiceDefsMatchingMarkerAndType(objectType, provider, localModule, markers, matches);


        // If didn't see @Local or any recognized marker annotation, then don't try to filter that
        // way. Continue on, eventually to the MasterObjectProvider service.

        if (markers.isEmpty())
        {
            return null;
        }

        return extractServiceFromMatches(objectType, markers, matches);
    }

    /**
     * Given markers and matches processed by {@link #findServiceDefsMatchingMarkerAndType(Class, org.apache.tapestry5.ioc.AnnotationProvider, Module, java.util.List, java.util.Set)}, this
     * finds the singular match, or reports an error for 0 or 2+ matches.
     */
    private <T> T extractServiceFromMatches(Class<T> objectType, List<Class> markers, Set<ServiceDef2> matches)
    {
        switch (matches.size())
        {

            case 1:

                ServiceDef def = matches.iterator().next();

                return getService(def.getServiceId(), objectType);

            case 0:

                // It's no accident that the user put the marker annotation at the injection
                // point, since it matches a known marker annotation, it better be there for
                // a reason. So if we don't get a match, we have to assume the user expected
                // one, and that is an error.

                // This doesn't help when the user places an annotation they *think* is a marker
                // but isn't really a marker (because no service is marked by the annotation).

                throw new RuntimeException(IOCMessages.noServicesMatchMarker(objectType, markers));

            default:
                throw new RuntimeException(IOCMessages.manyServicesMatchMarker(objectType, markers, matches));
        }
    }

    private <T> void findServiceDefsMatchingMarkerAndType(Class<T> objectType, AnnotationProvider provider, Module localModule, List<Class> markers,
                                                          Set<ServiceDef2> matches)
    {
        assert provider != null;

        boolean localOnly = localModule != null && provider.getAnnotation(Local.class) != null;

        matches.addAll(filterByType(objectType, localOnly ? moduleToServiceDefs.get(localModule) : allServiceDefs));

        if (localOnly)
        {
            markers.add(Local.class);
        }

        for (Class marker : markerToServiceDef.keySet())
        {
            if (provider.getAnnotation(marker) == null)
            {
                continue;
            }

            markers.add(marker);

            matches.retainAll(markerToServiceDef.get(marker));

            if (matches.isEmpty())
            {
                return;
            }
        }
    }

    @Override
    public <T> T getObject(Class<T> objectType, AnnotationProvider annotationProvider)
    {
        return getObject(objectType, annotationProvider, this, null);
    }

    @Override
    public void addRegistryShutdownListener(RegistryShutdownListener listener)
    {
        lock.check();

        registryShutdownHub.addRegistryShutdownListener(listener);
    }

    @Override
    public void addRegistryShutdownListener(Runnable listener)
    {
        lock.check();

        registryShutdownHub.addRegistryShutdownListener(listener);
    }

    @Override
    public void addRegistryWillShutdownListener(Runnable listener)
    {
        lock.check();

        registryShutdownHub.addRegistryWillShutdownListener(listener);
    }

    @Override
    public String expandSymbols(String input)
    {
        lock.check();

        // Again, a bit of work to avoid instantiating the SymbolSource until absolutely necessary.

        if (!InternalUtils.containsSymbols(input))
            return input;

        return getSymbolSource().expandSymbols(input);
    }

    /**
     * Defers obtaining the symbol source until actually needed.
     */
    private SymbolSource getSymbolSource()
    {
        if (symbolSource == null)
            symbolSource = getService(SYMBOL_SOURCE_SERVICE_ID, SymbolSource.class);

        return symbolSource;
    }

    @Override
    public <T> T autobuild(String description, final Class<T> clazz)
    {
        return invoke(description, new Invokable<T>()
        {
            @Override
            public T invoke()
            {
                return autobuild(clazz);
            }
        });
    }

    @Override
    public <T> T autobuild(final Class<T> clazz)
    {
        assert clazz != null;
        final Constructor constructor = InternalUtils.findAutobuildConstructor(clazz);

        if (constructor == null)
        {
            throw new RuntimeException(IOCMessages.noAutobuildConstructor(clazz));
        }

        Map<Class, Object> resourcesMap = CollectionFactory.newMap();
        resourcesMap.put(OperationTracker.class, RegistryImpl.this);

        InjectionResources resources = new MapInjectionResources(resourcesMap);

        ObjectCreator<T> plan = InternalUtils.createConstructorConstructionPlan(this, this, resources, null, "Invoking " + proxyFactory.getConstructorLocation(constructor).toString(), constructor);

        return plan.createObject();
    }

    @Override
    public <T> T proxy(Class<T> interfaceClass, Class<? extends T> implementationClass)
    {
        return proxy(interfaceClass, implementationClass, this);
    }

    @Override
    public <T> T proxy(Class<T> interfaceClass, Class<? extends T> implementationClass, ObjectLocator locator)
    {
        assert interfaceClass != null;
        assert implementationClass != null;

        if (InternalUtils.SERVICE_CLASS_RELOADING_ENABLED && InternalUtils.isLocalFile(implementationClass))
            return createReloadingProxy(interfaceClass, implementationClass, locator);

        return createNonReloadingProxy(interfaceClass, implementationClass, locator);
    }

    private <T> T createNonReloadingProxy(Class<T> interfaceClass, final Class<? extends T> implementationClass,
                                          final ObjectLocator locator)
    {
        final ObjectCreator<T> autobuildCreator = new ObjectCreator<T>()
        {
            @Override
            public T createObject()
            {
                return locator.autobuild(implementationClass);
            }
        };

        ObjectCreator<T> justInTime = new ObjectCreator<T>()
        {
            private T delegate;

            @Override
            public synchronized T createObject()
            {
                if (delegate == null)
                    delegate = autobuildCreator.createObject();

                return delegate;
            }
        };

        return proxyFactory.createProxy(interfaceClass, justInTime,
                String.format("<Autobuild proxy %s(%s)>", implementationClass.getName(), interfaceClass.getName()));
    }

    private <T> T createReloadingProxy(Class<T> interfaceClass, final Class<? extends T> implementationClass,
                                       ObjectLocator locator)
    {
        ReloadableObjectCreator creator = new ReloadableObjectCreator(proxyFactory, implementationClass.getClassLoader(),
                implementationClass.getName(), loggerSource.getLogger(implementationClass), this, locator);

        getService(UpdateListenerHub.class).addUpdateListener(creator);

        return proxyFactory.createProxy(interfaceClass, implementationClass, (ObjectCreator<T>) creator,
                String.format("<Autoreload proxy %s(%s)>", implementationClass.getName(), interfaceClass.getName()));
    }

    @Override
    public Object provideServiceProxy(String serviceId)
    {
        return getService(serviceId, Object.class);
    }

    @Override
    public void run(String description, Runnable operation)
    {
        operationTracker.run(description, operation);
    }

    @Override
    public <T> T invoke(String description, Invokable<T> operation)
    {
        return operationTracker.invoke(description, operation);
    }

    @Override
    public <T> T perform(String description, IOOperation<T> operation) throws IOException
    {
        return operationTracker.perform(description, operation);
    }

    @Override
    public Set<Class> getMarkerAnnotations()
    {
        return markerToServiceDef.keySet();
    }
    
    final private static class ModuleComparator implements Comparator<Module> {
        @Override
        public int compare(Module m1, Module m2)
        {
            return m1.getLoggerName().compareTo(m2.getLoggerName());
        }
    }
    
    final static private class DelegatingServiceConfigurationListener implements ServiceConfigurationListener {
        
        final private Logger logger;
        
        private List<ServiceConfigurationListener> delegates;
        private Map<ServiceDef, Map> mapped = CollectionFactory.newMap();
        private Map<ServiceDef, Collection> unordered = CollectionFactory.newMap();
        private Map<ServiceDef, List> ordered = CollectionFactory.newMap();
        
        public DelegatingServiceConfigurationListener(Logger logger)
        {
            this.logger = logger;
        }

        public void setDelegates(List<ServiceConfigurationListener> delegates)
        {
            
            this.delegates = delegates;
            
            for (ServiceDef serviceDef : mapped.keySet())
            {
                for (ServiceConfigurationListener delegate : delegates)
                {
                    delegate.onMappedConfiguration(serviceDef, Collections.unmodifiableMap(mapped.get(serviceDef)));
                }
            }

            for (ServiceDef serviceDef : unordered.keySet())
            {
                for (ServiceConfigurationListener delegate : delegates)
                {
                    delegate.onUnorderedConfiguration(serviceDef, Collections.unmodifiableCollection(unordered.get(serviceDef)));
                }
            }

            for (ServiceDef serviceDef : ordered.keySet())
            {
                for (ServiceConfigurationListener delegate : delegates)
                {
                    delegate.onOrderedConfiguration(serviceDef, Collections.unmodifiableList(ordered.get(serviceDef)));
                }
            }
            
            mapped.clear();
            mapped = null;
            unordered.clear();
            unordered = null;
            ordered.clear();
            ordered = null;

        }
        
        @Override
        public void onOrderedConfiguration(ServiceDef serviceDef, List configuration)
        {
            log("ordered", serviceDef, configuration);
            if (delegates == null)
            {
                ordered.put(serviceDef, configuration);
            }
            else
            {
                for (ServiceConfigurationListener delegate : delegates)
                {
                    delegate.onOrderedConfiguration(serviceDef, Collections.unmodifiableList(configuration));
                }
            }
        }

        @Override
        public void onUnorderedConfiguration(ServiceDef serviceDef, Collection configuration)
        {
            log("unordered", serviceDef, configuration);
            if (delegates == null)
            {
                unordered.put(serviceDef, configuration);
            }
            else
            {
                for (ServiceConfigurationListener delegate : delegates)
                {
                    delegate.onUnorderedConfiguration(serviceDef, Collections.unmodifiableCollection(configuration));
                }
            }
        }

        @Override
        public void onMappedConfiguration(ServiceDef serviceDef, Map configuration)
        {
            log("mapped", serviceDef, configuration);
            if (delegates == null)
            {
                mapped.put(serviceDef, configuration);
            }
            else
            {
                for (ServiceConfigurationListener delegate : delegates)
                {
                    delegate.onMappedConfiguration(serviceDef, Collections.unmodifiableMap(configuration));
                }
            }
            
        }
        
        private void log(String type, ServiceDef serviceDef, Object configuration)
        {
            if (logger.isDebugEnabled())
            {
                logger.debug(String.format("Service %s %s configuration: %s", 
                        serviceDef.getServiceId(), type, configuration.toString()));
            }
        }
        
    }
    
}
