package com.eucalyptus.component; import java.net.URI; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import org.apache.log4j.Logger; import com.eucalyptus.bootstrap.Bootstrap; import com.eucalyptus.bootstrap.BootstrapException; import com.eucalyptus.bootstrap.Bootstrapper; import com.eucalyptus.records.EventType; import com.eucalyptus.records.EventRecord; import com.eucalyptus.util.LogUtil; import com.eucalyptus.util.async.Callback; import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; public class Components { private static Logger LOG = Logger .getLogger( Components.class ); private static Map<Class<? extends ComponentInformation>, Map<String, ? extends ComponentInformation>> componentInformation = new ConcurrentHashMap<Class<? extends ComponentInformation>, Map<String, ? extends ComponentInformation>>( ); static { componentInformation.put( Service.class, new ConcurrentHashMap<String, Service>( ) ); componentInformation.put( Component.class, new ConcurrentHashMap<String, Component>( ) ); componentInformation.put( Lifecycle.class, new ConcurrentHashMap<String, Lifecycle>( ) ); componentInformation.put( Configuration.class, new ConcurrentHashMap<String, Configuration>( ) ); //TODO: do this during discovery! } public static com.eucalyptus.bootstrap.Component delegate = com.eucalyptus.bootstrap.Component.eucalyptus; @SuppressWarnings( "unchecked" ) public static List<Component> list( ) { return new ArrayList( Components.lookup( Component.class ).values( ) ); } private static <T extends ComponentInformation> Class getRealType( Class<T> maybeSubclass ) { Class type = null; for ( Class c : componentInformation.keySet( ) ) { if ( c.isAssignableFrom( maybeSubclass ) ) { type = c; return type; } } Components.dumpState( ); throw BootstrapException.throwFatal( "Failed bootstrapping component registry. Missing entry for component info type: " + maybeSubclass.getSimpleName( ) ); } private static <T> Map<String, T> lookup( Class type ) { return ( Map<String, T> ) componentInformation.get( getRealType( type ) ); } private static void dumpState( ) { for ( Class c : componentInformation.keySet( ) ) { for ( Entry<String, ? extends ComponentInformation> e : componentInformation.get( c ).entrySet( ) ) { LOG.info( EventRecord.here( Bootstrap.class, EventType.COMPONENT_REGISTRY_DUMP, c.getSimpleName( ), e.getKey( ), e.getValue( ).getClass( ) .getCanonicalName( ) ) ); } } } public static <T extends ComponentInformation> boolean contains( Class<T> type, String name ) { return Components.lookup( type ).containsKey( name ); } private static <T extends ComponentInformation> void remove( T componentInfo ) { Map<String, T> infoMap = lookup( componentInfo.getClass( ) ); infoMap.remove( componentInfo.getName( ) ); } private static <T extends ComponentInformation> void put( T componentInfo ) { Map<String, T> infoMap = lookup( componentInfo.getClass( ) ); if ( infoMap.containsKey( componentInfo.getName( ) ) ) { throw BootstrapException.throwFatal( "Failed bootstrapping component registry. Duplicate information for component '" + componentInfo.getName( ) + "': " + componentInfo.getClass( ).getSimpleName( ) + " as " + getRealType( componentInfo.getClass( ) ) ); } else { infoMap.put( componentInfo.getName( ), componentInfo ); } } public static <T extends ComponentInformation> void deregister( T componentInfo ) { remove( componentInfo ); EventRecord.here( Bootstrap.class, EventType.COMPONENT_DEREGISTERED, componentInfo.getName( ), componentInfo.getClass( ).getSimpleName( ) ).info( ); } static <T extends ComponentInformation> void register( T componentInfo ) { if ( !contains( componentInfo.getClass( ), componentInfo.getName( ) ) ) { EventRecord.here( Bootstrap.class, EventType.COMPONENT_REGISTERED, componentInfo.getName( ), componentInfo.getClass( ).getSimpleName( ) ).info( ); Components.put( componentInfo ); } } public static <T extends ComponentInformation> T lookup( Class<T> type, String name ) throws NoSuchElementException { if ( !contains( type, name ) ) { try { Components.create( name, null ); return Components.lookup( type, name ); } catch ( ServiceRegistrationException ex ) { throw new NoSuchElementException( "Missing entry for component '" + name + "' info type: " + type.getSimpleName( ) + " (" + getRealType( type ).getCanonicalName( ) ); } } else { return ( T ) Components.lookup( type ).get( name ); } } public static Component lookup( String componentName ) throws NoSuchElementException { return Components.lookup( Component.class, componentName ); } public static Component lookup( com.eucalyptus.bootstrap.Component component ) throws NoSuchElementException { return Components.lookup( Component.class, component.name( ) ); } public static boolean contains( String componentName ) { return Components.contains( Component.class, componentName ); } public static boolean contains( com.eucalyptus.bootstrap.Component component ) { return Components.contains( Component.class, component.name( ) ); } public static Component create( String name, URI uri ) throws ServiceRegistrationException { Component c = new Component( name, uri ); register( c ); return c; } private final static Function<Component, String> componentToString = componentToString( ); public static Function<Component, String> componentToString( ) { if ( componentToString != null ) { return componentToString; } else { synchronized ( Components.class ) { return new Function<Component, String>( ) { @Override public String apply( Component comp ) { final StringBuilder buf = new StringBuilder( ); buf.append( LogUtil.header( comp.getName( ) + " component configuration" ) ).append( "\n" ); buf.append( "-> Enabled/Local: " + comp.isEnabled( ) + "/" + comp.isLocal( ) ).append( "\n" ); buf.append( "-> State/Running: " + comp.getState( ) + "/" + comp.isRunning( ) ).append( "\n" ); buf.append( "-> Builder: " + comp.getBuilder( ).getClass( ).getSimpleName( ) ).append( "\n" ); buf.append( "-> Disable/Remote cli: " + System.getProperty( "euca." + comp.getPeer( ).name( ) + ".disable" ) + "/" + System.getProperty( "euca." + comp.getPeer( ).name( ) + ".remote" ) ).append( "\n" ); buf.append( "-> Configuration: " + ( comp.getConfiguration( ).getResource( ) != null ? comp.getConfiguration( ).getResource( ).getOrigin( ) : "null" ) ).append( "\n" ); for ( Bootstrapper b : comp.getConfiguration( ).getBootstrappers( ) ) { buf.append( "-> " + b.toString( ) ).append( "\n" ); } buf.append( LogUtil.subheader( comp.getName( ) + " services" ) ).append( "\n" ); for ( Service s : comp.getServices( ) ) { buf.append( "-> Service: " + s.getName( ) + " " + s.getUri( ) ).append( "\n" ); buf.append( "|-> Dispatcher: " + s.getDispatcher( ).getName( ) + " for " + s.getDispatcher( ).getAddress( ) ).append( "\n" ); buf.append( "|-> Service Endpoint: " + s.getEndpoint( ) ).append( "\n" ); //TODO: restore this. destinationBuffer.append( "|-> Credential DN: " + s.getKeys( ).getCertificate( ).getSubjectDN( ).toString( ) ); buf.append( "|-> Service config: " + LogUtil.dumpObject( s.getServiceConfiguration( ) ) ).append( "\n" ); } return buf.toString( ); } }; } } } private static final Callback.Success<Component> componentPrinter = componentPrinter( ); public static Callback.Success<Component> componentPrinter( ) { if ( componentPrinter != null ) { return componentPrinter; } else { synchronized ( Components.class ) { return new Callback.Success<Component>( ) { @Override public void fire( Component comp ) { LOG.info( componentToString.apply( comp ) ); } }; } } } private static final Function<Dispatcher, String> dispatcherToString = dispatcherToString( ); public static Function<Dispatcher, String> dispatcherToString( ) { if ( dispatcherToString != null ) { return dispatcherToString; } else { synchronized ( Components.class ) { return new Function<Dispatcher, String>( ) { @Override public String apply( Dispatcher comp ) { final StringBuilder buf = new StringBuilder( ); buf.append( "-> Dispatcher key=" ).append( comp.getName( ) ).append( " entry=" ).append( comp ); return buf.toString( ); } }; } } } private static final Callback.Success<Dispatcher> dispatcherPrinter = dispatcherPrinter( ); public static Callback.Success<Dispatcher> dispatcherPrinter( ) { if ( dispatcherPrinter != null ) { return dispatcherPrinter; } else { synchronized ( Components.class ) { return new Callback.Success<Dispatcher>( ) { @Override public void fire( Dispatcher arg0 ) { LOG.info( dispatcherToString.apply( arg0 ) ); } }; } } } private final static Callback.Success<Component> configurationPrinter = configurationPrinter( ); public static Callback.Success<Component> configurationPrinter( ) { if ( configurationPrinter != null ) { return configurationPrinter; } else { synchronized ( Components.class ) { return new Callback.Success<Component>( ) { @Override public void fire( Component comp ) { LOG.info( configurationToString.apply( comp ) ); } }; } } } private final static Function<Component, String> configurationToString = configurationToString( ); private static final Function<Bootstrapper, String> bootstrapperToString = new Function<Bootstrapper, String>( ) { @Override public String apply( Bootstrapper b ) { return b.getClass( ).getName( ) + " provides=" + b.getProvides( ) + " deplocal=" + b.getDependsLocal( ) + " depremote=" + b.getDependsRemote( ); } }; public static Function<Component, String> configurationToString( ) { if ( configurationToString != null ) { return configurationToString; } else { synchronized ( Components.class ) { return new Function<Component, String>( ) { @Override public String apply( Component comp ) { final StringBuilder buf = new StringBuilder( ); buf.append( String.format( "%s -> disable/remote cli: %s/%s", comp.getName( ), System.getProperty( String.format( "euca.%s.disable", comp.getPeer( ).name( ) ) ), System.getProperty( String.format( "euca.%s.remote", comp.getPeer( ).name( ) ) ) ) ).append( "\n" ); buf.append( String.format( "%s -> enabled/local/init: %s/%s/%s", comp.getName( ), comp.isEnabled( ), comp.isLocal( ), comp.isRunning( ) ) ).append( "\n" ); buf.append( String.format( "%s -> configuration: %s", comp.getName( ), ( comp.getConfiguration( ).getResource( ) != null ? comp.getConfiguration( ).getResource( ).getOrigin( ) : "null" ) ) ).append( "\n" ); buf.append( String.format( "%s -> bootstrappers: %s", comp.getName( ), Iterables.transform( comp.getConfiguration( ).getBootstrappers( ), bootstrapperToString ) ) ).append( "\n" ); return buf.toString( ); } }; } } } }