Components registry - Start, stop, restart
This commit is contained in:
parent
d083be2676
commit
53128c5e77
5 changed files with 283 additions and 20 deletions
|
@ -6,7 +6,6 @@ public class ComponentInitialisationException
|
|||
{
|
||||
|
||||
private static final long serialVersionUID = 6150762006182320443L;
|
||||
private ComponentInitialisationException chain;
|
||||
|
||||
|
||||
public ComponentInitialisationException( )
|
||||
|
@ -15,34 +14,21 @@ public class ComponentInitialisationException
|
|||
}
|
||||
|
||||
|
||||
public ComponentInitialisationException( String message , Throwable cause )
|
||||
public ComponentInitialisationException( final String message , final Throwable cause )
|
||||
{
|
||||
super( message , cause );
|
||||
}
|
||||
|
||||
|
||||
public ComponentInitialisationException( String message )
|
||||
public ComponentInitialisationException( final String message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
|
||||
public ComponentInitialisationException( Throwable cause )
|
||||
public ComponentInitialisationException( final Throwable cause )
|
||||
{
|
||||
super( cause );
|
||||
}
|
||||
|
||||
|
||||
ComponentInitialisationException( Throwable cause , ComponentInitialisationException initial )
|
||||
{
|
||||
super( "failed to revert incomplete initialisation" , cause );
|
||||
this.chain = initial;
|
||||
}
|
||||
|
||||
|
||||
public ComponentInitialisationException getChain( )
|
||||
{
|
||||
return chain;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ public class ComponentRegistry
|
|||
|
||||
private boolean failed;
|
||||
private boolean initialised;
|
||||
// private boolean active;
|
||||
private boolean active;
|
||||
|
||||
|
||||
public ComponentRegistry( )
|
||||
|
@ -63,6 +63,12 @@ public class ComponentRegistry
|
|||
}
|
||||
|
||||
|
||||
public boolean isActive( )
|
||||
{
|
||||
return active;
|
||||
}
|
||||
|
||||
|
||||
public ComponentState getState( String name )
|
||||
{
|
||||
return this.byName.get( name );
|
||||
|
@ -157,7 +163,8 @@ public class ComponentRegistry
|
|||
|
||||
public ComponentRegistry register( Collection< NewComponentInfo< ? > > components )
|
||||
throws ComponentCreationException , DuplicateComponentException , RecursiveDependenciesException ,
|
||||
DependencyInjectionException , AmbiguousComponentException , ComponentInitialisationException
|
||||
DependencyInjectionException , AmbiguousComponentException , ComponentInitialisationException ,
|
||||
ComponentStartupException
|
||||
{
|
||||
if ( this.failed ) {
|
||||
throw new IllegalStateException( "register() called on failed registry" );
|
||||
|
@ -206,7 +213,15 @@ public class ComponentRegistry
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: activate autostart components
|
||||
// Activate autostart components
|
||||
if ( this.active ) {
|
||||
for ( int i = 0 ; i < nOld + nAdd ; i++ ) {
|
||||
ComponentState cmp = this.components.get( i );
|
||||
if ( cmp.hasAutostart( ) ) {
|
||||
startComponentWithFailure( cmp );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
@ -232,12 +247,14 @@ public class ComponentRegistry
|
|||
|
||||
|
||||
public boolean destroy( )
|
||||
throws IllegalStateException
|
||||
{
|
||||
return this.destroy( null );
|
||||
}
|
||||
|
||||
|
||||
public boolean destroy( Collection< Throwable > errors )
|
||||
throws IllegalStateException
|
||||
{
|
||||
if ( this.failed ) {
|
||||
throw new IllegalStateException( "destroy() called on failed registry" );
|
||||
|
@ -245,6 +262,9 @@ public class ComponentRegistry
|
|||
if ( !this.initialised ) {
|
||||
return true;
|
||||
}
|
||||
if ( this.active && !this.stop( errors ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for ( int i = this.components.size( ) - 1 ; i >= 0 ; i-- ) {
|
||||
try {
|
||||
|
@ -264,6 +284,68 @@ public class ComponentRegistry
|
|||
}
|
||||
|
||||
|
||||
public void start( )
|
||||
throws IllegalStateException , ComponentStartupException
|
||||
{
|
||||
if ( this.failed ) {
|
||||
throw new IllegalStateException( "start() called on failed registry" );
|
||||
}
|
||||
if ( !this.initialised ) {
|
||||
throw new IllegalStateException( "start() called on uninitialised registry" );
|
||||
}
|
||||
if ( this.active ) {
|
||||
return;
|
||||
}
|
||||
|
||||
int nComponents = this.components.size( );
|
||||
for ( int i = 0 ; i < nComponents ; i++ ) {
|
||||
ComponentState cmp = this.components.get( i );
|
||||
if ( cmp.hasAutostart( ) && !cmp.isActive( ) ) {
|
||||
startComponentWithFailure( cmp );
|
||||
}
|
||||
}
|
||||
|
||||
this.initialised = true;
|
||||
}
|
||||
|
||||
|
||||
public boolean stop( )
|
||||
throws IllegalStateException
|
||||
{
|
||||
return this.stop( null );
|
||||
}
|
||||
|
||||
|
||||
public boolean stop( Collection< Throwable > errors )
|
||||
throws IllegalStateException
|
||||
{
|
||||
if ( this.failed ) {
|
||||
throw new IllegalStateException( "destroy() called on failed registry" );
|
||||
}
|
||||
if ( !this.active ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for ( int i = this.components.size( ) - 1 ; i >= 0 ; i-- ) {
|
||||
try {
|
||||
ComponentState cmp = this.components.get( i );
|
||||
if ( cmp.isActive( ) ) {
|
||||
cmp.runLifecycleAction( LifecycleStage.STOP );
|
||||
cmp.setActive( false );
|
||||
}
|
||||
} catch ( Throwable t ) {
|
||||
if ( errors != null ) {
|
||||
errors.add( t );
|
||||
}
|
||||
this.failed = true;
|
||||
}
|
||||
}
|
||||
|
||||
this.active = false;
|
||||
return !this.failed;
|
||||
}
|
||||
|
||||
|
||||
private static int resolveNewDependencies( ArrayList< TempBuildRec > adding ,
|
||||
ArrayList< ComponentState > nComponents , HashMap< String , ComponentState > byName ,
|
||||
HashMap< Class< ? > , ArrayList< ComponentState > > byType )
|
||||
|
@ -391,4 +473,30 @@ public class ComponentRegistry
|
|||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void startComponentWithFailure( ComponentState cmp )
|
||||
throws ComponentStartupException
|
||||
{
|
||||
try {
|
||||
this.startComponent( cmp );
|
||||
} catch ( ComponentStartupException e ) {
|
||||
this.failed = true;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void startComponent( ComponentState cmp )
|
||||
throws ComponentStartupException
|
||||
{
|
||||
try {
|
||||
cmp.runLifecycleAction( LifecycleStage.START );
|
||||
} catch ( ComponentStartupException e ) {
|
||||
throw e;
|
||||
} catch ( Throwable t ) {
|
||||
throw new ComponentStartupException( t );
|
||||
}
|
||||
cmp.setActive( true );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package info.ebenoit.ebul.cmp;
|
||||
|
||||
|
||||
public class ComponentRestartException
|
||||
extends ComponentException
|
||||
{
|
||||
|
||||
private static final long serialVersionUID = -6812486665718289373L;
|
||||
|
||||
|
||||
public ComponentRestartException( )
|
||||
{
|
||||
super( );
|
||||
}
|
||||
|
||||
|
||||
public ComponentRestartException( final String message , final Throwable cause )
|
||||
{
|
||||
super( message , cause );
|
||||
}
|
||||
|
||||
|
||||
public ComponentRestartException( final String message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
|
||||
public ComponentRestartException( final Throwable cause )
|
||||
{
|
||||
super( cause );
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package info.ebenoit.ebul.cmp;
|
||||
|
||||
|
||||
public class ComponentStartupException
|
||||
extends ComponentException
|
||||
{
|
||||
|
||||
private static final long serialVersionUID = -8010582342593242803L;
|
||||
|
||||
|
||||
public ComponentStartupException( )
|
||||
{
|
||||
super( );
|
||||
}
|
||||
|
||||
|
||||
public ComponentStartupException( final String message , final Throwable cause )
|
||||
{
|
||||
super( message , cause );
|
||||
}
|
||||
|
||||
|
||||
public ComponentStartupException( final String message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
|
||||
public ComponentStartupException( final Throwable cause )
|
||||
{
|
||||
super( cause );
|
||||
}
|
||||
|
||||
}
|
|
@ -17,6 +17,7 @@ public final class ComponentState
|
|||
private final boolean autostart;
|
||||
private boolean initialised;
|
||||
private boolean active;
|
||||
private boolean wasActive;
|
||||
|
||||
private final HashSet< ComponentState > dependencies = new HashSet< >( );
|
||||
private final HashSet< ComponentState > reverseDependencies = new HashSet< >( );
|
||||
|
@ -104,6 +105,106 @@ public final class ComponentState
|
|||
}
|
||||
|
||||
|
||||
public void start( )
|
||||
throws ComponentStartupException , IllegalStateException
|
||||
{
|
||||
if ( !this.initialised ) {
|
||||
throw new IllegalStateException( "attempting to start uninitialised component" );
|
||||
}
|
||||
if ( this.registry.hasFailed( ) ) {
|
||||
throw new IllegalStateException( "registry has failed" );
|
||||
}
|
||||
if ( !this.registry.isActive( ) ) {
|
||||
throw new IllegalStateException( "registry is inactive" );
|
||||
}
|
||||
|
||||
startNoChecks( );
|
||||
}
|
||||
|
||||
|
||||
public Throwable stop( )
|
||||
throws IllegalStateException
|
||||
{
|
||||
if ( this.registry.hasFailed( ) ) {
|
||||
throw new IllegalStateException( "registry has failed" );
|
||||
}
|
||||
this.wasActive = this.active;
|
||||
if ( this.active ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for ( ComponentState rdepState : this.reverseDependencies ) {
|
||||
Throwable t = rdepState.stop( );
|
||||
if ( t != null ) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
this.runLifecycleAction( LifecycleStage.START );
|
||||
} catch ( Throwable t ) {
|
||||
return t;
|
||||
}
|
||||
|
||||
this.active = false;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public void restart( )
|
||||
throws IllegalStateException , ComponentRestartException
|
||||
{
|
||||
if ( this.registry.hasFailed( ) ) {
|
||||
throw new IllegalStateException( "registry has failed" );
|
||||
}
|
||||
|
||||
Throwable t = this.stop( );
|
||||
if ( t != null ) {
|
||||
throw new ComponentRestartException( "failed to stop" , t );
|
||||
}
|
||||
|
||||
this.startIfPreviouslyActive( );
|
||||
}
|
||||
|
||||
|
||||
private void startNoChecks( )
|
||||
throws ComponentStartupException
|
||||
{
|
||||
if ( this.active ) {
|
||||
return;
|
||||
}
|
||||
for ( ComponentState depState : this.dependencies ) {
|
||||
depState.startNoChecks( );
|
||||
}
|
||||
try {
|
||||
this.runLifecycleAction( LifecycleStage.START );
|
||||
} catch ( ComponentStartupException e ) {
|
||||
throw e;
|
||||
} catch ( Throwable t ) {
|
||||
throw new ComponentStartupException( t );
|
||||
}
|
||||
this.active = true;
|
||||
}
|
||||
|
||||
|
||||
private void startIfPreviouslyActive( )
|
||||
throws ComponentRestartException
|
||||
{
|
||||
if ( this.wasActive ) {
|
||||
try {
|
||||
this.startNoChecks( );
|
||||
} catch ( ComponentStartupException e ) {
|
||||
throw new ComponentRestartException( "failed to restart " + this , e );
|
||||
}
|
||||
|
||||
for ( ComponentState rDepState : this.reverseDependencies ) {
|
||||
rDepState.startIfPreviouslyActive( );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void setInitialised( boolean initialised )
|
||||
{
|
||||
this.initialised = initialised;
|
||||
|
|
Loading…
Reference in a new issue