org.apache.cxf.configuration.spring.AbstractSpringBeanMap Maven / Gradle / Ivy
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache 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.apache.org/licenses/LICENSE-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.apache.cxf.configuration.spring;
import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import org.apache.cxf.helpers.CastUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
abstract class AbstractSpringBeanMap
implements ApplicationContextAware, InitializingBean, MapProvider, Serializable {
private static final long serialVersionUID = -6825008027450218536L;
protected ApplicationContext context;
protected Class> type;
protected String idsProperty;
protected String staticFieldName;
protected ConcurrentHashMap> idToBeanName = new ConcurrentHashMap>();
protected ConcurrentHashMap putStore = new ConcurrentHashMap(4, 0.75f, 4);
public void setApplicationContext(ApplicationContext ctx) throws BeansException {
this.context = ctx;
}
public void afterPropertiesSet() throws Exception {
processBeans(context);
}
public Map createMap() {
return new SpringBeanMapWrapper();
}
protected abstract void processBeans(ApplicationContext beanFactory);
protected List getBeanListForId(X id) {
List lst = new CopyOnWriteArrayList();
List tmpLst = idToBeanName.putIfAbsent(id, lst);
if (tmpLst != null) {
lst = tmpLst;
}
return lst;
}
protected Collection getIds(Object bean) {
try {
PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(bean.getClass(), idsProperty);
Method method = pd.getReadMethod();
Object o = method.invoke(bean, new Object[0]);
if (o instanceof Collection) {
return CastUtils.cast((Collection>)method.invoke(bean, new Object[0]));
}
@SuppressWarnings("unchecked")
X ar[] = (X[])o;
return Arrays.asList(ar);
} catch (IllegalArgumentException e) {
throw new BeanInitializationException("Could not retrieve ids.", e);
} catch (IllegalAccessException e) {
throw new BeanInitializationException("Could not access id getter.", e);
} catch (InvocationTargetException e) {
throw new BeanInitializationException("Could not invoke id getter.", e);
} catch (SecurityException e) {
throw new BeanInitializationException("Could not invoke id getter.", e);
}
}
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
public Class> getType() {
return type;
}
public void setType(Class> type) {
this.type = type;
}
public String getIdsProperty() {
return idsProperty;
}
public void setIdsProperty(String idsProperty) {
this.idsProperty = idsProperty;
}
public String getStaticFieldName() {
return staticFieldName;
}
public void setStaticFieldName(String staticFieldName) {
this.staticFieldName = staticFieldName;
}
public void clear() {
throw new UnsupportedOperationException();
}
public boolean containsKey(Object key) {
return idToBeanName.containsKey(key) || putStore.containsKey(key);
}
public boolean containsValue(Object arg0) {
throw new UnsupportedOperationException();
}
public Set> entrySet() {
Set> entries = new LinkedHashSet>();
for (X k : keySet()) {
entries.add(new Entry(this, k));
}
return entries;
}
@SuppressWarnings("unchecked")
public V get(Object key) {
List names = idToBeanName.get(key);
if (names != null) {
for (String name : names) {
context.getBean(name);
}
V v = (V)context.getBean(names.get(0));
V tmpV = putStore.putIfAbsent((X)key, v);
if (tmpV != null) {
v = tmpV;
}
idToBeanName.remove(key);
return v;
} else {
return putStore.get(key);
}
}
public boolean isEmpty() {
return idToBeanName.isEmpty() && putStore.isEmpty();
}
public Set keySet() {
Set keys = new LinkedHashSet();
keys.addAll(putStore.keySet());
keys.addAll(idToBeanName.keySet());
return keys;
}
public V put(X key, V value) {
// Make sure we don't take the key from Spring any more
idToBeanName.remove(key);
return putStore.put(key, value);
}
public void putAll(Map extends X, ? extends V> m) {
putStore.putAll(m);
}
public V remove(Object key) {
V v = get(key);
if (v != null) {
idToBeanName.remove(key);
} else {
v = putStore.get(key);
}
return v;
}
public int size() {
return idToBeanName.size() + putStore.size();
}
public Collection values() {
List values = new ArrayList();
values.addAll(putStore.values());
for (X id : idToBeanName.keySet()) {
values.add(get(id));
}
return values;
}
public static class Entry implements Map.Entry {
private AbstractSpringBeanMap map;
private X key;
public Entry(AbstractSpringBeanMap map, X key) {
this.map = map;
this.key = key;
}
public X getKey() {
return key;
}
public V getValue() {
return map.get(key);
}
public V setValue(V value) {
return map.put(key, value);
}
}
private class SpringBeanMapWrapper extends ConcurrentHashMap {
private static final long serialVersionUID = -8693455914470226111L;
public void clear() {
AbstractSpringBeanMap.this.clear();
}
public boolean containsKey(Object key) {
return AbstractSpringBeanMap.this.containsKey(key);
}
public boolean containsValue(Object value) {
return AbstractSpringBeanMap.this.containsValue(value);
}
public Set> entrySet() {
return AbstractSpringBeanMap.this.entrySet();
}
public V get(Object key) {
return AbstractSpringBeanMap.this.get(key);
}
public boolean isEmpty() {
return AbstractSpringBeanMap.this.isEmpty();
}
public Set keySet() {
return AbstractSpringBeanMap.this.keySet();
}
public V put(X key, V value) {
return AbstractSpringBeanMap.this.put(key, value);
}
public void putAll(Map extends X, ? extends V> t) {
AbstractSpringBeanMap.this.putAll(t);
}
public V remove(Object key) {
return AbstractSpringBeanMap.this.remove(key);
}
public int size() {
return AbstractSpringBeanMap.this.size();
}
public Collection values() {
return AbstractSpringBeanMap.this.values();
}
}
}