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 static final long serialVersionUID = 6150762006182320443L;
|
||||||
private ComponentInitialisationException chain;
|
|
||||||
|
|
||||||
|
|
||||||
public ComponentInitialisationException( )
|
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 );
|
super( message , cause );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ComponentInitialisationException( String message )
|
public ComponentInitialisationException( final String message )
|
||||||
{
|
{
|
||||||
super( message );
|
super( message );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ComponentInitialisationException( Throwable cause )
|
public ComponentInitialisationException( final Throwable cause )
|
||||||
{
|
{
|
||||||
super( 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 failed;
|
||||||
private boolean initialised;
|
private boolean initialised;
|
||||||
// private boolean active;
|
private boolean active;
|
||||||
|
|
||||||
|
|
||||||
public ComponentRegistry( )
|
public ComponentRegistry( )
|
||||||
|
@ -63,6 +63,12 @@ public class ComponentRegistry
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isActive( )
|
||||||
|
{
|
||||||
|
return active;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public ComponentState getState( String name )
|
public ComponentState getState( String name )
|
||||||
{
|
{
|
||||||
return this.byName.get( name );
|
return this.byName.get( name );
|
||||||
|
@ -157,7 +163,8 @@ public class ComponentRegistry
|
||||||
|
|
||||||
public ComponentRegistry register( Collection< NewComponentInfo< ? > > components )
|
public ComponentRegistry register( Collection< NewComponentInfo< ? > > components )
|
||||||
throws ComponentCreationException , DuplicateComponentException , RecursiveDependenciesException ,
|
throws ComponentCreationException , DuplicateComponentException , RecursiveDependenciesException ,
|
||||||
DependencyInjectionException , AmbiguousComponentException , ComponentInitialisationException
|
DependencyInjectionException , AmbiguousComponentException , ComponentInitialisationException ,
|
||||||
|
ComponentStartupException
|
||||||
{
|
{
|
||||||
if ( this.failed ) {
|
if ( this.failed ) {
|
||||||
throw new IllegalStateException( "register() called on failed registry" );
|
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;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -232,12 +247,14 @@ public class ComponentRegistry
|
||||||
|
|
||||||
|
|
||||||
public boolean destroy( )
|
public boolean destroy( )
|
||||||
|
throws IllegalStateException
|
||||||
{
|
{
|
||||||
return this.destroy( null );
|
return this.destroy( null );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean destroy( Collection< Throwable > errors )
|
public boolean destroy( Collection< Throwable > errors )
|
||||||
|
throws IllegalStateException
|
||||||
{
|
{
|
||||||
if ( this.failed ) {
|
if ( this.failed ) {
|
||||||
throw new IllegalStateException( "destroy() called on failed registry" );
|
throw new IllegalStateException( "destroy() called on failed registry" );
|
||||||
|
@ -245,6 +262,9 @@ public class ComponentRegistry
|
||||||
if ( !this.initialised ) {
|
if ( !this.initialised ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if ( this.active && !this.stop( errors ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for ( int i = this.components.size( ) - 1 ; i >= 0 ; i-- ) {
|
for ( int i = this.components.size( ) - 1 ; i >= 0 ; i-- ) {
|
||||||
try {
|
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 ,
|
private static int resolveNewDependencies( ArrayList< TempBuildRec > adding ,
|
||||||
ArrayList< ComponentState > nComponents , HashMap< String , ComponentState > byName ,
|
ArrayList< ComponentState > nComponents , HashMap< String , ComponentState > byName ,
|
||||||
HashMap< Class< ? > , ArrayList< ComponentState > > byType )
|
HashMap< Class< ? > , ArrayList< ComponentState > > byType )
|
||||||
|
@ -391,4 +473,30 @@ public class ComponentRegistry
|
||||||
throw e;
|
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 final boolean autostart;
|
||||||
private boolean initialised;
|
private boolean initialised;
|
||||||
private boolean active;
|
private boolean active;
|
||||||
|
private boolean wasActive;
|
||||||
|
|
||||||
private final HashSet< ComponentState > dependencies = new HashSet< >( );
|
private final HashSet< ComponentState > dependencies = new HashSet< >( );
|
||||||
private final HashSet< ComponentState > reverseDependencies = 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 )
|
void setInitialised( boolean initialised )
|
||||||
{
|
{
|
||||||
this.initialised = initialised;
|
this.initialised = initialised;
|
||||||
|
|
Loading…
Reference in a new issue