org.eclipse.sisu.bean.BeanScheduler Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2010-present Sonatype, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Stuart McCulloch (Sonatype, Inc.) - initial API and implementation
*******************************************************************************/
package org.eclipse.sisu.bean;
import java.util.ArrayList;
import com.google.inject.Binder;
import com.google.inject.Module;
import com.google.inject.Scopes;
import com.google.inject.matcher.Matcher;
import com.google.inject.matcher.Matchers;
import com.google.inject.spi.BindingScopingVisitor;
import com.google.inject.spi.DefaultBindingScopingVisitor;
/**
* Schedules safe activation of beans even when cyclic dependencies are involved.
* Takes advantage of the new Guice ProvisionListener SPI, if available at runtime.
*/
public abstract class BeanScheduler
{
// ----------------------------------------------------------------------
// Static initialization
// ----------------------------------------------------------------------
static
{
Object cycleActivator;
Object candidateCycle = new Object();
Object cycleConfirmed = new Object();
try
{
// extra check in case we have both old and new versions of guice overlapping on the runtime classpath
Binder.class.getMethod( "bindListener", Matcher.class, com.google.inject.spi.ProvisionListener[].class );
// allow cycle detection to be turned off completely
final String detectCycles = System.getProperty( "sisu.detect.cycles" );
if ( "false".equalsIgnoreCase( detectCycles ) )
{
cycleActivator = null;
}
else
{
cycleActivator = new CycleActivator();
}
// support use of the old 'pessimistic' approach
if ( "pessimistic".equalsIgnoreCase( detectCycles ) )
{
candidateCycle = cycleConfirmed;
}
}
catch ( final Exception e )
{
cycleActivator = null;
}
catch ( final LinkageError e )
{
cycleActivator = null;
}
CYCLE_ACTIVATOR = cycleActivator;
CANDIDATE_CYCLE = candidateCycle;
CYCLE_CONFIRMED = cycleConfirmed;
}
// ----------------------------------------------------------------------
// Constants
// ----------------------------------------------------------------------
static final Object CYCLE_ACTIVATOR;
static final Object CANDIDATE_CYCLE;
static final Object CYCLE_CONFIRMED;
/**
* Enables deferred activation of component cycles, only needed in legacy systems like Plexus.
*/
public static final Module MODULE = new Module()
{
public void configure( final Binder binder )
{
if ( null != CYCLE_ACTIVATOR )
{
binder.bindListener( Matchers.any(), (com.google.inject.spi.ProvisionListener) CYCLE_ACTIVATOR );
}
}
};
// ----------------------------------------------------------------------
// Implementation fields
// ----------------------------------------------------------------------
static final ThreadLocal