package jef.database.datasource;
import java.io.IOException;
import java.net.URL;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import jef.common.log.LogUtil;
import jef.common.wrapper.PropertiesMap;
import jef.tools.IOUtils;
import jef.tools.StringUtils;
/**
* DatasourceLookup implementaion of properties
* 会在classpath下的指定资源文件,以及System.properties中查找数据源配置
* @author jiyi
*
*/
public class PropertiesDataSourceInfoLookup implements DataSourceInfoLookup{
private String keyOfPrefix="";
private String keyOfUrl=".url";
private String keyOfUser=".user";
private String keyOfPassword=".password";
private String keyOfDriver=".driver";
private String location;
private boolean needLogonInfo=true;
private PasswordDecryptor passwordDecryptor=PasswordDecryptor.DUMMY;
private String defaultKey;
private Map<String,DataSourceInfo> cache;
public DataSourceInfo getDataSourceInfo(String dataSourceName) {
checkInit();
DataSourceInfo dsi=cache.get(dataSourceName.toUpperCase());
return dsi;
}
private void checkInit() {
if(cache==null){
init(new PropertiesMap(System.getProperties()));
if(StringUtils.isNotEmpty(location!=null)){
try {
Enumeration<URL> resources=this.getClass().getClassLoader().getResources(location);
if(!resources.hasMoreElements()){
LogUtil.error("No properties file [{}] found.",location);
}
for(;resources.hasMoreElements();){
Map<String,String> properties=IOUtils.loadProperties(resources.nextElement());
init(properties);
}
} catch (IOException e) {
LogUtil.exception(e);
}
}
}
}
private synchronized void init(Map<String,String> props) {
Map<String,DataSourceInfo> map;
if(cache==null){
map=new HashMap<String,DataSourceInfo>();
cache=map;
}else{
map=cache;
}
for(Entry<String,String> e: props.entrySet()){
if(e.getKey().endsWith(keyOfUrl) && e.getKey().startsWith(keyOfPrefix)){
int len=e.getKey().length();
String dsName=e.getKey().substring(keyOfPrefix.length(),len-keyOfPrefix.length()-keyOfUrl.length());
DataSourceInfo ds=tryGet(props, dsName);
if(ds!=null){
map.put(dsName.toUpperCase(), ds);
}
}
}
}
private DataSourceInfo tryGet(Map<String,String> p,String dataSourceName) {
String url=p.get(keyOfPrefix+dataSourceName+keyOfUrl);
if(url!=null && url.length()>0){
DataSourceInfoImpl dsi=new DataSourceInfoImpl(url);
dsi.setUser(p.get(keyOfPrefix+dataSourceName+keyOfUser));
String password=p.get(keyOfPrefix+dataSourceName+keyOfPassword);
if(StringUtils.isNotEmpty(password)){
password=passwordDecryptor.decrypt(password);
}
dsi.setPassword(password);
dsi.setDriverClass(p.get(keyOfPrefix+dataSourceName+keyOfDriver));
if(needLogonInfo && StringUtils.isEmpty(dsi.getUser())){
dsi=null;
}
return dsi;
}
return null;
}
/**
* 数据源配置在Properties文件中的前缀,举例<pre>
* jdbc.ds1.url=jdbc:mysql://localhost:3306/test
* jdbc.ds1.user=root
* jdbc.ds1.password=123456
* </pre>
* 在上例中KeyOfPrefix就是 'jdbc.'
* @param keyOfPrefix default value is empty
*/
public void setKeyOfPrefix(String keyOfPrefix) {
this.keyOfPrefix = keyOfPrefix;
}
/**
* 数据源配置在Properties文件中的URL的名称,举例<pre>
* jdbc.ds1.url=jdbc:mysql://localhost:3306/test
* jdbc.ds1.user=root
* jdbc.ds1.password=123456
* </pre>
* 在上例中KeyOfUrl就是 '.url'
* @param keyOfPrefix default valuie is '.url'
*/
public void setKeyOfUrl(String keyOfUrl) {
this.keyOfUrl = keyOfUrl;
}
/**
* 数据源配置在Properties文件中的username的名称,举例<pre>
* jdbc.ds1.url=jdbc:mysql://localhost:3306/test
* jdbc.ds1.user=root
* jdbc.ds1.password=123456
* </pre>
* 在上例中KeyOfUser就是 '.user'
* @param keyOfUser default valuie is '.user'
*/
public void setKeyOfUser(String keyOfUser) {
this.keyOfUser = keyOfUser;
}
/**
* 数据源配置在Properties文件中的username的名称,举例<pre>
* jdbc.ds1.url=jdbc:mysql://localhost:3306/test
* jdbc.ds1.user=root
* jdbc.ds1.password=123456
* </pre>
* 在上例中KeyOfPassword就是 '.password'
* @param keyOfPassword default valuie is '.password'
*/
public void setKeyOfPassword(String keyOfPassword) {
this.keyOfPassword = keyOfPassword;
}
/**
* 数据源配置在Properties文件中的driverClass,举例<pre>
* jdbc.ds1.url=jdbc:mysql://localhost:3306/test
* jdbc.ds1.user=root
* jdbc.ds1.password=123456
* jdbc.ds1.driver=org.gjt.mm.mysql.Driver
* </pre>
* 在上例中KeyOfDriver就是 '.driver'
* @param keyOfDriver default valuie is '.driver'
*/
public void setKeyOfDriver(String keyOfDriver) {
this.keyOfDriver = keyOfDriver;
}
/**
* 设置properties文件路径。不设置的话只会使用System.getProperty();
* 路径不能以/开头,jef会查找所有classpath下的该名称的资源文件来查找数据库配置
* @param localtion
*/
public void setLocation(String localtion) {
this.location = localtion;
}
/**
* 如果没有配置user或者password的数据源就忽略
* @param needLogonInfo
*/
public void setNeedLogonInfo(boolean needLogonInfo) {
this.needLogonInfo = needLogonInfo;
}
public void setPasswordDecryptor(PasswordDecryptor passwordDecryptor) {
this.passwordDecryptor=passwordDecryptor;
}
public String getDefaultKey() {
return defaultKey;
}
public void setDefaultKey(String defaultKey) {
this.defaultKey = defaultKey;
}
public Collection<String> getAvailableKeys() {
checkInit();
return cache.keySet();
}
}