0.1.0文件分析
类的关系图
Configurable【接口】
public interface Configurable {
void setConf(Configuration conf);
//一个接口函数方法,设置配置对象
Configuration getConf();
//一个接口函数方法,返回配置对象
}
Configured【类】
public class Configured implements Configurable {
private Configuration conf;
//具体的存储对象
public Configured(Configuration conf) {
setConf(conf);
}
//构造函数初始化存储配置对象
public void setConf(Configuration conf) {
this.conf = conf;
}
//实现接口,引用配置对象
public Configuration getConf() {
return conf;
}
//实现接口,返回配置对象
}
Configuration【类】
public class Configuration {
private static final Logger LOG =
LogFormatter.getLogger("org.apache.hadoop.conf.Configuration");
//日志对象
private ArrayList defaultResources = new ArrayList();
//列表对象
private ArrayList finalResources = new ArrayList();
//列表对象
private Properties properties;
//属性k/v对象
private ClassLoader classLoader =
Thread.currentThread().getContextClassLoader();
//类加载对象
public Configuration() {
defaultResources.add("hadoop-default.xml");
finalResources.add("hadoop-site.xml");
//分别在两个集合里分别设置一个配置文件名
//类似于conf/nutch-site.xml
conf/nutch-default.xml
}
public Configuration(Configuration other) {
this.defaultResources = (ArrayList)other.defaultResources.clone();
this.finalResources = (ArrayList)other.finalResources.clone();
if (other.properties != null)
this.properties = (Properties)other.properties.clone();
//基于别的对象复制其配置文件列表及属性集合对象
}
public void addDefaultResource(String name) {
addResource(defaultResources, name);
}//往默认集合列表里添加一个文件名
public void addDefaultResource(File file) {
addResource(defaultResources, file);
}//往默认集合列表里添加一个文件
public void addFinalResource(String name) {
addResource(finalResources, name);
}//往final集合列表里添加一个文件名
public void addFinalResource(File file) {
addResource(finalResources, file);
}//往final集合列表里添加一个文件
private synchronized void addResource(ArrayList resources, Object resource) {
resources.add(resource);
properties = null;
}
//由多个函数调用,参数1的列表添加另外一个对象,并设置properties为null.
public Object getObject(String name) { return getProps().get(name);}
//从属性集合里查找name对应的值
public void setObject(String name, Object value) {
getProps().put(name, value);
}
//将<name,value>设置到属性里
public Object get(String name, Object defaultValue) {
Object res = getObject(name);
if (res != null) return res;
else return defaultValue;
}
//从属性集合里查找,同时提供默认值
public String get(String name)
{ return getProps().getProperty(name);}
//从属性集合里查找对应的value
public void set(String name, Object value) {
getProps().setProperty(name, value.toString());
}
//设置<name,value>到属性中
public String get(String name, String defaultValue) {
return getProps().getProperty(name, defaultValue);
}
//查找对应的值,同时提供默认值
public int getInt(String name, int defaultValue) {
String valueString = get(name);
if (valueString == null)
return defaultValue;
try {
return Integer.parseInt(valueString);
} catch (NumberFormatException e) {
return defaultValue;
}
}
//从属性集合中查找name对应的整数,同时提供默认值
public void setInt(String name, int value) {
set(name, Integer.toString(value));
}
//添加<name,value>入集合
public long getLong(String name, long defaultValue) {
String valueString = get(name);
if (valueString == null)
return defaultValue;
try {
return Long.parseLong(valueString);
} catch (NumberFormatException e) {
return defaultValue;
}
}
//查找name对应的long,提供默认值
public void setLong(String name, long value) {
set(name, Long.toString(value));
}
//同上
public float getFloat(String name, float defaultValue) {
String valueString = get(name);
if (valueString == null)
return defaultValue;
try {
return Float.parseFloat(valueString);
} catch (NumberFormatException e) {
return defaultValue;
}
}
//同上
public boolean getBoolean(String name, boolean defaultValue) {
String valueString = get(name);
if ("true".equals(valueString))
return true;
else if ("false".equals(valueString))
return false;
else return defaultValue;
}
//根据name对应的字符串返回true/false.提供默认值
public void setBoolean(String name, boolean value) {
set(name, Boolean.toString(value));
}
//设置<name,value>入属性集合
public String[] getStrings(String name) {
String valueString = get(name);
if (valueString == null)
return null;
StringTokenizer tokenizer = new StringTokenizer (valueString,", \t\n\r\f");
List values = new ArrayList();
while (tokenizer.hasMoreTokens()) {
values.add(tokenizer.nextToken());
}
return (String[])values.toArray(new String[values.size()]);
}
//根据name对应的值,分词,提取对应的字符串数组
public Class getClass(String name, Class defaultValue) {
String valueString = get(name);
if (valueString == null)
return defaultValue;
try {
return Class.forName(valueString);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
//返回name对应的值对应的类,同时提供默认类值
public Class getClass(String propertyName, Class defaultValue,Class xface) {
try {
Class theClass = getClass(propertyName, defaultValue);
if (theClass != null && !xface.isAssignableFrom(theClass))
throw new RuntimeException(theClass+" not "+xface.getName());
return theClass;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//在提供默认类的前提下,查找propertyName对应的类,同时检测theClass是xface的类/子类,否则报错。
public void setClass(String propertyName, Class theClass, Class xface) {
if (!xface.isAssignableFrom(theClass))
throw new RuntimeException(theClass+" not "+xface.getName());
set(propertyName, theClass.getName());
}
//经过判断后,设置name对应的类
public File getFile(String dirsProp, String path) throws IOException {
String[] dirs = getStrings(dirsProp);
int hashCode = path.hashCode();
for (int i = 0; i < dirs.length; i++) { // try each local dir
int index = (hashCode+i & Integer.MAX_VALUE) % dirs.length;
File file = new File(dirs[index], path).getAbsoluteFile();
File dir = file.getParentFile();
if (dir.exists() || dir.mkdirs()) {
return file;
}
}
throw new IOException("No valid local directories in property: "+dirsProp);
}
//先查找dirsProp对应的字符串数组,根据一定的逻辑,生成一个文件夹并返回对应的文件
public URL getResource(String name) {
return classLoader.getResource(name);
}
//返回name对应的url
public InputStream getConfResourceAsInputStream(String name) {
try {
URL url= getResource(name);
if (url == null) {
LOG.info(name + " not found");
return null;
} else {
LOG.info("found resource " + name + " at " + url);
}
return url.openStream();
} catch (Exception e) {
return null;
}
}
//打开文件的输入流
public Reader getConfResourceAsReader(String name) {
try {
URL url= getResource(name);
if (url == null) {
LOG.info(name + " not found");
return null;
} else {
LOG.info("found resource " + name + " at " + url);
}
return new InputStreamReader(url.openStream());
} catch (Exception e) {
return null;
}
}
//打开对应文件的输入流对象
private synchronized Properties getProps() {
if (properties == null) {
Properties newProps = new Properties();
loadResources(newProps, defaultResources, false, false);
loadResources(newProps, finalResources, true, true);
properties = newProps;
}
return properties;
}
//根据2个列表里的文件或者文件名对应的配置信息构造properties
private void loadResources(Properties props,
ArrayList resources,
boolean reverse, boolean quiet) {
ListIterator i = resources.listIterator(reverse ? resources.size() : 0);
while (reverse ? i.hasPrevious() : i.hasNext()) {
loadResource(props, reverse ? i.previous() : i.next(), quiet);
}
}
//根据参数来从2个方向来分别提取配置信息
private void loadResource(Properties properties, Object name, boolean quiet) {
try {
DocumentBuilder builder =
DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = null;
if (name instanceof String) { // a CLASSPATH resource
URL url = getResource((String)name);
if (url != null) {
LOG.info("parsing " + url);
doc = builder.parse(url.toString());
}
} else if (name instanceof File) { // a file resource
File file = (File)name;
if (file.exists()) {
LOG.info("parsing " + file);
doc = builder.parse(file);
}
}
//获得DOM文档
if (doc == null) {
if (quiet)
return;
throw new RuntimeException(name + " not found");
}
Element root = doc.getDocumentElement();
if (!"configuration".equals(root.getTagName()))
LOG.severe("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 (!"property".equals(prop.getTagName()))
LOG.warning("bad conf file: element not <property>");
NodeList fields = prop.getChildNodes();
String attr = null;
String value = null;
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()))
attr = ((Text)field.getFirstChild()).getData();
if ("value".equals(field.getTagName()) && field.hasChildNodes())
value = ((Text)field.getFirstChild()).getData();
}
if (attr != null && value != null)
properties.setProperty(attr, value);
}
} catch (Exception e) {
LOG.severe("error parsing conf file: " + e);
throw new RuntimeException(e);
}
}
//根据配置文件来设置<k,v>注意后面的配置会覆盖前面的配置
public void write(OutputStream out) throws IOException {
Properties properties = getProps();
try {
Document doc =
DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Element conf = doc.createElement("configuration");
doc.appendChild(conf);
conf.appendChild(doc.createTextNode("\n"));
for (Enumeration e = properties.keys(); e.hasMoreElements();) {
String name = (String)e.nextElement();
Object object = properties.get(name);
String value = null;
if(object instanceof String) {
value = (String) object;
}else {
continue;
}
Element propNode = doc.createElement("property");
conf.appendChild(propNode);
Element nameNode = doc.createElement("name");
nameNode.appendChild(doc.createTextNode(name));
propNode.appendChild(nameNode);
Element valueNode = doc.createElement("value");
valueNode.appendChild(doc.createTextNode(value));
propNode.appendChild(valueNode);
conf.appendChild(doc.createTextNode("\n"));
}
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(out);
TransformerFactory transFactory = TransformerFactory.newInstance();
Transformer transformer = transFactory.newTransformer();
transformer.transform(source, result);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//保存配置信息
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("Configuration: ");
sb.append("defaults: ");
toString(defaultResources, sb);
sb.append("final: ");
toString(finalResources, sb);
return sb.toString();
}
//打印配置信息
private void toString(ArrayList resources, StringBuffer sb) {
ListIterator i = resources.listIterator();
while (i.hasNext()) {
if (i.nextIndex() != 0) {
sb.append(" , ");
}
Object obj = i.next();
if (obj instanceof File) {
sb.append((File)obj);
} else {
sb.append((String)obj);
}
}
}
//打印配置信息
public static void main(String[] args) throws Exception {
new Configuration().write(System.out);
}
}
例子程序
package conf;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URL;
import org.apache.hadoop.conf.Configurable;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
public class ConfTest {
private static ClassLoader classLoader = Thread.currentThread()
.getContextClassLoader();
public static void main(String[] args) throws IOException {
//String dir = new File("").getAbsolutePath();
String dir = ClassLoader.getSystemResource("").getFile().toString();
System.out.println("classpath: "+dir);
StringBuffer defaultString = new StringBuffer();
defaultString.append("<configuration>");
defaultString.append(" <property>");
defaultString.append(" <name>name</name>");
defaultString.append(" <value>qiangzigege</value>");
defaultString.append(" </property>");
defaultString.append(" <property>");
defaultString.append(" <name>age</name>");
defaultString.append(" <value>1</value>");
defaultString.append(" </property>");
defaultString.append("</configuration>");
File defaultXml = new File(dir, "hadoop-default.xml");
defaultXml.deleteOnExit();
boolean create = defaultXml.createNewFile();
if(!create){
System.out.println("create failed for "+defaultXml.getAbsolutePath());
return;
}
System.out.println("create ok for "+defaultXml.getAbsolutePath());
// URL url = classLoader.getResource(defaultXml.getAbsolutePath());
Writer writer = new OutputStreamWriter(new FileOutputStream(defaultXml));
writer.write(defaultString.toString());
writer.flush();
writer.close();
// /
defaultString = new StringBuffer();
defaultString.append("<configuration>");
defaultString.append(" <property>");
defaultString.append(" <name>name</name>");
defaultString.append(" <value>qiangzigege</value>");
defaultString.append(" </property>");
defaultString.append(" <property>");
defaultString.append(" <name>age</name>");
defaultString.append(" <value>100</value>");
defaultString.append(" </property>");
defaultString.append("</configuration>");
defaultXml = new File(dir, "hadoop-site.xml");
System.out.println(defaultXml.getAbsolutePath());
defaultXml.deleteOnExit();
create = defaultXml.createNewFile();
if(!create){
System.out.println("create failed for "+defaultXml.getAbsolutePath());
return;
}
System.out.println("create ok for "+defaultXml.getAbsolutePath());
// URL url = classLoader.getResource(defaultXml.getAbsolutePath());
writer = new OutputStreamWriter(new FileOutputStream(defaultXml));
writer.write(defaultString.toString());
writer.flush();
writer.close();
//if(true)return;
// System.out.println("current-path:" + new
// File("./").getAbsolutePath());
Configuration config = new Configuration();
Configurable configurable = new Configured(config);
config = configurable.getConf();
String name = config.get("name");
int age = config.getInt("age", 6);
String result = "name: " + name + " age: " + age;
System.out.println(result);
}
}