/******************************************************************************
 * Copyright (c) 2010 Oracle
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Konstantin Komissarchik - initial implementation and ongoing maintenance
 ******************************************************************************/

package org.eclipse.wst.common.project.facet.core.runtime.internal;

import static org.eclipse.wst.common.project.facet.core.util.internal.PluginUtil.instantiate;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.common.project.facet.core.IListener;
import org.eclipse.wst.common.project.facet.core.IProjectFacet;
import org.eclipse.wst.common.project.facet.core.IProjectFacetVersion;
import org.eclipse.wst.common.project.facet.core.ProjectFacetsManager;
import org.eclipse.wst.common.project.facet.core.VersionFormatException;
import org.eclipse.wst.common.project.facet.core.internal.FacetCorePlugin;
import org.eclipse.wst.common.project.facet.core.internal.ProblemLog;
import org.eclipse.wst.common.project.facet.core.internal.ProjectFacetVersion;
import org.eclipse.wst.common.project.facet.core.runtime.IRuntime;
import org.eclipse.wst.common.project.facet.core.runtime.IRuntimeBridge;
import org.eclipse.wst.common.project.facet.core.runtime.IRuntimeComponent;
import org.eclipse.wst.common.project.facet.core.runtime.IRuntimeComponentType;
import org.eclipse.wst.common.project.facet.core.runtime.IRuntimeComponentVersion;
import org.eclipse.wst.common.project.facet.core.runtime.RuntimeManager;
import org.eclipse.wst.common.project.facet.core.runtime.events.IRuntimeLifecycleEvent;
import org.eclipse.wst.common.project.facet.core.runtime.events.IRuntimeLifecycleListener;
import org.eclipse.wst.common.project.facet.core.runtime.events.internal.RuntimeLifecycleListenerRegistry;
import org.eclipse.wst.common.project.facet.core.runtime.events.internal.ValidationStatusChangedEvent;
import org.eclipse.wst.common.project.facet.core.util.internal.IndexedSet;
import org.eclipse.wst.common.project.facet.core.util.internal.VersionExpr;

/**
 * @author <a href="mailto:konstantin.komissarchik@oracle.com">Konstantin Komissarchik</a>
 */

public final class RuntimeManagerImpl
{
    private static final String EXTENSION_ID = "runtimes"; //$NON-NLS-1$
    private static final String BRIDGES_EXTENSION_ID = "runtimeBridges"; //$NON-NLS-1$

    private static final String ATTR_CLASS = "class"; //$NON-NLS-1$
    private static final String ATTR_ID = "id"; //$NON-NLS-1$
    private static final String ATTR_TYPE = "type"; //$NON-NLS-1$
    private static final String ATTR_VERSION = "version"; //$NON-NLS-1$
    private static final String EL_ADAPTER = "adapter"; //$NON-NLS-1$
    private static final String EL_BRIDGE = "bridge"; //$NON-NLS-1$
    private static final String EL_FACET = "facet"; //$NON-NLS-1$
    private static final String EL_FACTORY = "factory"; //$NON-NLS-1$
    private static final String EL_RUNTIME_COMPONENT = "runtime-component"; //$NON-NLS-1$
    private static final String EL_RUNTIME_COMPONENT_TYPE = "runtime-component-type"; //$NON-NLS-1$
    private static final String EL_RUNTIME_COMPONENT_VERSION = "runtime-component-version"; //$NON-NLS-1$
    private static final String EL_SUPPORTED = "supported"; //$NON-NLS-1$
    private static final String EL_UNSUPPORTED = "unsupported"; //$NON-NLS-1$
    private static final String EL_VERSION_COMPARATOR = "version-comparator"; //$NON-NLS-1$

    private static final String ANY = "any"; //$NON-NLS-1$
    
    private static final IndexedSet<String,IRuntimeComponentType> runtimeComponentTypes;
    private static final IndexedSet<String,IRuntime> runtimes;
    private static final List<Mapping> supportedMappings;
    private static final List<Mapping> unsupportedMappings;
    private static final Map<String,IRuntimeBridge> bridges;
    private static final Set<IListener> listeners;
    private static final RuntimeLifecycleListenerRegistry runtimeLifecycleListenerRegistry;
    private static RuntimeValidationThread runtimeValidationThread;
    
    static
    {
        runtimeComponentTypes = new IndexedSet<String,IRuntimeComponentType>();
        runtimes = new IndexedSet<String,IRuntime>();
        supportedMappings = new ArrayList<Mapping>();
        unsupportedMappings = new ArrayList<Mapping>();
        bridges = new HashMap<String,IRuntimeBridge>();
        listeners = new HashSet<IListener>();
        runtimeLifecycleListenerRegistry = new RuntimeLifecycleListenerRegistry();
        runtimeValidationThread = null;
        
        readMetadata();
        readBridgesExtensions();
    }
    
    private RuntimeManagerImpl() {}
    
    public static Set<IRuntimeComponentType> getRuntimeComponentTypes()
    {
        return runtimeComponentTypes.getItemSet();
    }
    
    public static boolean isRuntimeComponentTypeDefined( final String id )
    {
        return runtimeComponentTypes.containsKey( id );
    }
    
    public static IRuntimeComponentType getRuntimeComponentType( final String id )
    {
        final IRuntimeComponentType rc = runtimeComponentTypes.getItemByKey( id );
        
        if( rc == null )
        {
            final String msg 
                = NLS.bind( Resources.runtimeComponentTypeNotDefined, id );
            
            throw new IllegalArgumentException( msg );
        }
        
        return rc;
    }
    
    public static IRuntimeComponent createRuntimeComponent( final IRuntimeComponentVersion rcv,
                                                            final Map<String,String> properties )
    {
        final RuntimeComponent rc = new RuntimeComponent();
        
        rc.setRuntimeComponentVersion( rcv );
        
        if( properties != null )
        {
            for( Map.Entry<String,String> entry : properties.entrySet() )
            {
                rc.setProperty( entry.getKey(), entry.getValue() );
            }
        }
        
        return rc;
    }
    
    public static Set<IRuntime> getRuntimes()
    {
        synchronized( runtimes )
        {
            bridge();
            return new HashSet<IRuntime>( runtimes.getItemSet() );
        }
    }
    
    public static Set<IRuntime> getRuntimes( final Set<IProjectFacetVersion> facets )
    {
        synchronized( runtimes )
        {
            bridge();
            
            final Set<IRuntime> result = new HashSet<IRuntime>();
            
            for( IRuntime r : runtimes.getItemSet() )
            {
                boolean supports = true;
                
                for( IProjectFacetVersion fv : facets )
                {
                    if( ! r.supports( fv ) )
                    {
                        supports = false;
                        break;
                    }
                }
                
                if( supports )
                {
                    result.add( r );
                }
            }
            
            return result;
        }
    }
    
    public static boolean isRuntimeDefined( final String name )
    {
        synchronized( runtimes )
        {
            bridge();
            return runtimes.containsKey( name );
        }
    }
    
    public static IRuntime getRuntime( final String name )
    {
        synchronized( runtimes )
        {
            bridge();
            
            final IRuntime runtime = runtimes.getItemByKey( name );
            
            if( runtime == null )
            {
                final String msg = NLS.bind( Resources.runtimeNotDefined, name );
                throw new IllegalArgumentException( msg );
            }
            
            return runtime;
        }
    }
    
    public static IRuntime defineRuntime( final String name,
                                          final List<IRuntimeComponent> components,
                                          final Map<String,String> properties )
    {
        synchronized( runtimes )
        {
            final Runtime r = new Runtime();
            
            r.setName( name );
            
            for( IRuntimeComponent rc : components )
            {
                r.addRuntimeComponent( rc );
            }
            
            if( properties != null )
            {
                for( Map.Entry<String,String> entry : properties.entrySet() )
                {
                    r.setProperty( entry.getKey(), entry.getValue() );
                }
            }
            
            runtimes.addItemWithKey( r.getName(), r );
            
            notifyRuntimeListeners();
            
            return r;
        }
    }
    
    public static void deleteRuntime( final IRuntime runtime )
    {
        synchronized( runtimes )
        {
            if( runtimes.removeItemByKey( runtime.getName() ) )
            {
                notifyRuntimeListeners();
            }
        }
    }
    
    public static void addRuntimeListener( final IListener listener )
    {
        synchronized( listeners )
        {
            listeners.add( listener );
        }
    }
    
    public static void removeRuntimeListener( final IListener listener )
    {
        synchronized( listeners )
        {
            listeners.remove( listener );
        }
    }
    
    private static void notifyRuntimeListeners()
    {
        for( IListener listener : listeners )
        {
            try
            {
                listener.handle();
            }
            catch( Exception e )
            {
                FacetCorePlugin.log( e );
            }
        }
    }
    
    public static void addListener( final IRuntimeLifecycleListener listener,
                                    final IRuntimeLifecycleEvent.Type... types )
    {
        synchronized( runtimeLifecycleListenerRegistry )
        {
            runtimeLifecycleListenerRegistry.addListener( listener, types );
            
            if( runtimeValidationThread == null )
            {
                runtimeValidationThread = new RuntimeValidationThread();
                runtimeValidationThread.start();
            }
        }
    }
    
    public static void removeListener( final IRuntimeLifecycleListener listener )
    {
        synchronized( runtimeLifecycleListenerRegistry )
        {
            runtimeLifecycleListenerRegistry.removeListener( listener );
            
            if( runtimeValidationThread != null && runtimeLifecycleListenerRegistry.isEmpty() )
            {
                runtimeValidationThread.terminate();
                runtimeValidationThread = null;
            }
        }
    }
    
    static Set<IProjectFacetVersion> getSupportedFacets( final List<IRuntimeComponent> composition )
    {
        final Set<IProjectFacetVersion> result = new HashSet<IProjectFacetVersion>();
        
        // Process the supported declarations first.
        
        for( IRuntimeComponent rc : composition )
        {
            for( Mapping m : supportedMappings )
            {
                try
                {
                    result.addAll( m.evaluate( rc ) );                    
                }
                catch( CoreException e )
                {
                    FacetCorePlugin.log( e.getStatus() );
                }
                catch( VersionFormatException e )
                {
                    FacetCorePlugin.log( e );
                }
            }
        }
            
        // Unsupported declarations win over supported, therefore
        // they must be processed afterwards
        
        for( IRuntimeComponent rc : composition )
        {
            for( Mapping m : unsupportedMappings )
            {
                try
                {
                    result.removeAll( m.evaluate( rc ) );                    
                }
                catch( CoreException e )
                {
                    FacetCorePlugin.log( e.getStatus() );
                }
                catch( VersionFormatException e )
                {
                    FacetCorePlugin.log( e );
                }
            }
        }
        
        return result;
    }
    
    private static void bridge()
    {
        boolean modified = false;
        
        for( Map.Entry<String,IRuntimeBridge> entry : bridges.entrySet() )
        {
            final String brid = entry.getKey();
            final IRuntimeBridge br = entry.getValue();
            
            // Find the runtimes belonging to this bridge that are currently
            // in the system.
            
            final Map<String,BridgedRuntime> existing = new HashMap<String,BridgedRuntime>();
            
            for( IRuntime r : runtimes.getItemSet() )
            {
                if( r instanceof BridgedRuntime )
                {
                    final BridgedRuntime bridged = (BridgedRuntime) r;
                    
                    if( bridged.getBridgeId().equals( brid ) )
                    {
                        existing.put( bridged.getNativeRuntimeId(), bridged );
                    }
                }
            }
            
            // Get the new set of exported runtimes.
            
            final Set<String> exported;
            
            try
            {
                exported = br.getExportedRuntimeNames();
            }
            catch( CoreException e )
            {
                FacetCorePlugin.log( e );
                
                for( BridgedRuntime r : existing.values() )
                {
                    runtimes.removeItemByKey( r.getName() );
                    modified = true;
                }
                
                continue;
            }
            
            // Remove the absolete entries.
            
            for( BridgedRuntime r : existing.values() )
            {
                if( ! exported.contains( r.getNativeRuntimeId() ) )
                {
                    runtimes.removeItemByKey( r.getName() );
                    modified = true;
                }
            }
            
            // Create the new entries.
            
            for( String id : exported )
            {
                if( ! existing.containsKey( id ) )
                {
                    try
                    {
                        final IRuntimeBridge.IStub stub = br.bridge( id );
                        
                        final BridgedRuntime r 
                            = new BridgedRuntime( brid, id, stub );
                        
                        r.setName( createUniqueRuntimeName( id ) );
                        
                        runtimes.addItemWithKey( r.getName(), r );
                        modified = true;
                    }
                    catch( CoreException e )
                    {
                        FacetCorePlugin.log( e );
                    }
                }
            }
            
            if( modified )
            {
                notifyRuntimeListeners();
            }
        }
    }
    
    private static String createUniqueRuntimeName( final String suggestion )
    {
        String name = suggestion;
        
        for( int i = 1; runtimes.containsKey( name ); i++ )
        {
            name = suggestion + " (" + i + ")"; //$NON-NLS-1$ //$NON-NLS-2$
        }
        
        return name;
    }
    
    private static void readMetadata()
    {
        final IExtensionRegistry registry = Platform.getExtensionRegistry();
        
        final IExtensionPoint point 
            = registry.getExtensionPoint( FacetCorePlugin.PLUGIN_ID, 
                                          EXTENSION_ID );
        
        if( point == null )
        {
            throw new RuntimeException( "Extension point not found!" ); //$NON-NLS-1$
        }
        
        final List<IConfigurationElement> cfgels = new ArrayList<IConfigurationElement>();
        
        for( IExtension extension : point.getExtensions() )
        {
            for( IConfigurationElement cfgel : extension.getConfigurationElements() )
            {
                cfgels.add( cfgel );
            }
        }
        
        for( IConfigurationElement config : cfgels )
        {
            if( config.getName().equals( EL_RUNTIME_COMPONENT_TYPE ) )
            {
                readRuntimeComponentType( config );
            }
        }

        for( IConfigurationElement config : cfgels )
        {
            if( config.getName().equals( EL_RUNTIME_COMPONENT_VERSION ) )
            {
                readRuntimeComponentVersion( config );
            }
        }
        
        calculateVersionComparisonTables();

        for( IConfigurationElement config : cfgels )
        {
            if( config.getName().equals( EL_ADAPTER ) )
            {
                readAdapter( config );
            }
        }

        for( IConfigurationElement config : cfgels )
        {
            if( config.getName().equals( EL_SUPPORTED ) )
            {
                readMapping( config, supportedMappings );
            }
        }

        for( IConfigurationElement config : cfgels )
        {
            if( config.getName().equals( EL_UNSUPPORTED ) )
            {
                readMapping( config, unsupportedMappings );
            }
        }
    }
    
    private static void readRuntimeComponentType( final IConfigurationElement config )
    {
        final String id = config.getAttribute( ATTR_ID );

        if( id == null )
        {
            reportMissingAttribute( config, ATTR_ID );
            return;
        }
        
        final RuntimeComponentType rct = new RuntimeComponentType();
        rct.setId( id );
        rct.setPluginId( config.getContributor().getName() );

        final IConfigurationElement[] children = config.getChildren();
        
        for( int i = 0; i < children.length; i++ )
        {
            final IConfigurationElement child = children[ i ];
            final String childName = child.getName();
            
            if( childName.equals( EL_VERSION_COMPARATOR ) )
            {
                final String clname = child.getAttribute( ATTR_CLASS );
                
                if( clname == null )
                {
                    reportMissingAttribute( child, ATTR_CLASS );
                    return;
                }
                
                rct.setVersionComparator( clname );
            }
        }
        
        runtimeComponentTypes.addItemWithKey( id, rct );
    }
    
    private static void readRuntimeComponentVersion( final IConfigurationElement config )
    {
        final String type = config.getAttribute( ATTR_TYPE );

        if( type == null )
        {
            reportMissingAttribute( config, ATTR_TYPE );
            return;
        }
        
        final String ver = config.getAttribute( ATTR_VERSION );

        if( ver == null )
        {
            reportMissingAttribute( config, ATTR_VERSION );
            return;
        }
        
        final RuntimeComponentType rct 
            = (RuntimeComponentType) runtimeComponentTypes.getItemByKey( type );
        
        if( rct == null )
        {
            final String msg
                = NLS.bind( Resources.runtimeComponentTypeNotDefined, type ) +
                  NLS.bind( Resources.usedInPlugin, config.getContributor().getName() );
            
            FacetCorePlugin.log( msg );
            
            return;
        }
        
        final RuntimeComponentVersion rcv = new RuntimeComponentVersion();
        
        rcv.setRuntimeComponentType( rct );
        rcv.setVersionString( ver );
        rcv.setPluginId( config.getContributor().getName() );
        
        rct.addVersion( rcv );
    }
    
    /**
     * Pre-computes the tables that describe how versions of runtime components
     * compare to each other. This allows the IRuntimeComponentVersion.compareTo() 
     * operation, which is called rather frequently, to be reduced to a hash 
     * table lookup instead of having to do a parse and comparison of two 
     * version strings.
     */
    
    private static void calculateVersionComparisonTables()
    {
        final List<IRuntimeComponentType> badRuntimeComponentTypes 
            = new ArrayList<IRuntimeComponentType>();
        
        for( IRuntimeComponentType rct : runtimeComponentTypes.getItemSet() )
        {
            try
            {
                final Comparator<String> comp = rct.getVersionComparator();
                
                final List<IRuntimeComponentVersion> versions 
                    = new ArrayList<IRuntimeComponentVersion>( rct.getVersions() );
                
                final Map<IRuntimeComponentVersion,Map<IRuntimeComponentVersion,Integer>> compTables
                    = new HashMap<IRuntimeComponentVersion,Map<IRuntimeComponentVersion,Integer>>();
                
                for( IRuntimeComponentVersion rcv : versions )
                {
                    compTables.put( rcv, new HashMap<IRuntimeComponentVersion,Integer>() );
                }
                
                for( int i = 0, n = versions.size(); i < n; i++ )
                {
                    final IRuntimeComponentVersion iVer = versions.get( i );
                    final String iVerStr = iVer.getVersionString();
                    final Map<IRuntimeComponentVersion,Integer> iCompTable = compTables.get( iVer );
                    
                    for( int j = i + 1; j < n; j++ )
                    {
                        final IRuntimeComponentVersion jVer = versions.get( j );
                        final String jVerStr = jVer.getVersionString();
                        final Map<IRuntimeComponentVersion,Integer> jCompTable = compTables.get( jVer );
                        
                        final int result = comp.compare( iVerStr, jVerStr );
                        
                        iCompTable.put( jVer, new Integer( result ) );
                        jCompTable.put( iVer, new Integer( result * -1 ) );
                    }
                }
                
                for( Map.Entry<IRuntimeComponentVersion,Map<IRuntimeComponentVersion,Integer>> entry
                     : compTables.entrySet() )
                {
                    final RuntimeComponentVersion rcv = (RuntimeComponentVersion) entry.getKey();
                    rcv.setComparisonTable( entry.getValue() );
                }
            }
            catch( Exception e )
            {
                // The failure here is due to the problem loading the provided
                // version comparator or due to the problem comparing the
                // version string. In either case, we log the exception and
                // remove all traces of this runtime component type from the 
                // system to keep a faulty runtime component type from dragging
                // down the entire system.
                
                FacetCorePlugin.log( e );
                badRuntimeComponentTypes.add( rct );
            }
        }
        
        for( IRuntimeComponentType rct : badRuntimeComponentTypes )
        {
            runtimeComponentTypes.removeItem( rct );
        }
    }
    
    private static void readAdapter( final IConfigurationElement config )
    {
        IRuntimeComponentType rctype = null;
        IRuntimeComponentVersion rcversion = null;
        String factory = null;
        final List<String> types = new ArrayList<String>();
        
        final IConfigurationElement[] children = config.getChildren();
        
        for( int i = 0; i < children.length; i++ )
        {
            final IConfigurationElement child = children[ i ];
            final String childName = child.getName();
            
            if( childName.equals( EL_RUNTIME_COMPONENT ) )
            {
                final String id = child.getAttribute( ATTR_ID );

                if( id == null )
                {
                    reportMissingAttribute( child, ATTR_ID );
                    return;
                }
                
                if( ! isRuntimeComponentTypeDefined( id ) )
                {
                    final String msg
                        = NLS.bind( Resources.runtimeComponentTypeNotDefined, id ) +
                          NLS.bind( Resources.usedInPlugin, 
                                    child.getContributor().getName() );
                    
                    FacetCorePlugin.log( msg );
                    
                    return;
                }
                
                rctype = getRuntimeComponentType( id );
                
                final String version = child.getAttribute( ATTR_VERSION );
                
                if( version != null )
                {
                    if( ! rctype.hasVersion( version ) )
                    {
                        String msg
                            = NLS.bind( Resources.runtimeComponentVersionNotDefined,
                                        id, version );
                        
                        msg += NLS.bind( Resources.usedInPlugin, 
                                         config.getContributor().getName() );
                        
                        FacetCorePlugin.log( msg );
                        
                        return;
                    }
                    
                    rcversion = rctype.getVersion( version );
                }
            }
            else if( childName.equals( EL_FACTORY ) )
            {
                factory = child.getAttribute( ATTR_CLASS );

                if( factory == null )
                {
                    reportMissingAttribute( child, ATTR_CLASS );
                    return;
                }
            }
            else if( childName.equals( ATTR_TYPE ) )
            {
                final String type = child.getAttribute( ATTR_CLASS );

                if( type == null )
                {
                    reportMissingAttribute( child, ATTR_CLASS );
                    return;
                }
                else
                {
                    types.add( type );
                }
            }
        }
        
        final Set<IRuntimeComponentVersion> versions;
        
        if( rcversion == null )
        {
            versions = rctype.getVersions();
        }
        else
        {
            versions = Collections.singleton( rcversion );
        }
        
        final String plugin = config.getContributor().getName();
        
        for( IRuntimeComponentVersion rcv : versions )
        {
            final RuntimeComponentVersion v = (RuntimeComponentVersion) rcv;
            
            for( String type : types )
            {
                v.addAdapterFactory( type, plugin, factory );
            }
        }
    }
    
    private static void readMapping( final IConfigurationElement config, 
                                     final List<Mapping> mappings )
    {
        final Mapping m = new Mapping();
        final IConfigurationElement[] children = config.getChildren();
        
        for( int i = 0; i < children.length; i++ )
        {
            final IConfigurationElement child = children[ i ];
            final String childName = child.getName();
            
            if( childName.equals( EL_FACET ) )
            {
                final IProjectFacet f = readProjectFacetRef( child );
                
                if( f == null )
                {
                    continue;
                }
                
                final String v = child.getAttribute( ATTR_VERSION );
                VersionExpr<ProjectFacetVersion> expr = null;
                
                if( v != null )
                {
                    try
                    {
                        final String pluginId = config.getContributor().getName();
                        expr = new VersionExpr<ProjectFacetVersion>( f, v, pluginId );
                    }
                    catch( CoreException e )
                    {
                        FacetCorePlugin.log( e.getStatus() );
                        continue;
                    }
                }
                
                m.facets.put( f, expr );
            }
            else if( childName.equals( EL_RUNTIME_COMPONENT ) )
            {
                if( child.getAttribute( ANY ) == null )
                {
                    final IRuntimeComponentType rct 
                        = readRuntimeComponentTypeRef( child );
                    
                    if( rct == null )
                    {
                        continue;
                    }
                    
                    final String v = child.getAttribute( ATTR_VERSION );
                    VersionExpr<RuntimeComponentVersion> expr = null;
                    
                    if( v != null )
                    {
                        try
                        {
                            final String pluginId = config.getContributor().getName();
                            expr = new VersionExpr<RuntimeComponentVersion>( rct, v, pluginId );
                        }
                        catch( CoreException e )
                        {
                            FacetCorePlugin.log( e.getStatus() );
                            continue;
                        }
                    }
                    
                    m.runtimeComponents.put( rct, expr );
                }
            }
        }
        
        mappings.add( m );
    }
    
    private static void readBridgesExtensions()
    {
        final IExtensionRegistry registry = Platform.getExtensionRegistry();
        
        final IExtensionPoint point 
            = registry.getExtensionPoint( FacetCorePlugin.PLUGIN_ID, 
                                          BRIDGES_EXTENSION_ID );
        
        if( point == null )
        {
            throw new RuntimeException( "Extension point not found!" ); //$NON-NLS-1$
        }
        
        final List<IConfigurationElement> cfgels = new ArrayList<IConfigurationElement>();
        
        for( IExtension extension : point.getExtensions() )
        {
            for( IConfigurationElement cfgel : extension.getConfigurationElements() )
            {
                cfgels.add( cfgel );
            }
        }

        for( IConfigurationElement config : cfgels )
        {
            if( config.getName().equals( EL_BRIDGE ) )
            {
                final String id = config.getAttribute( ATTR_ID );

                if( id == null )
                {
                    reportMissingAttribute( config, ATTR_ID );
                    return;
                }
                
                final String clname = config.getAttribute( ATTR_CLASS );

                if( clname == null )
                {
                    reportMissingAttribute( config, ATTR_CLASS );
                    return;
                }
                
                final String pluginId = config.getContributor().getName();
                final IRuntimeBridge br = instantiate( pluginId, clname, IRuntimeBridge.class );
                
                if( br == null )
                {
                    continue;
                }
                
                bridges.put( id, br );
            }
        }
    }
    
    private static IRuntimeComponentType readRuntimeComponentTypeRef( final IConfigurationElement config )
    {
        final String id = config.getAttribute( ATTR_ID );
        
        if( id == null )
        {
            reportMissingAttribute( config, ATTR_ID );
            return null;
        }
        
        if( ! isRuntimeComponentTypeDefined( id ) )
        {
            final String msg
                = NLS.bind( Resources.runtimeComponentTypeNotDefined, id ) +
                  NLS.bind( Resources.usedInPlugin, 
                            config.getContributor().getName() );
            
            FacetCorePlugin.log( msg );
            
            return null;
        }
        
        return getRuntimeComponentType( id );
    }
    
    private static IProjectFacet readProjectFacetRef( final IConfigurationElement config )
    {
        final String id = config.getAttribute( ATTR_ID );

        if( id == null )
        {
            reportMissingAttribute( config, ATTR_ID );
            return null;
        }
        
        if( ! ProjectFacetsManager.isProjectFacetDefined( id ) )
        {
            ProblemLog.reportMissingFacet( id, config.getContributor().getName() );
            return null;
        }
        
        return ProjectFacetsManager.getProjectFacet( id );
    }
    
    private static void reportMissingAttribute( final IConfigurationElement el,
                                                final String attribute )
    {
        final String[] params 
            = new String[] { el.getContributor().getName(), el.getName(), attribute };
        
        final String msg = NLS.bind( Resources.missingAttribute, params ); 
    
        FacetCorePlugin.log( msg );
    }
    
    private static final class Mapping
    {
        public final Map<IProjectFacet,VersionExpr<ProjectFacetVersion>> facets 
            = new HashMap<IProjectFacet,VersionExpr<ProjectFacetVersion>>();
        
        public final Map<IRuntimeComponentType,VersionExpr<RuntimeComponentVersion>> runtimeComponents 
            = new HashMap<IRuntimeComponentType,VersionExpr<RuntimeComponentVersion>>();
        
        private Set<IProjectFacetVersion> evaluate( final IRuntimeComponent rc )
        
            throws CoreException
            
        {
            final IRuntimeComponentType rct = rc.getRuntimeComponentType();
            final IRuntimeComponentVersion rcv = rc.getRuntimeComponentVersion();
            
            if( this.runtimeComponents.containsKey( rct ) )
            {
                final VersionExpr<RuntimeComponentVersion> expr = this.runtimeComponents.get( rct );
                
                if( expr != null && ! expr.check( rcv ) )
                {
                    return Collections.emptySet();
                }
            }
            else if( ! this.runtimeComponents.isEmpty() )
            {
                return Collections.emptySet();
            }
            
            final Set<IProjectFacetVersion> result = new HashSet<IProjectFacetVersion>();
            
            for( Map.Entry<IProjectFacet,VersionExpr<ProjectFacetVersion>> entry 
                 : this.facets.entrySet() )
            {
                final IProjectFacet f = entry.getKey();
                final VersionExpr<ProjectFacetVersion> expr = entry.getValue();
                
                for( IProjectFacetVersion fv : f.getVersions() )
                {
                    if( expr == null || expr.check( fv ) )
                    {
                        result.add( fv );
                    }
                }
            }
            
            return result;
        }
    }
    
    private static final class RuntimeValidationThread

        extends Thread
        
    {
        private boolean isAborted;
        private Map<String,IStatus> validationResults;
        
        public RuntimeValidationThread()
        {
            this.isAborted = false;
            this.validationResults = new HashMap<String,IStatus>();
        }
        
        private IStatus getValidationResult( final IRuntime runtime )
        {
            synchronized( this.validationResults )
            {
                return this.validationResults.get( runtime.getName() );
            }
        }
        
        private void setValidationResult( final IRuntime runtime,
                                          final IStatus validationResult )
        {
            synchronized( this.validationResults )
            {
                this.validationResults.put( runtime.getName(), validationResult );
            }
        }
        
        @Override
        public void run()
        {
            while( ! this.isAborted )
            {
                for( IRuntime runtime : RuntimeManager.getRuntimes() )
                {
                    final IStatus oldResult = getValidationResult( runtime );
                    final IStatus newResult = runtime.validate( new NullProgressMonitor() );
                    
                    if( oldResult == null || ! oldResult.getMessage().equals( newResult.getMessage() ) )
                    {
                        setValidationResult( runtime, newResult );
                        
                        final IRuntimeLifecycleEvent event
                            = new ValidationStatusChangedEvent( runtime, oldResult, newResult );
                        
                        runtimeLifecycleListenerRegistry.notifyListeners( event );
                    }
                }

                try
                {
                    Thread.sleep( 1000 );
                }
                catch( InterruptedException e ) {}
            }
        }
        
        public void terminate()
        {
            this.isAborted = true;
        }
    }

    public static final class Resources
    
        extends NLS
        
    {
        public static String missingAttribute;
        public static String runtimeComponentTypeNotDefined;
        public static String runtimeComponentVersionNotDefined;
        public static String runtimeNotDefined;
        public static String usedInPlugin;
        
        static
        {
            initializeMessages( RuntimeManagerImpl.class.getName(), 
                                Resources.class );
        }
    }
    
}