001: package org.osbl.spring;
002:
003: import org.osbl.ServiceProvider;
004: import org.springframework.beans.factory.support.DefaultListableBeanFactory;
005: import org.springframework.beans.factory.support.RootBeanDefinition;
006: import org.springframework.beans.factory.*;
007: import org.springframework.beans.*;
008:
009: import java.util.*;
010: import java.beans.PropertyDescriptor;
011:
012: public class SpringServiceProvider extends ServiceProvider implements
013: BeanFactoryAware {
014: private static Map<Class<? extends Object>, BeanHelper> BEAN_HELPER_CACHE = new HashMap<Class<? extends Object>, BeanHelper>();
015:
016: DefaultListableBeanFactory beanFactory;
017:
018: public SpringServiceProvider() {
019: INSTANCE = this ;
020: }
021:
022: public List<String> getServiceNames() {
023: return Arrays.asList(getBeanFactory().getBeanDefinitionNames());
024: }
025:
026: public Object getService(String name) {
027: return getBeanFactory().getBean(name);
028: }
029:
030: public <T> T getService(Class<T> type) {
031: ListableBeanFactory beanFactory = getBeanFactory();
032: do {
033: String[] names = beanFactory.getBeanNamesForType(type);
034: switch (names.length) {
035: case 0:
036: if (beanFactory instanceof HierarchicalBeanFactory) {
037: HierarchicalBeanFactory hierarchicalBeanFactory = (HierarchicalBeanFactory) beanFactory;
038: beanFactory = (ListableBeanFactory) hierarchicalBeanFactory
039: .getParentBeanFactory();
040: continue;
041: } else
042: beanFactory = null;
043: case 1:
044: return (T) getService(names[0]);
045: default:
046: throw new IllegalArgumentException(
047: "More than one bean of type '" + type
048: + "' found in beanFactory");
049: }
050: } while (beanFactory != null);
051:
052: return null;
053: }
054:
055: public void autowireServices(Object bean) {
056: Class<? extends Object> type = bean.getClass();
057: SpringServiceProvider.BeanHelper helper = getBeanHelper(type);
058: BeanWrapper bw = helper.getBeanWrapper();
059: // prevent multiple thread access
060: synchronized (bw) {
061: bw.setWrappedInstance(bean);
062: populateBean(type.getName(), helper.getBeanDefinition(), bw);
063: }
064: }
065:
066: private SpringServiceProvider.BeanHelper getBeanHelper(
067: Class<? extends Object> type) {
068: SpringServiceProvider.BeanHelper helper = BEAN_HELPER_CACHE
069: .get(type);
070: if (helper == null) {
071: helper = new SpringServiceProvider.BeanHelper(
072: new BeanWrapperImpl(), new RootBeanDefinition(type,
073: false));
074: BEAN_HELPER_CACHE.put(type, helper);
075: }
076: return helper;
077: }
078:
079: private void populateBean(String beanName, RootBeanDefinition bd,
080: BeanWrapper bw) {
081: PropertyValues pvs = bd.getPropertyValues();
082: MutablePropertyValues mpvs = new MutablePropertyValues(pvs);
083: String[] propertyNames = getPropertyNames(bd, bw);
084: for (int i = 0; i < propertyNames.length; i++) {
085: String propertyName = propertyNames[i];
086: Class<?> requiredType = bw.getPropertyDescriptor(
087: propertyName).getPropertyType();
088: Object bean = getService(requiredType);
089: if (bean != null) {
090: PropertyValue propertyValue = new PropertyValue(
091: propertyName, bean);
092: mpvs.addPropertyValue(propertyValue);
093: }
094: }
095: bw.setPropertyValues(mpvs);
096: }
097:
098: private String[] getPropertyNames(
099: RootBeanDefinition mergedBeanDefinition, BeanWrapper bw) {
100: Set<String> result = new TreeSet<String>();
101: PropertyValues pvs = mergedBeanDefinition.getPropertyValues();
102: PropertyDescriptor[] pds = bw.getPropertyDescriptors();
103: for (int i = 0; i < pds.length; i++) {
104: if (pds[i].getWriteMethod() != null
105: && !pvs.contains(pds[i].getName())
106: && !BeanUtils.isSimpleProperty(pds[i]
107: .getPropertyType())) {
108: result.add(pds[i].getName());
109: }
110: }
111: return result.toArray(new String[result.size()]);
112: }
113:
114: public void setBeanFactory(BeanFactory beanFactory)
115: throws BeansException {
116: this .beanFactory = (DefaultListableBeanFactory) beanFactory;
117: }
118:
119: private static class BeanHelper {
120: private BeanWrapper beanWrapper;
121: private RootBeanDefinition beanDefinition;
122:
123: public BeanHelper(BeanWrapper beanWrapper,
124: RootBeanDefinition beanDefinition) {
125: this .beanWrapper = beanWrapper;
126: this .beanDefinition = beanDefinition;
127: }
128:
129: public BeanWrapper getBeanWrapper() {
130: return beanWrapper;
131: }
132:
133: public RootBeanDefinition getBeanDefinition() {
134: return beanDefinition;
135: }
136: }
137:
138: private DefaultListableBeanFactory getBeanFactory() {
139: return beanFactory;
140: }
141: }
|