/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library 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 Lesser General Public License for more
* details.
*/
package com.liferay.portal.spring.bean;
import com.liferay.portal.kernel.bean.PortalBeanLocatorUtil;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
/**
* @author Shuyang Zhou
*/
public class BeanReferenceRefreshUtil {
public static void refresh(BeanFactory beanFactory) throws Exception {
BeanRegistrations beanRegistrations = _registeredRefreshPoints.remove(
beanFactory);
if (beanRegistrations == null) {
return;
}
beanRegistrations.refresh();
}
public static void registerRefreshPoint(
BeanFactory beanFactory, Object targetBean, Field field,
String referencedBeanName) {
BeanRegistrations beanRegistrations = _registeredRefreshPoints.get(
beanFactory);
if (beanRegistrations == null) {
beanRegistrations = new BeanRegistrations(beanFactory);
_registeredRefreshPoints.put(beanFactory, beanRegistrations);
}
beanRegistrations.addRefreshPoint(
targetBean, field, referencedBeanName);
}
public interface PACL {
public Object getNewReferencedBean(
String referencedBeanName, BeanFactory beanFactory);
}
private static final Log _log = LogFactoryUtil.getLog(
BeanReferenceRefreshUtil.class);
private static final PACL _pacl = new NoPACL();
private static final Map<BeanFactory, BeanRegistrations>
_registeredRefreshPoints = new IdentityHashMap<>();
private static class BeanRegistrations {
public BeanRegistrations(BeanFactory beanFactory) {
_beanFactory = beanFactory;
}
public void addRefreshPoint(
Object bean, Field field, String referencedBeanName) {
List<RefreshPoint> refreshPoints = _beansToRefresh.get(bean);
if (refreshPoints == null) {
refreshPoints = new ArrayList<>();
_beansToRefresh.put(bean, refreshPoints);
}
refreshPoints.add(new RefreshPoint(field, referencedBeanName));
}
public void refresh() throws Exception {
for (Map.Entry<Object, List<RefreshPoint>> entry :
_beansToRefresh.entrySet()) {
_refresh(entry.getKey(), entry.getValue());
}
}
private void _refresh(
Object targetBean, List<RefreshPoint> refreshPoints)
throws Exception {
for (RefreshPoint refreshPoint : refreshPoints) {
_refresh(targetBean, refreshPoint);
}
}
private void _refresh(Object targetBean, RefreshPoint refreshPoint)
throws Exception {
Field field = refreshPoint._field;
Object oldReferenceBean = field.get(targetBean);
String referencedBeanName = refreshPoint._referencedBeanName;
Object newReferencedBean = _pacl.getNewReferencedBean(
referencedBeanName, _beanFactory);
if (oldReferenceBean == newReferencedBean) {
return;
}
field.set(targetBean, newReferencedBean);
if (_log.isDebugEnabled()) {
_log.debug(
"Refreshed field " + field + " with old value " +
oldReferenceBean + " with new value " +
newReferencedBean + " on bean " + targetBean);
}
}
private final BeanFactory _beanFactory;
private final Map<Object, List<RefreshPoint>> _beansToRefresh =
new IdentityHashMap<>();
}
private static class NoPACL implements PACL {
@Override
public Object getNewReferencedBean(
String referencedBeanName, BeanFactory beanFactory) {
try {
return beanFactory.getBean(referencedBeanName);
}
catch (NoSuchBeanDefinitionException nsbde) {
if (_log.isInfoEnabled()) {
_log.info(
"Bean " + referencedBeanName + " may be defined in " +
"the portal");
}
return PortalBeanLocatorUtil.locate(referencedBeanName);
}
}
}
private static class RefreshPoint {
public RefreshPoint(Field field, String referencedBeanName) {
_field = field;
_referencedBeanName = referencedBeanName;
}
private final Field _field;
private final String _referencedBeanName;
}
}