package com.meidusa.amoeba.context;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.log4j.Logger;
import org.apache.log4j.helpers.LogLog;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import com.meidusa.amoeba.config.BeanObjectEntityConfig;
import com.meidusa.amoeba.config.ConfigurationException;
import com.meidusa.amoeba.config.DBServerConfig;
import com.meidusa.amoeba.config.DocumentUtil;
import com.meidusa.amoeba.config.ParameterMapping;
import com.meidusa.amoeba.util.StringUtil;
public class DBServerConfigFileLoader implements DBServerConfigLoader {
protected static Logger logger = Logger.getLogger(DBServerConfigFileLoader.class);
private String configFile;
public String getConfigFile() {
return configFile;
}
public void setConfigFile(String configFile) {
this.configFile = configFile;
}
@Override
public Map<String, DBServerConfig> loadConfig() {
DocumentBuilder db;
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setValidating(true);
dbf.setNamespaceAware(false);
db = dbf.newDocumentBuilder();
db.setEntityResolver(new EntityResolver() {
public InputSource resolveEntity(String publicId, String systemId) {
if (systemId.endsWith("dbserver.dtd")) {
InputStream in = ProxyRuntimeContext.class.getResourceAsStream("/com/meidusa/amoeba/xml/dbserver.dtd");
if (in == null) {
LogLog.error("Could not find [dbserver.dtd]. Used [" + ProxyRuntimeContext.class.getClassLoader() + "] class loader in the search.");
return null;
} else {
return new InputSource(in);
}
} else {
return null;
}
}
});
db.setErrorHandler(new ErrorHandler() {
public void warning(SAXParseException exception) {
}
public void error(SAXParseException exception) throws SAXException {
logger.error(exception.getMessage() + " at (" + exception.getLineNumber() + ":" + exception.getColumnNumber() + ")");
throw exception;
}
public void fatalError(SAXParseException exception) throws SAXException {
logger.fatal(exception.getMessage() + " at (" + exception.getLineNumber() + ":" + exception.getColumnNumber() + ")");
throw exception;
}
});
return loadConfigurationFile(db);
} catch (Exception e) {
logger.fatal("Could not load configuration file, failing", e);
throw new ConfigurationException("Error loading configuration file " + configFile, e);
}
}
private Map<String, DBServerConfig> loadConfigurationFile( DocumentBuilder db) {
Document doc = null;
InputStream is = null;
Map<String, DBServerConfig> configMap = new HashMap<String, DBServerConfig>();
try {
is = new FileInputStream(new File(configFile));
if (is == null) {
throw new Exception("Could not open file " + configFile);
}
doc = db.parse(is);
} catch (Exception e) {
final String s = "Caught exception while loading file " + configFile;
logger.error(s, e);
throw new ConfigurationException(s, e);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
logger.error("Unable to close input stream", e);
}
}
}
Element rootElement = doc.getDocumentElement();
final String nodeName = rootElement.getNodeName();
if (nodeName.equals("amoeba:dbServers")) {
loadServers(rootElement,configMap);
}
if (logger.isInfoEnabled()) {
logger.info("Loaded Dbserver configuration from: " + configFile);
}
return configMap;
}
private void loadServers(Element current,Map<String, DBServerConfig> configMap){
NodeList children = current.getChildNodes();
int childSize = children.getLength();
for (int i = 0; i < childSize; i++) {
Node childNode = children.item(i);
if (childNode instanceof Element) {
Element child = (Element) childNode;
DBServerConfig serverConfig = loadServer(child);
if (serverConfig.getVirtual() != null && serverConfig.getVirtual().booleanValue()) {
if (serverConfig.getPoolConfig() != null) {
if (StringUtil.isEmpty(serverConfig.getPoolConfig().getClassName())) {
serverConfig.getPoolConfig().setClassName(getDefaultVirtualPoolClassName());
}
}
} else {
if (serverConfig.getPoolConfig() != null) {
if (StringUtil.isEmpty(serverConfig.getPoolConfig().getClassName())) {
serverConfig.getPoolConfig().setClassName(getDefaultRealPoolClassName());
}
}
}
/*if (serverConfig.getFactoryConfig() != null) {
if (StringUtil.isEmpty(serverConfig.getFactoryConfig().getClassName())) {
throw new ConfigurationException("DBServer Config name=" + serverConfig.getName()+" factory class must not be null!");
}
}*/
configMap.put(serverConfig.getName(), serverConfig);
}
}
}
private DBServerConfig loadServer(Element current) {
DBServerConfig serverConfig = new DBServerConfig();
NamedNodeMap nodeMap = current.getAttributes();
Map<String, Object> map = new HashMap<String, Object>();
for (int i = 0; i < nodeMap.getLength(); i++) {
Node node = nodeMap.item(i);
if (node instanceof org.w3c.dom.Attr) {
Attr attr = (Attr) node;
map.put(attr.getName(), attr.getNodeValue());
}
}
ParameterMapping.mappingObject(serverConfig, map,null);
BeanObjectEntityConfig factory = DocumentUtil.loadBeanConfig(DocumentUtil.getTheOnlyElement(current, "factoryConfig"));
BeanObjectEntityConfig pool = DocumentUtil.loadBeanConfig(DocumentUtil.getTheOnlyElement(current, "poolConfig"));
if (pool != null) {
serverConfig.setPoolConfig(pool);
}
if (factory != null) {
serverConfig.setFactoryConfig(factory);
}
return serverConfig;
}
protected String getDefaultRealPoolClassName() {
return DEFAULT_REAL_POOL_CLASS;
}
protected String getDefaultVirtualPoolClassName() {
return DEFAULT_VIRTUAL_POOL_CLASS;
}
}