/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, version 2 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl-2.0.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
*
* Copyright 2006 - 2013 Pentaho Corporation. All rights reserved.
*/
package org.pentaho.platform.engine.core.system.objfac.spring;
import org.pentaho.platform.api.engine.IPentahoObjectReference;
import org.pentaho.platform.api.engine.IPentahoObjectRegistration;
import org.pentaho.platform.engine.core.system.PentahoSystem;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.event.ContextClosedEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
/**
* A Registry for published Spring beans. Also allows for looking up the names of all beans registered for a given type
* in the given Spring bean factory
* <p/>
* User: nbaker Date: 3/27/13
*/
public class PublishedBeanRegistry {
private static Map<Object, Map<Class<?>, List<String>>> classToBeanMap = Collections
.synchronizedMap( new WeakHashMap<Object, Map<Class<?>, List<String>>>() );
private static Map<ListableBeanFactory, Object> factoryMarkerCache = Collections
.synchronizedMap( new WeakHashMap<ListableBeanFactory, Object>() );
private static Map<ListableBeanFactory, List<IPentahoObjectRegistration>> handleRegistry =
Collections.synchronizedMap( new WeakHashMap<ListableBeanFactory, List<IPentahoObjectRegistration>>() );
/**
* Register a bean for the given class. The factoryMarker is a UUID associated with the originating BeanFactory
*
* @param beanName
* @param clazz
* @param factoryMarker
*/
public static void registerBean( String beanName, Class<?> clazz, Object factoryMarker ) {
if ( beanName == null ) {
throw new IllegalArgumentException( "Bean name cannot be null" );
}
if ( clazz == null ) {
throw new IllegalArgumentException( "Class cannot be null" );
}
if ( factoryMarker == null ) {
throw new IllegalArgumentException( "factoryMarker cannot be null" );
}
Map<Class<?>, List<String>> registryMap = classToBeanMap.get( factoryMarker );
if ( registryMap == null ) {
registryMap = new WeakHashMap<Class<?>, List<String>>();
classToBeanMap.put( factoryMarker, registryMap );
}
List<String> beansImplementingType = registryMap.get( clazz );
if ( beansImplementingType == null ) {
beansImplementingType = Collections.synchronizedList( new ArrayList<String>() );
registryMap.put( clazz, beansImplementingType );
}
beansImplementingType.add( beanName );
}
public static void registerFactory( ApplicationContext applicationContext ) {
Object markerBean = null;
try {
// The marker may not be present if there are no published beans from this factory.
markerBean = applicationContext.getBean( Const.FACTORY_MARKER );
} catch ( NoSuchBeanDefinitionException ignored ) {
// ignore
}
if ( markerBean == null ) {
// The applicationContext has been declared to be registered, but no beans are actually published. Ignoring this
// applicationContext
return;
}
factoryMarkerCache.put( applicationContext, markerBean );
final ConfigurableApplicationContext listableBeanFactory =
(ConfigurableApplicationContext) applicationContext;
List<IPentahoObjectRegistration> registrationList = new ArrayList<>();
handleRegistry.put( listableBeanFactory, registrationList );
Map<Class<?>, List<String>> classListMap = classToBeanMap.get( markerBean );
for ( Map.Entry<Class<?>, List<String>> classListEntry : classListMap.entrySet() ) {
Class<?> clazz = classListEntry.getKey();
for ( String beanName : classListEntry.getValue() ) {
IPentahoObjectRegistration iPentahoObjectRegistration = PentahoSystem.registerReference(
new SpringPentahoObjectReference( listableBeanFactory, beanName, clazz, null,
listableBeanFactory.getBeanFactory().getBeanDefinition( beanName ) ) );
registrationList.add( iPentahoObjectRegistration );
}
}
listableBeanFactory.addApplicationListener( new ApplicationListener() {
@Override public void onApplicationEvent( ApplicationEvent applicationEvent ) {
if ( applicationEvent instanceof ContextClosedEvent ) {
for ( IPentahoObjectRegistration iPentahoObjectRegistration : handleRegistry.get( listableBeanFactory ) ) {
iPentahoObjectRegistration.remove();
}
}
}
} );
}
/**
* Return the list of registered BeanFactories
*
* @return list of factories
*/
public static Set<ListableBeanFactory> getRegisteredFactories() {
return factoryMarkerCache.keySet();
}
public static void reset() {
factoryMarkerCache.clear();
}
}