package com.eucalyptus.bootstrap; import static com.eucalyptus.system.Ats.From; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.List; import org.apache.log4j.Logger; import com.eucalyptus.records.EventType; import com.google.common.collect.Lists; import com.eucalyptus.records.EventRecord; public class BootstrapperDiscovery extends ServiceJarDiscovery { private static Logger LOG = Logger.getLogger( BootstrapperDiscovery.class ); private static List<Class> bootstrappers = Lists.newArrayList( ); public BootstrapperDiscovery() {} @Override public boolean processClass( Class candidate ) throws Throwable { String bc = candidate.getCanonicalName( ); Class bootstrapper = this.getBootstrapper( candidate ); if ( !From( candidate ).has( RunDuring.class ) ) { throw BootstrapException.throwFatal( "Bootstrap class does not specify execution stage (RunDuring.value=Bootstrap.Stage): " + bc ); } else if ( !From( candidate ).has( Provides.class ) ) { throw BootstrapException.throwFatal( "Bootstrap class does not specify provided component (Provides.value=Component): " + bc ); } //TODO: maybe more checks at pre-load time for bootstrappers. this.bootstrappers.add( bootstrapper ); return true; } @SuppressWarnings( "unchecked" ) public static List<Bootstrapper> getBootstrappers( ) { List<Bootstrapper> ret = Lists.newArrayList( ); for ( Class c : bootstrappers ) { if ( c.equals( SystemBootstrapper.class ) ) continue; try { EventRecord.here( BootstrapperDiscovery.class, EventType.BOOTSTRAPPER_INIT,"<init>()V", c.getCanonicalName( ) ).info( ); try { ret.add( ( Bootstrapper ) c.newInstance( ) ); } catch ( Exception e ) { EventRecord.here( BootstrapperDiscovery.class, EventType.BOOTSTRAPPER_INIT,"getInstance()L", c.getCanonicalName( ) ).info( ); Method m = c.getDeclaredMethod( "getInstance", new Class[] {} ); ret.add( ( Bootstrapper ) m.invoke( null, new Object[] {} ) ); } } catch ( Exception e ) { throw BootstrapException.throwFatal( "Error in <init>()V and getInstance()L; in bootstrapper: " + c.getCanonicalName( ), e ); } } return ret; } @SuppressWarnings( "unchecked" ) private Class getBootstrapper( Class candidate ) throws Exception { if ( Modifier.isAbstract( candidate.getModifiers( ) ) ) throw new InstantiationException( candidate.getName( ) + " is abstract." ); if ( !Bootstrapper.class.isAssignableFrom( candidate ) ) throw new InstantiationException( candidate + " does not conform to " + Bootstrapper.class ); LOG.debug( "Candidate bootstrapper: " + candidate.getName( ) ); if ( !Modifier.isPublic( candidate.getDeclaredConstructor( new Class[] {} ).getModifiers( ) ) ) { Method factory = candidate.getDeclaredMethod( "getInstance", new Class[] {} ); if ( !Modifier.isStatic( factory.getModifiers( ) ) || !Modifier.isPublic( factory.getModifiers( ) ) ) { throw new InstantiationException( candidate.getCanonicalName( ) + " does not declare public <init>()V or public static getInstance()L;" ); } } LOG.debug( "Found bootstrapper: " + candidate.getName( ) ); return candidate; } @Override public Double getPriority( ) { return 0.0d; } }