package com.easyooo.framework.configure;
import static org.springframework.util.Assert.notEmpty;
import static org.springframework.util.Assert.notNull;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.List;
import java.util.Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.util.StringUtils;
import com.easyooo.framework.common.util.CollectionUtil;
import com.easyooo.framework.configure.BeanCreateInfo;
import com.easyooo.framework.configure.BeanDefinitionFactory;
import com.easyooo.framework.configure.NodeExecutor;
import com.easyooo.framework.configure.OverrideProperties;
import com.easyooo.framework.configure.ResourcePropertiesUtil;
import com.easyooo.framework.configure.UnifiedConfigException;
import com.easyooo.framework.support.zookeeper.ZookeeperExpcetion;
import com.easyooo.framework.support.zookeeper.ZookeeperTemplate;
/**
* 这是一个工厂类构造器,支持标准的单节点、属性配置文件的加载方式,返回一个标准的Spring Bean Defintion
*
* @author Killer
*/
public class FactoryBeanNodeExecutor implements NodeExecutor, InitializingBean {
protected Logger logger = LoggerFactory.getLogger(getClass());
/**
* 该参数设置之后
* 意味着classpath下面有个名为该参数的properties文件
*/
protected String defaultPropertiesShortName;
/** 完整的节点名称 */
protected String znode;
/** 工厂类的BeanId */
protected String factoryBeanId;
/** 工厂类Class */
protected Class<?> factoryClass;
/** 必须的属性名称 */
protected List<String> requiredProerites;
/**
* 解析Node完整流程
*
* @param zookeeperTemplate
* @param source
* @return
* @throws UnifiedConfigException
* @throws IOException
* @throws ZookeeperExpcetion
*/
public List<BeanDefinitionHolder> doExecuteInBox(
ZookeeperTemplate zookeeperTemplate, String source)
throws UnifiedConfigException, IOException, ZookeeperExpcetion {
// default properties
OverrideProperties defaultProperties = getDefaultProperties(defaultPropertiesShortName);
// read zk
byte[] data = zookeeperTemplate.readData(znode);
String propertiesString = new String(data);
Properties p = defaultProperties.overrideProperties(new StringReader(
propertiesString));
checkProperties(p);
// create Bean
return CollectionUtil.gList(createFactoryBeanDefinition(p));
}
/**
* 加载默认配置文件
*
* @see ResourcePropertiesUtil#getPropertiesInputStream(String)
* @param shortName
* 属性文件的名称
* @return
* @throws UnifiedConfigException
*/
protected OverrideProperties getDefaultProperties(String shortName)
throws IOException {
InputStream inputStream = ResourcePropertiesUtil
.getPropertiesInputStream(shortName);
OverrideProperties defaultProperties = new OverrideProperties();
if (inputStream == null) {
logger.warn(String .format("The default %s.properties in the classpath does not exist", shortName));
} else {
defaultProperties.loadDefaultProperties(inputStream);
inputStream.close();
}
return defaultProperties;
}
protected void checkProperties(Properties p) throws UnifiedConfigException {
if (requiredProerites != null && requiredProerites.size() > 0) {
for (String propertyName : requiredProerites) {
if (StringUtils.isEmpty(p.getProperty(propertyName))) {
throw new UnifiedConfigException(String.format(
"property '%s' is a required in the %s znode.",
propertyName, defaultPropertiesShortName));
}
}
}
}
protected BeanDefinitionHolder createFactoryBeanDefinition(
Properties properties) throws UnifiedConfigException {
BeanCreateInfo beanInfo = new BeanCreateInfo(factoryClass,
factoryBeanId, properties, null);
return BeanDefinitionFactory.createBeanDefinition(beanInfo);
}
@Override
public List<BeanDefinitionHolder> doExecute(
ZookeeperTemplate zookeeperTemplate, String source)
throws UnifiedConfigException {
try {
return doExecuteInBox(zookeeperTemplate, source);
} catch (IOException e) {
throw new UnifiedConfigException(e);
} catch (ZookeeperExpcetion e) {
throw new UnifiedConfigException(e);
} catch (UnifiedConfigException uce) {
throw uce;
}
}
public void setDefaultPropertiesShortName(String defaultPropertiesShortName) {
this.defaultPropertiesShortName = defaultPropertiesShortName;
}
public void setZnode(String znode) {
this.znode = znode;
}
public void setFactoryBeanId(String factoryBeanId) {
this.factoryBeanId = factoryBeanId;
}
public void setFactoryClass(Class<?> factoryClass) {
this.factoryClass = factoryClass;
}
public void setRequiredProerites(List<String> requiredProerites) {
this.requiredProerites = requiredProerites;
}
@Override
public void afterPropertiesSet() throws Exception {
notNull(defaultPropertiesShortName, "Property 'defaultPropertiesShortName' is required");
notNull(znode, "Property 'znode' is required");
notNull(factoryBeanId, "Property 'factoryBeanId' is required");
notNull(factoryClass, "Property 'factoryClass' is required");
notEmpty(requiredProerites, "requiredProerites must not be empty: it must contain at least 1 element");
}
}