Created
July 17, 2014 12:08
-
-
Save wendal/e1ada7128222670852ee to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.nutz.ioc.impl; | |
import java.io.File; | |
/** | |
* 代理Properties文件,以便直接在Ioc配置文件中使用 | |
* | |
* @author wendal(wendal1985@gmail.com) | |
* @author zozoh(zozohtnt@gmail.com) | |
* | |
* @since 1.b.37 | |
*/ | |
public class PropertiesProxy { | |
private static final Log log = Logs.get(); | |
// 是否为UTF8格式的Properties文件 | |
private final boolean utf8; | |
// 是否忽略无法加载的文件 | |
private boolean ignoreResourceNotFound = false; | |
private MultiLineProperties mp = new MultiLineProperties(); | |
public PropertiesProxy() { | |
this(true); | |
} | |
public PropertiesProxy(boolean utf8) { | |
this.utf8 = utf8; | |
} | |
public PropertiesProxy(String... paths) { | |
this(true); | |
this.setPaths(paths); | |
} | |
public PropertiesProxy(InputStream in) { | |
this(true); | |
try { | |
mp = new MultiLineProperties(); | |
mp.load(new InputStreamReader(in)); | |
} | |
catch (IOException e) { | |
throw Lang.wrapThrow(e); | |
} | |
} | |
/** | |
* @param r | |
* 文本输入流 | |
* @since 1.b.50 | |
*/ | |
public PropertiesProxy(Reader r) { | |
this(true); | |
try { | |
mp = new MultiLineProperties(); | |
mp.load(r); | |
} | |
catch (IOException e) { | |
throw Lang.wrapThrow(e); | |
} | |
} | |
/** | |
* 加载指定文件/文件夹的Properties文件,合并成一个Properties对象 | |
* <p> | |
* <b style=color:red>如果有重复的key,请务必注意加载的顺序!!<b/> | |
* | |
* @param paths | |
* 需要加载的Properties文件路径 | |
*/ | |
public void setPaths(String... paths) { | |
mp = new MultiLineProperties(); | |
try { | |
List<NutResource> list = getResources(paths); | |
if (utf8) | |
for (NutResource nr : list) { | |
Reader r = nr.getReader(); | |
try { | |
mp.load(nr.getReader(), false); | |
} finally { | |
Streams.safeClose(r); | |
} | |
} | |
else { | |
Properties p = new Properties(); | |
for (NutResource nr : list) { | |
InputStream in = nr.getInputStream(); | |
try { | |
p.load(nr.getInputStream()); | |
} finally { | |
Streams.safeClose(in); | |
} | |
} | |
mp.putAll(p); | |
} | |
} | |
catch (IOException e) { | |
throw Lang.wrapThrow(e); | |
} | |
} | |
/** | |
* 加载指定文件/文件夹的Properties文件 | |
* | |
* @param paths | |
* 需要加载的Properties文件路径 | |
* @return 加载到的Properties文件Resource列表 | |
*/ | |
private List<NutResource> getResources(String... paths) { | |
List<NutResource> list = new ArrayList<NutResource>(); | |
for (String path : paths) { | |
try { | |
List<NutResource> resources = Scans.me().loadResource("^.+[.]properties$", path); | |
list.addAll(resources); | |
} | |
catch (Exception e) { | |
if (ignoreResourceNotFound) { | |
if (log.isWarnEnabled()) { | |
log.warn("Could not load resource from " + path + ": " + e.getMessage()); | |
} | |
} else { | |
throw Lang.wrapThrow(e); | |
} | |
} | |
} | |
return list; | |
} | |
public void setIgnoreResourceNotFound(boolean ignoreResourceNotFound) { | |
this.ignoreResourceNotFound = ignoreResourceNotFound; | |
} | |
/** | |
* @param key | |
* 键 | |
* @return 是否包括这个键 | |
* @since 1.b.50 | |
*/ | |
public boolean has(String key) { | |
return mp.containsKey(key); | |
} | |
public void put(String key, String value) { | |
mp.put(key, value); | |
} | |
public PropertiesProxy set(String key, String val) { | |
put(key, val); | |
return this; | |
} | |
public String check(String key) { | |
String val = get(key); | |
if (null == val) | |
throw Lang.makeThrow("Ioc.$conf expect property '%s'", key); | |
return val; | |
} | |
public boolean getBoolean(String key) { | |
return getBoolean(key, false); | |
} | |
public boolean getBoolean(String key, boolean dfval) { | |
String val = get(key); | |
if (Strings.isBlank(val)) | |
return dfval; | |
return Castors.me().castTo(val, Boolean.class); | |
} | |
public String get(String key) { | |
return mp.get(key); | |
} | |
public String get(String key, String defaultValue) { | |
return Strings.sNull(mp.get(key), defaultValue); | |
} | |
public String trim(String key) { | |
return Strings.trim(get(key)); | |
} | |
public String trim(String key, String defaultValue) { | |
return Strings.trim(get(key, defaultValue)); | |
} | |
public int getInt(String key) { | |
return getInt(key, -1); | |
} | |
public int getInt(String key, int defaultValue) { | |
try { | |
return Integer.parseInt(get(key)); | |
} | |
catch (NumberFormatException e) { | |
return defaultValue; | |
} | |
} | |
public long getLong(String key) { | |
return getLong(key, -1); | |
} | |
public long getLong(String key, long dfval) { | |
try { | |
return Long.parseLong(get(key)); | |
} | |
catch (NumberFormatException e) { | |
return dfval; | |
} | |
} | |
public String getTrim(String key) { | |
return Strings.trim(get(key)); | |
} | |
public String getTrim(String key, String defaultValue) { | |
return Strings.trim(get(key, defaultValue)); | |
} | |
public List<String> getKeys() { | |
return mp.keys(); | |
} | |
public Collection<String> getValues() { | |
return mp.values(); | |
} | |
public Properties toProperties() { | |
Properties p = new Properties(); | |
for (String key : mp.keySet()) { | |
p.put(key, mp.get(key)); | |
} | |
return p; | |
} | |
/** | |
* 根据自身的一个键对应的值扩展自身的属性。 | |
* <p> | |
* 本函数假设你可能有下面的键值: | |
* | |
* <pre> | |
* ... | |
* files: | |
* path/to_a.properties | |
* path/to_b.properties | |
* #End files | |
* </pre> | |
* | |
* 那么如果你调用 <code>joinByKey("files");</code> <br> | |
* 则会将其值的两个属性文件展开,加入到自身。 | |
* <p> | |
* 属性文件的路径可以是磁盘全路径,或者在 CLASSPATH 里的路径 | |
* | |
* @param key | |
* 键 | |
* @return 自身 | |
*/ | |
public PropertiesProxy joinByKey(String key) { | |
String str = get(key); | |
final PropertiesProxy me = this; | |
if (!Strings.isBlank(str)) { | |
String[] ss = Strings.splitIgnoreBlank(str, "\n"); | |
for (String s : ss) { | |
File f = Files.findFile(s); | |
if (null == f) { | |
throw Lang.makeThrow("Fail to found path '%s' in CLASSPATH or File System!", s); | |
} | |
// 如果是一个包,引用全部 Files | |
if (f.isDirectory()) { | |
Disks.visitFile(f, new FileVisitor() { | |
public void visit(File f) { | |
me.joinAndClose(Streams.fileInr(f)); | |
} | |
}, new FileFilter() { | |
public boolean accept(File f) { | |
if (f.isDirectory()) | |
return !f.isHidden() && !f.getName().startsWith("."); | |
return f.getName().endsWith(".properties"); | |
} | |
}); | |
} | |
// 否则引用单个文件 | |
else if (f.isFile()) { | |
this.joinAndClose(Streams.fileInr(f)); | |
} | |
} | |
} | |
return this; | |
} | |
/** | |
* 将另外一个 Properties 文本加入本散列表 | |
* | |
* @param r | |
* 文本输入流 | |
* @return 自身 | |
*/ | |
public PropertiesProxy joinAndClose(Reader r) { | |
MultiLineProperties mp = new MultiLineProperties(); | |
try { | |
mp.load(r); | |
} | |
catch (IOException e) { | |
throw Lang.wrapThrow(e); | |
} | |
finally { | |
Streams.safeClose(r); | |
} | |
this.mp.putAll(mp); | |
return this; | |
} | |
public Map<String, String> toMap() { | |
return new HashMap<String, String>(mp); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment