/******************************************************************************* * 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 java.util.HashSet; import java.util.List; import java.util.Set; import com.google.inject.ProvisionException; import com.google.inject.TypeLiteral; import com.google.inject.spi.TypeEncounter; import com.google.inject.spi.TypeListener; /** * {@link TypeListener} that listens for bean types and arranges for their properties to be injected. */ public final class BeanListener implements TypeListener { // ---------------------------------------------------------------------- // Implementation fields // ---------------------------------------------------------------------- private final BeanBinder beanBinder; // ---------------------------------------------------------------------- // Constructors // ---------------------------------------------------------------------- public BeanListener( final BeanBinder beanBinder ) { this.beanBinder = beanBinder; } // ---------------------------------------------------------------------- // Public methods // ---------------------------------------------------------------------- public <B> void hear( final TypeLiteral<B> type, final TypeEncounter<B> encounter ) { final PropertyBinder propertyBinder = beanBinder.bindBean( type, encounter ); if ( null == propertyBinder ) { return; // no properties to bind } final List<PropertyBinding> bindings = new ArrayList<PropertyBinding>(); final Set<String> visited = new HashSet<String>(); for ( final BeanProperty<?> property : new BeanProperties( type.getRawType() ) ) { if ( property.getAnnotation( javax.inject.Inject.class ) != null || property.getAnnotation( com.google.inject.Inject.class ) != null ) { continue; // these properties will have already been injected by Guice } final String name = property.getName(); if ( visited.add( name ) ) { try { final PropertyBinding binding = propertyBinder.bindProperty( property ); if ( binding == PropertyBinder.LAST_BINDING ) { break; // no more bindings } if ( binding != null ) { bindings.add( binding ); } else { visited.remove( name ); } } catch ( final RuntimeException e ) { encounter.addError( new ProvisionException( "Error binding: " + property, e ) ); } } } if ( bindings.size() > 0 ) { encounter.register( new BeanInjector<B>( bindings ) ); } } }