{
FutureTask<T> singletonFuture;
synchronized (this) {
if (disposed)
{
throw new ComponentLifecycleException("This ComponentManager has already been destroyed");
}
// if singleton already created, simply return the existing singleton
T singleton = getExistingInstance( false );
if (singleton != null) {
return singleton;
}
// no existing singleton, create a new one
singletonFuture = new FutureTask<T>(new CreateInstance());
this.singletonFuture = singletonFuture;
}
// do not call CreateInstance.get() inside of a synchronized block because createInstance results in
// several callbacks to user code which could result in a dead lock
if ( singletonFuture != null )
{
singletonFuture.run();
}
// try to get the future instance
try
{
return singletonFuture.get();
}
catch ( Exception e )
{
// creation failed... clear future reference
synchronized ( this )
{
// only clear if still refering to this method's future
if ( this.singletonFuture == singletonFuture )
{
this.singletonFuture = null;
}
}
// future.get() normally throws an execution execption which contains the real cause
Throwable cause = e;
if ( e instanceof ExecutionException && e.getCause() != null )
{
cause = e.getCause();
}
// rethrow ComponentInstantiationException
if ( cause instanceof ComponentInstantiationException )
{
throw (ComponentInstantiationException) cause;
}
// rethrow ComponentLifecycleException
if ( cause instanceof ComponentLifecycleException )
{
throw (ComponentLifecycleException) cause;
}
// nothing else was expected
throw new ComponentLifecycleException( "Unexpected error obtaining singleton instance", cause );
}
}