| /****************************************************************************** |
| * 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 ); |
| } |
| } |
| |
| } |