/**
* $Id: BeanCollectorAutoRegistrar.java 105077 2012-02-24 22:54:29Z ottenhoff@longsight.com $
* $URL: https://source.sakaiproject.org/svn/entitybroker/trunk/utils/src/java/org/sakaiproject/entitybroker/util/spring/BeanCollectorAutoRegistrar.java $
* BeanCollectorAutoRegistrar.java - entity-broker - Apr 15, 2008 4:29:18 PM - azeckoski
**************************************************************************
* Copyright (c) 2007, 2008, 2009 The Sakai Foundation
*
* Licensed under the Educational Community License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.opensource.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sakaiproject.entitybroker.util.spring;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.entitybroker.collector.AutoRegister;
import org.sakaiproject.entitybroker.collector.BeanCollector;
import org.sakaiproject.entitybroker.collector.OrderedBean;
import org.sakaiproject.entitybroker.collector.BeanMapCollector;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
/**
* This will collect the autoregistered beans and place them into all the locations which requested them
*
* @author Aaron Zeckoski (aaron@caret.cam.ac.uk)
*/
public class BeanCollectorAutoRegistrar implements ApplicationListener, ApplicationContextAware, InitializingBean {
private static Log log = LogFactory.getLog(BeanCollectorAutoRegistrar.class);
private ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
public void onApplicationEvent(ApplicationEvent event) {
// We do not actually respond to any events, purpose is to time initialisation only.
}
private Set<String> autoRegistered;
public void init() {
String[] autobeans = applicationContext.getBeanNamesForType(AutoRegister.class, false, false);
autoRegistered = new HashSet<String>();
for (int i = 0; i < autobeans.length; i++) {
autoRegistered.add(autobeans[i]);
}
}
public void afterPropertiesSet() throws Exception {
log.debug("setAC: " + applicationContext.getDisplayName());
ConfigurableApplicationContext cac = (ConfigurableApplicationContext) applicationContext;
ConfigurableBeanFactory cbf = (ConfigurableBeanFactory) cac.getBeanFactory();
cbf.addBeanPostProcessor(new BeanPostProcessor() {
@SuppressWarnings("unchecked")
public Object postProcessBeforeInitialization(Object bean, String beanName) {
if (bean instanceof BeanCollector<?>) {
BeanCollector<Object> bc = (BeanCollector<Object>) bean;
Class<?> c = bc.getCollectedType();
if (c == null) {
throw new IllegalArgumentException("collected type cannot be null");
}
List<Object> l = getAutoRegisteredBeansOfType(c);
logCollectedBeanInsertion(beanName, c.getName(), l);
bc.setCollectedBeans(l);
} else if (bean instanceof BeanMapCollector) {
BeanMapCollector bc = (BeanMapCollector) bean;
Class<?>[] cArray = bc.getCollectedTypes();
if (cArray == null) {
throw new IllegalArgumentException("collected types cannot be null");
}
Map<Class<?>, List<?>> collectedBeans = new HashMap<Class<?>, List<?>>();
for (int i = 0; i < cArray.length; i++) {
List<Object> l = getAutoRegisteredBeansOfType(cArray[i]);
logCollectedBeanInsertion(beanName, cArray[i].getName(), l);
collectedBeans.put(cArray[i], l);
}
bc.setCollectedBeansMap(collectedBeans);
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
});
}
/**
* Get all autoregistered beans of a specific type
* @param c the class type
* @return a list of the matching beans
*/
private List<Object> getAutoRegisteredBeansOfType(Class<?> c) {
String[] autobeans = applicationContext.getBeanNamesForType(c, false, false);
List<Object> l = new ArrayList<Object>();
for (String autobean : autobeans) {
if (autoRegistered.contains(autobean)) {
Object bean = applicationContext.getBean(autobean);
l.add(bean);
}
}
Collections.sort(l, new OrderComparator());
return l;
}
/**
* Generate a log message about the collected insertion
* @param beanName the name of the bean getting collected beans inserted into it
* @param l the list of beans that were inserted
*/
private void logCollectedBeanInsertion(String beanName, String beanType, List<Object> l) {
StringBuilder registeredBeans = new StringBuilder();
registeredBeans.append("[");
for (int i = 0; i < l.size(); i++) {
if (i > 0) {
registeredBeans.append(",");
}
registeredBeans.append(l.get(i).getClass().getName());
}
registeredBeans.append("]");
log.info("Set collected beans of type ("+beanType+") on bean ("+beanName+") to ("+l.size()+") " + registeredBeans.toString());
}
/**
* Comparator to order the collected beans based on order or use default order otherwise
*
* @author Aaron Zeckoski (aaron@caret.cam.ac.uk)
*/
public static class OrderComparator implements Comparator<Object>, Serializable {
public final static long serialVersionUID = 1l;
public int compare(Object arg0, Object arg1) {
if (arg0 instanceof OrderedBean &&
arg1 instanceof OrderedBean) {
return ((OrderedBean)arg0).getOrder() - ((OrderedBean)arg1).getOrder();
} else if (arg0 instanceof OrderedBean) {
return -1;
} else if (arg1 instanceof OrderedBean) {
return 1;
} else {
return 0;
}
}
}
}