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