
commons.box.util.INIs Maven / Gradle / Ivy
Show all versions of commons-box-app Show documentation
package commons.box.util;
import commons.box.app.AppLog;
import commons.box.app.AppResource;
import org.ini4j.Ini;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Supplier;
/**
* 载入INI配置文件
* 创建作者:xingxiuyi
* 版权所属:xingxiuyi
*/
public final class INIs {
private static final AppLog LOG = Logs.get(INIs.class);
private static final Map> EMPTY_MAP = Maps.immmap(null);
/**
* 返回配置 每节一个map 未分节的配置在默认空字符串为key的map中
*
* @param file INI文件
* @return
*/
public static Map> load(File file) {
return load(new FileIniLoadConsumer(file, null));
}
/**
* 返回配置 每节一个map 未分节的配置在默认空字符串为key的map中
*
* 需要手工关闭流
*
* @param is INI文件流
* @return
*/
public static Map> load(InputStream is) {
return load(new InputStreamIniLoadConsumer(is, null));
}
/**
* 返回配置 每节一个map 未分节的配置在默认空字符串为key的map中
*
* 此方法会自动关闭流
*
* @param sp
* @param onFail
* @return
*/
public static Map> load(Supplier sp, Consumer onFail) {
Map> result = null;
InputStream is = null;
try {
is = sp.get();
if (is != null) result = load(new InputStreamIniLoadConsumer(is, onFail));
} catch (Throwable e) {
LOG.warn("无法读取目标流");
if (onFail != null) onFail.accept(e);
} finally {
IOs.close(is);
}
if (result == null) result = EMPTY_MAP;
return result;
}
/**
* 返回配置 每节一个map 未分节的配置在默认空字符串为key的map中
*
* 此方法会自动关闭流
*
* @param sp
* @return
*/
public static Map> load(Supplier sp) {
return load(sp, null);
}
/**
* 返回配置 每节一个map 未分节的配置在默认空字符串为key的map中
*
* @param url INI文件路径
* @return
*/
public static Map> load(URL url) {
return load(new URLIniLoadConsumer(url, null));
}
/**
* 返回配置 每节一个map 未分节的配置在默认空字符串为key的map中
*
* @param resourcePath 资源路径 支持classpath*:/a/b 样式的通配符 整合多个匹配资源
* @return
*/
public static Map> load(String resourcePath) {
Map> map = new LinkedHashMap<>();
List res = Resources.resources(resourcePath);
for (AppResource r : res) {
Map> m = load(r);
if (m != null) Maps.combin(map, m);
}
return map;
}
/**
* 返回配置 每节一个map 未分节的配置在默认空字符串为key的map中
*
* @param resource
* @return
*/
public static Map> load(AppResource resource) {
if (resource == null) return EMPTY_MAP;
InputStream is = null;
try {
is = resource.stream();
return load(new InputStreamIniLoadConsumer(is, null));
} catch (Throwable e) {
LOG.error("无法读取文件 " + resource, e);
} finally {
if (is != null) IOs.close(is);
}
return null;
}
/**
* 返回配置 每节一个map 未分节的配置在默认空字符串为key的map中
*
* @param content INI文件内容
* @return
*/
public static Map> loadByContent(String content) {
return load(new StringIniLoadConsumer(content, null));
}
/**
* 返回配置 每节一个map 未分节的配置在默认空字符串为key的map中 需实现iniConsumer方法调用ini.load()
*
* @param iniConsumer
* @return
*/
public static Map> load(Consumer iniConsumer) {
if (iniConsumer == null) return EMPTY_MAP;
Map> configs = new LinkedHashMap<>();
try {
Ini ini = new Ini();
iniConsumer.accept(ini);
for (Map.Entry me : ini.entrySet()) {
String mk = me.getKey();
Ini.Section mv = me.getValue();
if (mk == null || mv == null) continue;
Map cv = configs.computeIfAbsent(mk, k -> new LinkedHashMap<>());
for (Map.Entry m : mv.entrySet()) {
if (m.getKey() == null) continue;
cv.put(Strs.toString(m.getKey()), Strs.toString(m.getValue()));
}
}
} catch (Throwable e) {
LOG.warn("载入配置发生错误 " + e.getMessage(), e);
}
return configs;
}
private static final class FileIniLoadConsumer implements Consumer {
private final File file;
private final Consumer failed;
public FileIniLoadConsumer(File file, Consumer failed) {
this.file = file;
this.failed = failed;
}
@Override
public void accept(Ini ini) {
if (ini == null || this.file == null) return;
try {
ini.load(this.file);
} catch (Throwable e) {
LOG.error("载入INI内容发生错误 FILE=" + this.file);
if (this.failed != null) this.failed.accept(e);
}
}
}
private static final class InputStreamIniLoadConsumer implements Consumer {
private final InputStream is;
private final Consumer failed;
public InputStreamIniLoadConsumer(InputStream is, Consumer failed) {
this.is = is;
this.failed = failed;
}
@Override
public void accept(Ini ini) {
if (ini == null || this.is == null) return;
try {
ini.load(this.is);
} catch (Throwable e) {
LOG.error("载入INI内容发生错误 InputStream=" + this.is, e);
if (this.failed != null) this.failed.accept(e);
}
}
}
private static final class StringIniLoadConsumer implements Consumer {
private final String str;
private final Consumer failed;
public StringIniLoadConsumer(String str, Consumer failed) {
this.str = str;
this.failed = failed;
}
@Override
public void accept(Ini ini) {
if (ini == null || Strs.isBlank(this.str)) return;
InputStream is = null;
try {
byte[] bytes = this.str.getBytes(Langs.CHARSET_UTF8);
is = new ByteArrayInputStream(bytes);
ini.load(is);
} catch (Throwable e) {
LOG.error("载入INI内容发生错误 InputStream=" + this.str, e);
if (this.failed != null) this.failed.accept(e);
} finally {
if (is != null) IOs.close(is);
}
}
}
private static final class URLIniLoadConsumer implements Consumer {
private final URL url;
private final Consumer failed;
public URLIniLoadConsumer(URL url, Consumer failed) {
this.url = url;
this.failed = failed;
}
@Override
public void accept(Ini ini) {
if (ini == null || this.url == null) return;
try {
ini.load(this.url);
} catch (Throwable e) {
LOG.error("载入INI内容发生错误 URL=" + this.url, e);
if (this.failed != null) this.failed.accept(e);
}
}
}
}