Hadoop源码之Configuration类

来源:互联网 发布:淘宝拍照单反相机 编辑:程序博客网 时间:2024/05/01 22:28

1 Configuration概况

Configuration是Hadoop中与配置文件打交道的类,他也是JobConfiguration的父类。配置文件一般是内容为一系列xml数据格式的键值对。配置文件可以由一个字符串指定,也可以由一个Path实例指定。

Hadoop默认情况下会加载两个配置文件,core-default.xml和core-site.xml,用户可以为程序加载额外的配置文件。

配置参数可以声明为final,防止后面加载的参数引起它的改变。

在配置文件中字符串值将首先被处理为变量扩展,比如,如果有下面一段配置

<property>     <name>basedir</name>     <value>user.name</value>
</property><property> <name>tempdir</name> <value>basedir</value></property>

 

当Configuration的一个实例conf,调用conf.get("tempdir")时,将得到basedir,而在配置中basedir是字符串,恰好又有属性名为basedir的属性,故最后得到的是user.name

 

2 Configuration

它用Resouce ArrayList<Object> resources 来存储配置文件的名称,用private Properties properties存储键值对。该类的静态代码段将两个默认配置文件名添加进resources

而Configuration的实例调用getProps()获取键值对,getProps()调用loadResource(Properties,Object,blooean)加载资源文件。

3 具体内容及注释:

注释只标记几个重要的方法

public class Configuration implements Iterable<Map.Entry<String,String>>,                                      Writable {  private static final Log LOG =    LogFactory.getLog(Configuration.class);  private boolean quietmode = true;    /**   * List of configuration resources.   */  private ArrayList<Object> resources = new ArrayList<Object>();  /**   * List of configuration parameters marked <b>final</b>.    */  private Set<String> finalParameters = new HashSet<String>();    private boolean loadDefaults = true;    /**   * Configurtion objects   */  private static final WeakHashMap<Configuration,Object> REGISTRY =     new WeakHashMap<Configuration,Object>();    /**   * List of default Resources. Resources are loaded in the order of the list    * entries   */  private static final CopyOnWriteArrayList<String> defaultResources =    new CopyOnWriteArrayList<String>();  //静态代码段,添加两个主要配置文件到defsultResouces  static{    //print deprecation warning if hadoop-site.xml is found in classpath    ClassLoader cL = Thread.currentThread().getContextClassLoader();    if (cL == null) {      cL = Configuration.class.getClassLoader();    }    if(cL.getResource("hadoop-site.xml")!=null) {      LOG.warn("DEPRECATED: hadoop-site.xml found in the classpath. " +          "Usage of hadoop-site.xml is deprecated. Instead use core-site.xml, "          + "mapred-site.xml and hdfs-site.xml to override properties of " +          "core-default.xml, mapred-default.xml and hdfs-default.xml " +          "respectively");    }    addDefaultResource("core-default.xml");    addDefaultResource("core-site.xml");  }    private Properties properties;  private Properties overlay;  private ClassLoader classLoader;  {    classLoader = Thread.currentThread().getContextClassLoader();    if (classLoader == null) {      classLoader = Configuration.class.getClassLoader();    }  }    /** A new configuration. */  public Configuration() {    this(true);  }  /** A new configuration where the behavior of reading from the default    * resources can be turned off.   *    * If the parameter {@code loadDefaults} is false, the new instance   * will not load resources from the default files.    * @param loadDefaults specifies whether to load from the default files   */  public Configuration(boolean loadDefaults) {    this.loadDefaults = loadDefaults;    if (LOG.isDebugEnabled()) {      LOG.debug(StringUtils.stringifyException(new IOException("config()")));    }    synchronized(Configuration.class) {      REGISTRY.put(this, null);    }  }    /**    * A new configuration with the same settings cloned from another.   *    * @param other the configuration from which to clone settings.   */  @SuppressWarnings("unchecked")  public Configuration(Configuration other) {    if (LOG.isDebugEnabled()) {      LOG.debug(StringUtils.stringifyException                (new IOException("config(config)")));    }      this.resources = (ArrayList)other.resources.clone();   synchronized(other) {     if (other.properties != null) {       this.properties = (Properties)other.properties.clone();     }     if (other.overlay!=null) {       this.overlay = (Properties)other.overlay.clone();     }   }       this.finalParameters = new HashSet<String>(other.finalParameters);    synchronized(Configuration.class) {      REGISTRY.put(this, null);    }  }    /**   * Add a default resource. Resources are loaded in the order of the resources    * added.   * @param name file name. File should be present in the classpath.   */  public static synchronized void addDefaultResource(String name) {    if(!defaultResources.contains(name)) {      defaultResources.add(name);      for(Configuration conf : REGISTRY.keySet()) {        if(conf.loadDefaults) {          conf.reloadConfiguration();        }      }    }  }  /**   * Add a configuration resource.    *    * The properties of this resource will override properties of previously    * added resources, unless they were marked <a href="#Final">final</a>.    *    * @param name resource to be added, the classpath is examined for a file    *             with that name.   */  public void addResource(String name) {    addResourceObject(name);  }  /**   * Add a configuration resource.    *    * The properties of this resource will override properties of previously    * added resources, unless they were marked <a href="#Final">final</a>.    *    * @param url url of the resource to be added, the local filesystem is    *            examined directly to find the resource, without referring to    *            the classpath.   */  public void addResource(URL url) {    addResourceObject(url);  }  /**   * Add a configuration resource.    *    * The properties of this resource will override properties of previously    * added resources, unless they were marked <a href="#Final">final</a>.    *    * @param file file-path of resource to be added, the local filesystem is   *             examined directly to find the resource, without referring to    *             the classpath.   */  public void addResource(Path file) {    addResourceObject(file);  }  /**   * Add a configuration resource.    *    * The properties of this resource will override properties of previously    * added resources, unless they were marked <a href="#Final">final</a>.    *    * @param in InputStream to deserialize the object from.    */  public void addResource(InputStream in) {    addResourceObject(in);  }      /**   * Reload configuration from previously added resources.   *   * This method will clear all the configuration read from the added    * resources, and final parameters. This will make the resources to    * be read again before accessing the values. Values that are added   * via set methods will overlay values read from the resources.   */  public synchronized void reloadConfiguration() {    properties = null;                            // trigger reload    finalParameters.clear();                      // clear site-limits  }  //添加资源文件  private synchronized void addResourceObject(Object resource) {    resources.add(resource);                      // add to resources    reloadConfiguration();  }    private static Pattern varPat = Pattern.compile("\\$\\{[^\\}\\$\u0020]+\\}");  private static int MAX_SUBST = 20;  private String substituteVars(String expr) {    if (expr == null) {      return null;    }    Matcher match = varPat.matcher("");    String eval = expr;    for(int s=0; s<MAX_SUBST; s++) {      match.reset(eval);      if (!match.find()) {        return eval;      }      String var = match.group();      var = var.substring(2, var.length()-1); // remove ${ .. }      String val = null;      try {        val = System.getProperty(var);      } catch(SecurityException se) {        LOG.warn("Unexpected SecurityException in Configuration", se);      }      if (val == null) {        val = getRaw(var);      }      if (val == null) {        return eval; // return literal ${var}: var is unbound      }      // substitute      eval = eval.substring(0, match.start())+val+eval.substring(match.end());    }    throw new IllegalStateException("Variable substitution depth too large: "                                     + MAX_SUBST + " " + expr);  }    /**   * Get the value of the <code>name</code> property, <code>null</code> if   * no such property exists.   *    * Values are processed for <a href="#VariableExpansion">variable expansion</a>    * before being returned.    *    * @param name the property name.   * @return the value of the <code>name</code> property,    *         or null if no such property exists.   */  public String get(String name) {    return substituteVars(getProps().getProperty(name));  }  /**   * Get the value of the <code>name</code> property, without doing   * <a href="#VariableExpansion">variable expansion</a>.   *    * @param name the property name.   * @return the value of the <code>name</code> property,    *         or null if no such property exists.   */  public String getRaw(String name) {    return getProps().getProperty(name);  }  /**    * Set the <code>value</code> of the <code>name</code> property.   *    * @param name property name.   * @param value property value.   */  public void set(String name, String value) {    getOverlay().setProperty(name, value);    getProps().setProperty(name, value);  }    /**   * Sets a property if it is currently unset.   * @param name the property name   * @param value the new value   */  public void setIfUnset(String name, String value) {    if (get(name) == null) {      set(name, value);    }  }    private synchronized Properties getOverlay() {    if (overlay==null){      overlay=new Properties();    }    return overlay;  }  /**    * Get the value of the <code>name</code> property. If no such property    * exists, then <code>defaultValue</code> is returned.   *    * @param name property name.   * @param defaultValue default value.   * @return property value, or <code>defaultValue</code> if the property    *         doesn't exist.                       */  public String get(String name, String defaultValue) {    return substituteVars(getProps().getProperty(name, defaultValue));  }      /**    * Get the value of the <code>name</code> property as an <code>int</code>.   *      * If no such property exists, or if the specified value is not a valid   * <code>int</code>, then <code>defaultValue</code> is returned.   *    * @param name property name.   * @param defaultValue default value.   * @return property value as an <code>int</code>,    *         or <code>defaultValue</code>.    */  public int getInt(String name, int defaultValue) {    String valueString = get(name);    if (valueString == null)      return defaultValue;    try {      String hexString = getHexDigits(valueString);      if (hexString != null) {        return Integer.parseInt(hexString, 16);      }      return Integer.parseInt(valueString);    } catch (NumberFormatException e) {      return defaultValue;    }  }  /**    * Set the value of the <code>name</code> property to an <code>int</code>.   *    * @param name property name.   * @param value <code>int</code> value of the property.   */  public void setInt(String name, int value) {    set(name, Integer.toString(value));  }  /**    * Get the value of the <code>name</code> property as a <code>long</code>.     * If no such property is specified, or if the specified value is not a valid   * <code>long</code>, then <code>defaultValue</code> is returned.   *    * @param name property name.   * @param defaultValue default value.   * @return property value as a <code>long</code>,    *         or <code>defaultValue</code>.    */  public long getLong(String name, long defaultValue) {    String valueString = get(name);    if (valueString == null)      return defaultValue;    try {      String hexString = getHexDigits(valueString);      if (hexString != null) {        return Long.parseLong(hexString, 16);      }      return Long.parseLong(valueString);    } catch (NumberFormatException e) {      return defaultValue;    }  }  private String getHexDigits(String value) {    boolean negative = false;    String str = value;    String hexString = null;    if (value.startsWith("-")) {      negative = true;      str = value.substring(1);    }    if (str.startsWith("0x") || str.startsWith("0X")) {      hexString = str.substring(2);      if (negative) {        hexString = "-" + hexString;      }      return hexString;    }    return null;  }    /**    * Set the value of the <code>name</code> property to a <code>long</code>.   *    * @param name property name.   * @param value <code>long</code> value of the property.   */  public void setLong(String name, long value) {    set(name, Long.toString(value));  }  /**    * Get the value of the <code>name</code> property as a <code>float</code>.     * If no such property is specified, or if the specified value is not a valid   * <code>float</code>, then <code>defaultValue</code> is returned.   *    * @param name property name.   * @param defaultValue default value.   * @return property value as a <code>float</code>,    *         or <code>defaultValue</code>.    */  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;    }  }  /**   * Set the value of the <code>name</code> property to a <code>float</code>.   *    * @param name property name.   * @param value property value.   */  public void setFloat(String name, float value) {    set(name,Float.toString(value));  }   /**    * Get the value of the <code>name</code> property as a <code>boolean</code>.     * If no such property is specified, or if the specified value is not a valid   * <code>boolean</code>, then <code>defaultValue</code> is returned.   *    * @param name property name.   * @param defaultValue default value.   * @return property value as a <code>boolean</code>,    *         or <code>defaultValue</code>.    */  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;  }  /**    * Set the value of the <code>name</code> property to a <code>boolean</code>.   *    * @param name property name.   * @param value <code>boolean</code> value of the property.   */  public void setBoolean(String name, boolean value) {    set(name, Boolean.toString(value));  }  /**   * Set the given property, if it is currently unset.   * @param name property name   * @param value new value   */  public void setBooleanIfUnset(String name, boolean value) {    setIfUnset(name, Boolean.toString(value));  }  /**   * A class that represents a set of positive integer ranges. It parses    * strings of the form: "2-3,5,7-" where ranges are separated by comma and    * the lower/upper bounds are separated by dash. Either the lower or upper    * bound may be omitted meaning all values up to or over. So the string    * above means 2, 3, 5, and 7, 8, 9, ...   */  public static class IntegerRanges {    private static class Range {      int start;      int end;    }    List<Range> ranges = new ArrayList<Range>();        public IntegerRanges() {    }        public IntegerRanges(String newValue) {      StringTokenizer itr = new StringTokenizer(newValue, ",");      while (itr.hasMoreTokens()) {        String rng = itr.nextToken().trim();        String[] parts = rng.split("-", 3);        if (parts.length < 1 || parts.length > 2) {          throw new IllegalArgumentException("integer range badly formed: " +                                              rng);        }        Range r = new Range();        r.start = convertToInt(parts[0], 0);        if (parts.length == 2) {          r.end = convertToInt(parts[1], Integer.MAX_VALUE);        } else {          r.end = r.start;        }        if (r.start > r.end) {          throw new IllegalArgumentException("IntegerRange from " + r.start +                                              " to " + r.end + " is invalid");        }        ranges.add(r);      }    }    /**     * Convert a string to an int treating empty strings as the default value.     * @param value the string value     * @param defaultValue the value for if the string is empty     * @return the desired integer     */    private static int convertToInt(String value, int defaultValue) {      String trim = value.trim();      if (trim.length() == 0) {        return defaultValue;      }      return Integer.parseInt(trim);    }    /**     * Is the given value in the set of ranges     * @param value the value to check     * @return is the value in the ranges?     */    public boolean isIncluded(int value) {      for(Range r: ranges) {        if (r.start <= value && value <= r.end) {          return true;        }      }      return false;    }        @Override    public String toString() {      StringBuffer result = new StringBuffer();      boolean first = true;      for(Range r: ranges) {        if (first) {          first = false;        } else {          result.append(',');        }        result.append(r.start);        result.append('-');        result.append(r.end);      }      return result.toString();    }  }  /**   * Parse the given attribute as a set of integer ranges   * @param name the attribute name   * @param defaultValue the default value if it is not set   * @return a new set of ranges from the configured value   */  public IntegerRanges getRange(String name, String defaultValue) {    return new IntegerRanges(get(name, defaultValue));  }  /**    * Get the comma delimited values of the <code>name</code> property as    * a collection of <code>String</code>s.     * If no such property is specified then empty collection is returned.   * <p>   * This is an optimized version of {@link #getStrings(String)}   *    * @param name property name.   * @return property value as a collection of <code>String</code>s.    */  public Collection<String> getStringCollection(String name) {    String valueString = get(name);    return StringUtils.getStringCollection(valueString);  }  /**    * Get the comma delimited values of the <code>name</code> property as    * an array of <code>String</code>s.     * If no such property is specified then <code>null</code> is returned.   *    * @param name property name.   * @return property value as an array of <code>String</code>s,    *         or <code>null</code>.    */  public String[] getStrings(String name) {    String valueString = get(name);    return StringUtils.getStrings(valueString);  }  /**    * Get the comma delimited values of the <code>name</code> property as    * an array of <code>String</code>s.     * If no such property is specified then default value is returned.   *    * @param name property name.   * @param defaultValue The default value   * @return property value as an array of <code>String</code>s,    *         or default value.    */  public String[] getStrings(String name, String... defaultValue) {    String valueString = get(name);    if (valueString == null) {      return defaultValue;    } else {      return StringUtils.getStrings(valueString);    }  }  /**    * Set the array of string values for the <code>name</code> property as    * as comma delimited values.     *    * @param name property name.   * @param values The values   */  public void setStrings(String name, String... values) {    set(name, StringUtils.arrayToString(values));  }   /**   * Load a class by name.   *    * @param name the class name.   * @return the class object.   * @throws ClassNotFoundException if the class is not found.   */  public Class<?> getClassByName(String name) throws ClassNotFoundException {    return Class.forName(name, true, classLoader);  }  /**    * Get the value of the <code>name</code> property   * as an array of <code>Class</code>.   * The value of the property specifies a list of comma separated class names.     * If no such property is specified, then <code>defaultValue</code> is    * returned.   *    * @param name the property name.   * @param defaultValue default value.   * @return property value as a <code>Class[]</code>,    *         or <code>defaultValue</code>.    */  public Class<?>[] getClasses(String name, Class<?> ... defaultValue) {    String[] classnames = getStrings(name);    if (classnames == null)      return defaultValue;    try {      Class<?>[] classes = new Class<?>[classnames.length];      for(int i = 0; i < classnames.length; i++) {        classes[i] = getClassByName(classnames[i]);      }      return classes;    } catch (ClassNotFoundException e) {      throw new RuntimeException(e);    }  }  /**    * Get the value of the <code>name</code> property as a <code>Class</code>.     * If no such property is specified, then <code>defaultValue</code> is    * returned.   *    * @param name the class name.   * @param defaultValue default value.   * @return property value as a <code>Class</code>,    *         or <code>defaultValue</code>.    */  public Class<?> getClass(String name, Class<?> defaultValue) {    String valueString = get(name);    if (valueString == null)      return defaultValue;    try {      return getClassByName(valueString);    } catch (ClassNotFoundException e) {      throw new RuntimeException(e);    }  }  /**    * Get the value of the <code>name</code> property as a <code>Class</code>   * implementing the interface specified by <code>xface</code>.   *      * If no such property is specified, then <code>defaultValue</code> is    * returned.   *    * An exception is thrown if the returned class does not implement the named   * interface.    *    * @param name the class name.   * @param defaultValue default value.   * @param xface the interface implemented by the named class.   * @return property value as a <code>Class</code>,    *         or <code>defaultValue</code>.   */  public <U> Class<? extends U> getClass(String name,                                          Class<? extends U> defaultValue,                                          Class<U> xface) {    try {      Class<?> theClass = getClass(name, defaultValue);      if (theClass != null && !xface.isAssignableFrom(theClass))        throw new RuntimeException(theClass+" not "+xface.getName());      else if (theClass != null)        return theClass.asSubclass(xface);      else        return null;    } catch (Exception e) {      throw new RuntimeException(e);    }  }  /**    * Set the value of the <code>name</code> property to the name of a    * <code>theClass</code> implementing the given interface <code>xface</code>.   *    * An exception is thrown if <code>theClass</code> does not implement the    * interface <code>xface</code>.    *    * @param name property name.   * @param theClass property value.   * @param xface the interface implemented by the named class.   */  public void setClass(String name, Class<?> theClass, Class<?> xface) {    if (!xface.isAssignableFrom(theClass))      throw new RuntimeException(theClass+" not "+xface.getName());    set(name, theClass.getName());  }  /**    * Get a local file under a directory named by <i>dirsProp</i> with   * the given <i>path</i>.  If <i>dirsProp</i> contains multiple directories,   * then one is chosen based on <i>path</i>'s hash code.  If the selected   * directory does not exist, an attempt is made to create it.   *    * @param dirsProp directory in which to locate the file.   * @param path file-path.   * @return local file under the directory with the given path.   */  public Path getLocalPath(String dirsProp, String path)    throws IOException {    String[] dirs = getStrings(dirsProp);    int hashCode = path.hashCode();    FileSystem fs = FileSystem.getLocal(this);    for (int i = 0; i < dirs.length; i++) {  // try each local dir      int index = (hashCode+i & Integer.MAX_VALUE) % dirs.length;      Path file = new Path(dirs[index], path);      Path dir = file.getParent();      if (fs.mkdirs(dir) || fs.exists(dir)) {        return file;      }    }    LOG.warn("Could not make " + path +              " in local directories from " + dirsProp);    for(int i=0; i < dirs.length; i++) {      int index = (hashCode+i & Integer.MAX_VALUE) % dirs.length;      LOG.warn(dirsProp + "[" + index + "]=" + dirs[index]);    }    throw new IOException("No valid local directories in property: "+dirsProp);  }  /**    * Get a local file name under a directory named in <i>dirsProp</i> with   * the given <i>path</i>.  If <i>dirsProp</i> contains multiple directories,   * then one is chosen based on <i>path</i>'s hash code.  If the selected   * directory does not exist, an attempt is made to create it.   *    * @param dirsProp directory in which to locate the file.   * @param path file-path.   * @return local file under the directory with the given path.   */  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);      File dir = file.getParentFile();      if (dir.exists() || dir.mkdirs()) {        return file;      }    }    throw new IOException("No valid local directories in property: "+dirsProp);  }  /**    * Get the {@link URL} for the named resource.   *    * @param name resource name.   * @return the url for the named resource.   */  public URL getResource(String name) {    return classLoader.getResource(name);  }    /**    * Get an input stream attached to the configuration resource with the   * given <code>name</code>.   *    * @param name configuration resource name.   * @return an input stream attached to the resource.   */  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;    }  }  /**    * Get a {@link Reader} attached to the configuration resource with the   * given <code>name</code>.   *    * @param name configuration resource name.   * @return a reader attached to the resource.   */  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 = new Properties();      loadResources(properties, resources, quietmode);      if (overlay!= null)        properties.putAll(overlay);    }    return properties;  }  /**   * Return the number of keys in the configuration.   *   * @return number of keys in the configuration.   */  public int size() {    return getProps().size();  }  /**   * Clears all keys from the configuration.   */  public void clear() {    getProps().clear();    getOverlay().clear();  }  /**   * Get an {@link Iterator} to go through the list of <code>String</code>    * key-value pairs in the configuration.   *    * @return an iterator over the entries.   */  public Iterator<Map.Entry<String, String>> iterator() {    // Get a copy of just the string to string pairs. After the old object    // methods that allow non-strings to be put into configurations are removed,    // we could replace properties with a Map<String,String> and get rid of this    // code.    Map<String,String> result = new HashMap<String,String>();    for(Map.Entry<Object,Object> item: getProps().entrySet()) {      if (item.getKey() instanceof String &&           item.getValue() instanceof String) {        result.put((String) item.getKey(), (String) item.getValue());      }    }    return result.entrySet().iterator();  }  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 {      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) {        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);    }  }  /**    * Write out the non-default properties in this configuration to the give   * {@link OutputStream}.   *    * @param out the output stream to write to.   */  public void writeXml(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);    }  }  /**   * Get the {@link ClassLoader} for this job.   *    * @return the correct class loader.   */  public ClassLoader getClassLoader() {    return classLoader;  }    /**   * Set the class loader that will be used to load the various objects.   *    * @param classLoader the new class loader.   */  public void setClassLoader(ClassLoader classLoader) {    this.classLoader = classLoader;  }    @Override  public String toString() {    StringBuffer sb = new StringBuffer();    sb.append("Configuration: ");    if(loadDefaults) {      toString(defaultResources, sb);      if(resources.size()>0) {        sb.append(", ");      }    }    toString(resources, sb);    return sb.toString();  }  private void toString(List resources, StringBuffer sb) {    ListIterator i = resources.listIterator();    while (i.hasNext()) {      if (i.nextIndex() != 0) {        sb.append(", ");      }      sb.append(i.next());    }  }  /**    * Set the quietness-mode.    *    * In the quiet-mode, error and informational messages might not be logged.   *    * @param quietmode <code>true</code> to set quiet-mode on, <code>false</code>   *              to turn it off.   */  public synchronized void setQuietMode(boolean quietmode) {    this.quietmode = quietmode;  }  /** For debugging.  List non-default properties to the terminal and exit. */  public static void main(String[] args) throws Exception {    new Configuration().writeXml(System.out);  }  @Override  public void readFields(DataInput in) throws IOException {    clear();    int size = WritableUtils.readVInt(in);    for(int i=0; i < size; ++i) {      set(org.apache.hadoop.io.Text.readString(in),           org.apache.hadoop.io.Text.readString(in));    }  }  //@Override  public void write(DataOutput out) throws IOException {    Properties props = getProps();    WritableUtils.writeVInt(out, props.size());    for(Map.Entry<Object, Object> item: props.entrySet()) {      org.apache.hadoop.io.Text.writeString(out, (String) item.getKey());      org.apache.hadoop.io.Text.writeString(out, (String) item.getValue());    }  }}


 

0 0
原创粉丝点击