package com.meidusa.amoeba.config.loader;
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.Document;
import org.w3c.dom.Element;
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.ConfigUtil;
import com.meidusa.amoeba.config.ParameterMapping;
import com.meidusa.amoeba.config.ProxyServerConfig;
import com.meidusa.amoeba.config.loader.AmoebaContextLoader;
import com.meidusa.amoeba.config.loader.DBServerConfigLoader;
import com.meidusa.amoeba.config.loader.util.ConfigLoaderUtil;
import com.meidusa.amoeba.context.ProxyRuntimeContext;
import com.meidusa.amoeba.exception.ConfigurationException;
import com.meidusa.amoeba.net.ConnectionManager;
import com.meidusa.amoeba.util.StringUtil;
public class AmoebaContextFileLoader implements AmoebaContextLoader{
protected static Logger logger = Logger.getLogger(AmoebaContextFileLoader.class);
private ProxyRuntimeContext amoebaContext;
public void setAmoebaContext(ProxyRuntimeContext amoebaContext) {
this.amoebaContext = amoebaContext;
}
@Override
public ProxyServerConfig loadConfig() {
String PATH_SEPARATOR = StringUtil.PATH_SEPARATOR;
String config = amoebaContext.getAmoebaHomePath() + PATH_SEPARATOR + "conf" + PATH_SEPARATOR + "amoeba.xml";
config = ConfigUtil.filter(config);
File configFile = new File(config);
if(config == null || !configFile.exists()){
logger.error("could not find config file:"+configFile.getAbsolutePath());
System.exit(-1);
}
return loadConfig(configFile.getAbsolutePath());
}
private ProxyServerConfig loadConfig(String configFileName) {
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("amoeba.dtd")) {
InputStream in =
this.getClass().getResourceAsStream("/com/meidusa/amoeba/xml/amoeba.dtd");
if (in == null) {
LogLog.error("Could not find [amoeba.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(configFileName, db);
} catch (Exception e) {
logger.fatal("Could not load configuration file, failing", e);
throw new ConfigurationException("Error loading configuration file " + configFileName, e);
}
}
private ProxyServerConfig loadConfigurationFile(String fileName, DocumentBuilder db) {
Document doc = null;
InputStream is = null;
ProxyServerConfig config = new ProxyServerConfig();
try {
is = new FileInputStream(new File(fileName));
if (is == null) {
throw new Exception("Could not open file " + fileName);
}
doc = db.parse(is);
} catch (Exception e) {
final String s = "Caught exception while loading file " + fileName;
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();
NodeList children = rootElement.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;
final String nodeName = child.getNodeName();
if (nodeName.equals("proxy")) {
loadProxyConfig(child, config);
} else if (nodeName.equals("connectionManagerList")) {
loadConnectionManagers(child, config);
} else if (nodeName.equals("dbServerLoader")) {
loadDbServerLoader(rootElement, config);
} else if (nodeName.equals("queryRouter")) {
loadQueryRouter(rootElement, config);
} else if (nodeName.equals("userLoader")){
loadUserLoader(rootElement, config);
}
}
}
if (logger.isInfoEnabled()) {
logger.info("Loaded Amoeba Proxy configuration from: " + fileName);
}
return config;
}
private void loadQueryRouter(Element current, ProxyServerConfig config) {
BeanObjectEntityConfig queryRouter =
ConfigLoaderUtil.loadBeanConfig(ConfigLoaderUtil.getTheOnlyElement(current, "queryRouter"));
config.setQueryRouterConfig(queryRouter);
}
private void loadDbServerLoader(Element current, ProxyServerConfig config) {
BeanObjectEntityConfig dbserverLoader =
ConfigLoaderUtil.loadBeanConfig(ConfigLoaderUtil.getTheOnlyElement(current,
"dbServerLoader"));
DBServerConfigLoader loader = (DBServerConfigLoader) dbserverLoader.createBeanObject(true, amoebaContext.getConnectionManagerList());
config.putAllServers(loader.loadConfig());
}
private void loadUserLoader(Element current, ProxyServerConfig config) {
BeanObjectEntityConfig userLoaderConfig = ConfigLoaderUtil.loadBeanConfig(ConfigLoaderUtil.getTheOnlyElement(current, "userLoader"));
userLoaderConfig.createBeanObject(true, null);
}
private void loadConnectionManagers(Element current, ProxyServerConfig config) {
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;
BeanObjectEntityConfig managerConfig = ConfigLoaderUtil.loadBeanConfig(child);
if (StringUtil.isEmpty(managerConfig.getClassName())) {
managerConfig.setClassName(amoebaContext.getDefaultServerConnectionManagerClassName());
}
config.addManager(managerConfig.getName(), managerConfig);
}
}
// create bean and init
for (Map.Entry<String, BeanObjectEntityConfig> entry : config.getManagers().entrySet()) {
BeanObjectEntityConfig beanObjectEntityConfig = entry.getValue();
try {
ConnectionManager manager =
(ConnectionManager) amoebaContext.createBeanObjectEntity(beanObjectEntityConfig, true);
manager.setName(entry.getKey());
amoebaContext.getConnectionManagerList().put(manager.getName(), manager);
} catch (Exception e) {
throw new ConfigurationException("manager instance error", e);
}
}
}
private void loadProxyConfig(Element current, ProxyServerConfig config) {
NodeList children = current.getChildNodes();
int childSize = children.getLength();
Map<String, Object> map = new HashMap<String, Object>();
for (int i = 0; i < childSize; i++) {
Node childNode = children.item(i);
if (childNode instanceof Element) {
Element child = (Element) childNode;
final String nodeName = child.getNodeName();
if (nodeName.equals("property")) {
String key = child.getAttribute("name");
String value = child.getTextContent();
map.put(key, value);
}
else if (nodeName.equals("service")) {
BeanObjectEntityConfig server = ConfigLoaderUtil.loadBeanConfig(child);
config.addServerConfig(server);
}
else if (nodeName.equals("runtime")) {
BeanObjectEntityConfig runtime = ConfigLoaderUtil.loadBeanConfig(child);
config.setRuntimeConfig(runtime);
}
}
}
ParameterMapping.mappingObject(config, map, null);
}
}