Configuration 的属性:
private boolean quietmode = true;//用于设置加载配置的模式,解析配置文件的过程中,不输出日志信息,就这么简单。
private ArrayList<Object> resources = new ArrayList<Object>();
/*
resources 存放的是配置信息对象,可以为url,classpath,path,inputStream,
还可以为xml文件中的一个节点元素(Element),在loadReasource方法中可以清楚的看出。
*/
private Set<String> finalParameters = new HashSet<String>();//标记为final的配置参数列表
private boolean loadDefaults = true;//是否加载默认的配置文件信息
private static final WeakHashMap<Configuration,Object> REGISTRY =
new WeakHashMap<Configuration,Object>();//用于多有个configuration对象的管理,弱哈
//希可以自动清除不在正常使用的键对应的条目
/*
在CopyOnWriteArrayList里处理写操作(包括add、remove、set等)是先将原始的数据通过JDK1.6的Arrays.copyof()来生成一份新的数组
然后在新的数据对象上进行写,写完后再将原来的引用指向到当前这个数据对象(这里应用了常识1),这样保证了每次写都是在新的对象上(因为要保证写的一致性,这里要对各种写操作要加一把锁,JDK1.6在这里用了重入锁),
*/
private static final CopyOnWriteArrayList<String> defaultResources =
new CopyOnWriteArrayList<String>();
//properties类继承自hashtable,将配置文件中的信息以键值对的形式保存下来
private Properties properties;
private Properties overlay;
//overlay为覆盖属性,主要是和properties合并,替换或添加键值对
private ClassLoader classLoader;//类加载器
几个方法:
//从配置文件中获取properties
private synchronized Properties getProps() {
if (properties == null) {
properties = new Properties();
loadResources(properties, resources, quietmode);
if (overlay!= null)//覆盖用的Properties类型
properties.putAll(overlay);
}
return properties;
}
private void loadResources(Properties properties,
ArrayList resources,
boolean quiet) {
if(loadDefaults) {
for (String resource : defaultResources) {
loadResource(properties, resource, quiet);
}
//support the hadoop-site.xml as a deprecated case
if(getResource("hadoop-site.xml")!=null) {
loadResource(properties, "hadoop-site.xml", quiet);
}
}
for (Object resource : resources) {
loadResource(properties, resource, quiet);
}
}
private void loadResource(Properties properties, Object name, boolean quiet) {
try {//处理xml文档
DocumentBuilderFactory docBuilderFactory
= DocumentBuilderFactory.newInstance();
//ignore all comments inside the xml file
docBuilderFactory.setIgnoringComments(true);
//allow includes in the xml file
docBuilderFactory.setNamespaceAware(true);
try {
docBuilderFactory.setXIncludeAware(true);
} catch (UnsupportedOperationException e) {
LOG.error("Failed to set setXIncludeAware(true) for parser "
+ docBuilderFactory
+ ":" + e,
e);
}
DocumentBuilder builder = docBuilderFactory.newDocumentBuilder();
Document doc = null;
Element root = null;
if (name instanceof URL) { // an URL resource
URL url = (URL)name;
if (url != null) {
if (!quiet) {
LOG.info("parsing " + url);
}
doc = builder.parse(url.toString());
}
} else if (name instanceof String) { // a CLASSPATH resource
URL url = getResource((String)name);
if (url != null) {
if (!quiet) {
LOG.info("parsing " + url);
}
doc = builder.parse(url.toString());
}
} else if (name instanceof Path) { // a file resource
// Can't use FileSystem API or we get an infinite loop
// since FileSystem uses Configuration API. Use java.io.File instead.
File file = new File(((Path)name).toUri().getPath())
.getAbsoluteFile();
if (file.exists()) {
if (!quiet) {
LOG.info("parsing " + file);
}
InputStream in = new BufferedInputStream(new FileInputStream(file));
try {
doc = builder.parse(in);
} finally {
in.close();
}
}
} else if (name instanceof InputStream) {//一个输入流
try {
doc = builder.parse((InputStream)name);
} finally {
((InputStream)name).close();
}
} else if (name instanceof Element) {//或者是一个人xml中的一个节点元素
root = (Element)name;
}
if (doc == null && root == null) {
if (quiet)
return;
throw new RuntimeException(name + " not found");
}
if (root == null) {
root = doc.getDocumentElement();//获取根节点
}
if (!"configuration".equals(root.getTagName()))
LOG.fatal("bad conf file: top-level element not <configuration>");
NodeList props = root.getChildNodes();
for (int i = 0; i < props.getLength(); i++) {
Node propNode = props.item(i);
if (!(propNode instanceof Element))
continue;
Element prop = (Element)propNode;
if ("configuration".equals(prop.getTagName())) {
loadResource(properties, prop, quiet);
continue;
}
if (!"property".equals(prop.getTagName()))
LOG.warn("bad conf file: element not <property>");
NodeList fields = prop.getChildNodes();
String attr = null;
String value = null;
boolean finalParameter = false;
for (int j = 0; j < fields.getLength(); j++) {
Node fieldNode = fields.item(j);
if (!(fieldNode instanceof Element))
continue;
Element field = (Element)fieldNode;
if ("name".equals(field.getTagName()) && field.hasChildNodes())
attr = ((Text)field.getFirstChild()).getData().trim();
if ("value".equals(field.getTagName()) && field.hasChildNodes())
value = ((Text)field.getFirstChild()).getData();
if ("final".equals(field.getTagName()) && field.hasChildNodes())
finalParameter = "true".equals(((Text)field.getFirstChild()).getData());
}
// Ignore this parameter if it has already been marked as 'final'
if (attr != null && value != null) {
if (!finalParameters.contains(attr)) {
properties.setProperty(attr, value);
if (finalParameter)
finalParameters.add(attr);
} else {
LOG.warn(name+":a attempt to override final parameter: "+attr
+"; Ignoring.");
}
}
}
} catch (IOException e) {
LOG.fatal("error parsing conf file: " + e);
throw new RuntimeException(e);
} catch (DOMException e) {
LOG.fatal("error parsing conf file: " + e);
throw new RuntimeException(e);
} catch (SAXException e) {
LOG.fatal("error parsing conf file: " + e);
throw new RuntimeException(e);
} catch (ParserConfigurationException e) {
LOG.fatal("error parsing conf file: " + e);
throw new RuntimeException(e);
}
}
以上三个方法从resource中获取配置信息,保存在propertites中
private boolean quietmode = true;//用于设置加载配置的模式,解析配置文件的过程中,不输出日志信息,就这么简单。
private ArrayList<Object> resources = new ArrayList<Object>();
/*
resources 存放的是配置信息对象,可以为url,classpath,path,inputStream,
还可以为xml文件中的一个节点元素(Element),在loadReasource方法中可以清楚的看出。
*/
private Set<String> finalParameters = new HashSet<String>();//标记为final的配置参数列表
private boolean loadDefaults = true;//是否加载默认的配置文件信息
private static final WeakHashMap<Configuration,Object> REGISTRY =
new WeakHashMap<Configuration,Object>();//用于多有个configuration对象的管理,弱哈
//希可以自动清除不在正常使用的键对应的条目
/*
在CopyOnWriteArrayList里处理写操作(包括add、remove、set等)是先将原始的数据通过JDK1.6的Arrays.copyof()来生成一份新的数组
然后在新的数据对象上进行写,写完后再将原来的引用指向到当前这个数据对象(这里应用了常识1),这样保证了每次写都是在新的对象上(因为要保证写的一致性,这里要对各种写操作要加一把锁,JDK1.6在这里用了重入锁),
*/
private static final CopyOnWriteArrayList<String> defaultResources =
new CopyOnWriteArrayList<String>();
//properties类继承自hashtable,将配置文件中的信息以键值对的形式保存下来
private Properties properties;
private Properties overlay;
//overlay为覆盖属性,主要是和properties合并,替换或添加键值对
private ClassLoader classLoader;//类加载器
几个方法:
//从配置文件中获取properties
private synchronized Properties getProps() {
if (properties == null) {
properties = new Properties();
loadResources(properties, resources, quietmode);
if (overlay!= null)//覆盖用的Properties类型
properties.putAll(overlay);
}
return properties;
}
private void loadResources(Properties properties,
ArrayList resources,
boolean quiet) {
if(loadDefaults) {
for (String resource : defaultResources) {
loadResource(properties, resource, quiet);
}
//support the hadoop-site.xml as a deprecated case
if(getResource("hadoop-site.xml")!=null) {
loadResource(properties, "hadoop-site.xml", quiet);
}
}
for (Object resource : resources) {
loadResource(properties, resource, quiet);
}
}
private void loadResource(Properties properties, Object name, boolean quiet) {
try {//处理xml文档
DocumentBuilderFactory docBuilderFactory
= DocumentBuilderFactory.newInstance();
//ignore all comments inside the xml file
docBuilderFactory.setIgnoringComments(true);
//allow includes in the xml file
docBuilderFactory.setNamespaceAware(true);
try {
docBuilderFactory.setXIncludeAware(true);
} catch (UnsupportedOperationException e) {
LOG.error("Failed to set setXIncludeAware(true) for parser "
+ docBuilderFactory
+ ":" + e,
e);
}
DocumentBuilder builder = docBuilderFactory.newDocumentBuilder();
Document doc = null;
Element root = null;
if (name instanceof URL) { // an URL resource
URL url = (URL)name;
if (url != null) {
if (!quiet) {
LOG.info("parsing " + url);
}
doc = builder.parse(url.toString());
}
} else if (name instanceof String) { // a CLASSPATH resource
URL url = getResource((String)name);
if (url != null) {
if (!quiet) {
LOG.info("parsing " + url);
}
doc = builder.parse(url.toString());
}
} else if (name instanceof Path) { // a file resource
// Can't use FileSystem API or we get an infinite loop
// since FileSystem uses Configuration API. Use java.io.File instead.
File file = new File(((Path)name).toUri().getPath())
.getAbsoluteFile();
if (file.exists()) {
if (!quiet) {
LOG.info("parsing " + file);
}
InputStream in = new BufferedInputStream(new FileInputStream(file));
try {
doc = builder.parse(in);
} finally {
in.close();
}
}
} else if (name instanceof InputStream) {//一个输入流
try {
doc = builder.parse((InputStream)name);
} finally {
((InputStream)name).close();
}
} else if (name instanceof Element) {//或者是一个人xml中的一个节点元素
root = (Element)name;
}
if (doc == null && root == null) {
if (quiet)
return;
throw new RuntimeException(name + " not found");
}
if (root == null) {
root = doc.getDocumentElement();//获取根节点
}
if (!"configuration".equals(root.getTagName()))
LOG.fatal("bad conf file: top-level element not <configuration>");
NodeList props = root.getChildNodes();
for (int i = 0; i < props.getLength(); i++) {
Node propNode = props.item(i);
if (!(propNode instanceof Element))
continue;
Element prop = (Element)propNode;
if ("configuration".equals(prop.getTagName())) {
loadResource(properties, prop, quiet);
continue;
}
if (!"property".equals(prop.getTagName()))
LOG.warn("bad conf file: element not <property>");
NodeList fields = prop.getChildNodes();
String attr = null;
String value = null;
boolean finalParameter = false;
for (int j = 0; j < fields.getLength(); j++) {
Node fieldNode = fields.item(j);
if (!(fieldNode instanceof Element))
continue;
Element field = (Element)fieldNode;
if ("name".equals(field.getTagName()) && field.hasChildNodes())
attr = ((Text)field.getFirstChild()).getData().trim();
if ("value".equals(field.getTagName()) && field.hasChildNodes())
value = ((Text)field.getFirstChild()).getData();
if ("final".equals(field.getTagName()) && field.hasChildNodes())
finalParameter = "true".equals(((Text)field.getFirstChild()).getData());
}
// Ignore this parameter if it has already been marked as 'final'
if (attr != null && value != null) {
if (!finalParameters.contains(attr)) {
properties.setProperty(attr, value);
if (finalParameter)
finalParameters.add(attr);
} else {
LOG.warn(name+":a attempt to override final parameter: "+attr
+"; Ignoring.");
}
}
}
} catch (IOException e) {
LOG.fatal("error parsing conf file: " + e);
throw new RuntimeException(e);
} catch (DOMException e) {
LOG.fatal("error parsing conf file: " + e);
throw new RuntimeException(e);
} catch (SAXException e) {
LOG.fatal("error parsing conf file: " + e);
throw new RuntimeException(e);
} catch (ParserConfigurationException e) {
LOG.fatal("error parsing conf file: " + e);
throw new RuntimeException(e);
}
}
以上三个方法从resource中获取配置信息,保存在propertites中