package com.eucalyptus.configurable; import java.lang.reflect.Field; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import com.eucalyptus.event.PassiveEventListener; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import com.google.common.collect.Multimaps; import edu.ucsb.eucalyptus.msgs.ComponentProperty; public class PropertyDirectory { private static Logger LOG = Logger.getLogger( PropertyDirectory.class ); private static Map<String, ConfigurableProperty> fqMap = Maps.newHashMap( ); private static Multimap<String, ConfigurableProperty> fqPrefixMap = Multimaps.newHashMultimap( ); private static Map<String, ConfigurableProperty> fqPendingMap = Maps.newHashMap( ); private static Multimap<String, ConfigurableProperty> fqPendingPrefixMap = Multimaps.newHashMultimap( ); private static List<ConfigurablePropertyBuilder> builders = Lists.newArrayList( new StaticPropertyEntry.StaticPropertyBuilder( ), new SingletonDatabasePropertyEntry.DatabasePropertyBuilder( ), new MultiDatabasePropertyEntry.DatabasePropertyBuilder( )); //FIXME: make this dynamic kkthx. public static class NoopEventListener extends PassiveEventListener<ConfigurableProperty> { public static NoopEventListener NOOP = new NoopEventListener( ); @Override public void firingEvent( ConfigurableProperty t ) {} } @SuppressWarnings( { "unchecked" } ) public static ConfigurableProperty buildPropertyEntry( Class c, Field field ) { for ( ConfigurablePropertyBuilder b : builders ) { try { ConfigurableProperty prop = null; try { prop = b.buildProperty( c, field ); } catch ( ConfigurablePropertyException e ) { throw e; } catch ( Throwable t ) { LOG.error( "Failed to prepare configurable field: " + c.getCanonicalName( ) + "." + field.getName( ) ); System.exit( 1 ); } if ( prop != null ) { ConfigurableClass configurableAnnot = (ConfigurableClass) c.getAnnotation(ConfigurableClass.class); if ( configurableAnnot.deferred() ) { if ( !fqPendingMap.containsKey( prop.getQualifiedName( ) ) ) { fqPendingMap.put( prop.getQualifiedName( ), prop ); fqPendingPrefixMap.put( prop.getEntrySetName( ), prop ); return prop; } } else { if ( !fqMap.containsKey( prop.getQualifiedName( ) ) ) { fqMap.put( prop.getQualifiedName( ), prop ); fqPrefixMap.put( prop.getEntrySetName( ), prop ); return prop; } else { RuntimeException r = new RuntimeException( "Duplicate configurable field in same config file: \n" + "-> " + fqMap.get( prop.getQualifiedName( ) ).getDefiningClass( ).getCanonicalName( ) + "." + field.getName( ) + "\n" + "-> " + c.getCanonicalName( ) + "." + field.getName( ) + "\n" ); LOG.fatal( r, r ); System.exit( 1 ); throw r; } } } } catch ( ConfigurablePropertyException e ) { LOG.debug( e, e ); } } return null; } public static List<String> getPropertyEntrySetNames( ) { return Lists.newArrayList( fqPrefixMap.keySet( ) ); } public static List<ConfigurableProperty> getPropertyEntrySet( ) { List<ConfigurableProperty> props = Lists.newArrayList( ); for ( String fqPrefix : fqPrefixMap.keySet( ) ) { props.addAll( getPropertyEntrySet( fqPrefix ) ); } return props; } public static List<ConfigurableProperty> getPropertyEntrySet( String prefix ) { List<ConfigurableProperty> props = Lists.newArrayList( ); for ( ConfigurableProperty fq : fqPrefixMap.get( prefix ) ) { props.add( fq ); } return props; } public static List<ConfigurableProperty> getPropertyEntrySet( String prefix, String alias ) { List<ConfigurableProperty> props = Lists.newArrayList( ); for ( ConfigurableProperty fq : fqPrefixMap.get( prefix ) ) { if(fq.getAlias().equals(alias)) props.add( fq ); } return props; } public static ConfigurableProperty getPropertyEntry( String fq ) throws IllegalAccessException { if ( !fqMap.containsKey( fq ) ) { throw new IllegalAccessException( "No such property: " + fq ); } else { return fqMap.get( fq ); } } public static List<ConfigurableProperty> getPendingPropertyEntrySet( String prefix ) { List<ConfigurableProperty> props = Lists.newArrayList( ); for ( ConfigurableProperty fq : fqPendingPrefixMap.get( prefix ) ) { props.add( fq ); } return props; } public static String getEntrySetDescription( String entrySetName ) { return "Temporary description"; } public static List<ComponentProperty> getComponentPropertySet( String prefix ) { List<ComponentProperty> componentProps = Lists.newArrayList(); List<ConfigurableProperty> props = getPropertyEntrySet( prefix ); for (ConfigurableProperty prop : props) { componentProps.add(new ComponentProperty(prop.getWidgetType().toString(), prop.getDisplayName(), prop.getValue(), prop.getQualifiedName())); } return componentProps; } public static void addProperty(ConfigurableProperty prop) { if ( !fqMap.containsKey( prop.getQualifiedName( ) ) ) { fqMap.put( prop.getQualifiedName( ), prop ); fqPrefixMap.put( prop.getEntrySetName( ), prop ); } } public static void removeProperty(ConfigurableProperty prop) { if ( fqMap.containsKey( prop.getQualifiedName( ) ) ) { fqMap.remove( prop.getQualifiedName( ) ); fqPrefixMap.remove( prop.getEntrySetName( ), prop ); } } public static List<ComponentProperty> getComponentPropertySet(String prefix, String alias) { List<ComponentProperty> componentProps = Lists.newArrayList(); List<ConfigurableProperty> props = getPropertyEntrySet( prefix, alias ); for (ConfigurableProperty prop : props) { componentProps.add(new ComponentProperty(prop.getWidgetType().toString(), prop.getDisplayName(), prop.getValue(), prop.getQualifiedName())); } return componentProps; } }