Ini.java
- /*
- * Ini
- *
- * $Id$
- * $URL$
- */
- package gov.usgs.util;
- import java.io.BufferedReader;
- import java.io.InputStreamReader;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.io.PrintStream;
- import java.io.PrintWriter;
- import java.util.Collections;
- import java.util.Iterator;
- import java.util.Properties;
- import java.util.HashMap;
- /**
- * Ini is a Properties that supports sections.
- *
- * Format Rules:
- * <ul>
- * <li>Empty lines are ignored.
- * <li>Leading and trailing white space are ignored.
- * <li>Comments must be on separate lines, and begin with '#' or ';'.
- * <li>Properties are key value pairs delimited by an equals: key = value
- * <li>Section Names are on separate lines, begin with '[' and end with ']'. Any
- * whitespace around the brackets is ignored.
- * <li>Any properties before the first section are in the "null" section
- * </ul>
- *
- * Format Example:
- *
- * <pre>
- * #comment about the global
- * global = value
- *
- * # comment about this section
- * ; another comment about this section
- * [ Section Name ]
- * section = value
- * </pre>
- *
- */
- public class Ini extends Properties {
- /** Serialization version. */
- private static final long serialVersionUID = 1L;
- /** Section names map to Section properties. */
- private HashMap<String, Properties> sections = new HashMap<String, Properties>();
- /** String for representing a comment start */
- public static final String COMMENT_START = ";";
- /** String for representing an alternate comment start */
- public static final String ALTERNATE_COMMENT_START = "#";
- /** String to represent a section start */
- public static final String SECTION_START = "[";
- /** String to represent a section end */
- public static final String SECTION_END = "]";
- /** String to delimit properties */
- public static final String PROPERTY_DELIMITER = "=";
- /**
- * Same as new Ini(null).
- */
- public Ini() {
- this(null);
- }
- /**
- * Construct a new Ini with defaults.
- *
- * @param properties
- * a Properties or Ini object with defaults. If an Ini object,
- * also makes a shallow copy of sections.
- */
- public Ini(final Properties properties) {
- super(properties);
- if (properties instanceof Ini) {
- sections.putAll(((Ini) properties).getSections());
- }
- }
- /**
- * @return the section properties map.
- */
- public HashMap<String, Properties> getSections() {
- return sections;
- }
- /**
- * Get a section property.
- *
- * @param section
- * the section, if null calls getProperty(key).
- * @param key
- * the property name.
- * @return value or property, or null if no matching property found.
- */
- public String getSectionProperty(String section, String key) {
- if (section == null) {
- return getProperty(key);
- } else {
- Properties props = sections.get(section);
- if (props != null) {
- return props.getProperty(key);
- } else {
- return null;
- }
- }
- }
- /**
- * Set a section property.
- *
- * @param section
- * the section, if null calls super.setProperty(key, value).
- * @param key
- * the property name.
- * @param value
- * the property value.
- * @return any previous value for key.
- */
- public Object setSectionProperty(String section, String key, String value) {
- if (section == null) {
- return setProperty(key, value);
- } else {
- Properties props = sections.get(section);
- if (props == null) {
- // new section
- props = new Properties();
- sections.put(section, props);
- }
- return props.setProperty(key, value);
- }
- }
- /**
- * Read an Ini input stream.
- *
- * @param inStream
- * the input stream to read.
- * @throws IOException
- * if unable to parse input stream.
- */
- public void load(InputStream inStream) throws IOException {
- BufferedReader br = new BufferedReader(new InputStreamReader(inStream));
- // keep track of current line number
- int lineNumber = 0;
- // line being parsed
- String line;
- // section being parsed
- Properties section = null;
- while ((line = br.readLine()) != null) {
- lineNumber = lineNumber + 1;
- line = line.trim();
- // empty line or comment
- if (line.length() == 0 || line.startsWith(COMMENT_START)
- || line.startsWith(ALTERNATE_COMMENT_START)) {
- // ignore
- continue;
- }
- // section
- else if (line.startsWith(SECTION_START)
- && line.endsWith(SECTION_END)) {
- // remove brackets
- line = line.replace(SECTION_START, "");
- line = line.replace(SECTION_END, "");
- line = line.trim();
- // store all properties in section
- section = new Properties();
- getSections().put(line, section);
- }
- // parse as property
- else {
- int index = line.indexOf("=");
- if (index == -1) {
- throw new IOException("Expected " + PROPERTY_DELIMITER
- + " on line " + lineNumber + ": '" + line + "'");
- } else {
- String[] parts = line.split(PROPERTY_DELIMITER, 2);
- String key = parts[0].trim();
- String value = parts[1].trim();
- if (section != null) {
- section.setProperty(key, value);
- } else {
- setProperty(key, value);
- }
- }
- }
- }
- br.close();
- }
- /**
- * Write an Ini format to a PrintWriter.
- *
- * @param props
- * properties to write.
- * @param writer
- * the writer that writes.
- * @param header
- * an optioal header that will appear in comments at the start of
- * the ini format.
- * @throws IOException
- * if unable to write output.
- */
- @SuppressWarnings("unchecked")
- public static void write(final Properties props, final PrintWriter writer,
- String header) throws IOException {
- if (header != null) {
- // write the header
- writer.write(new StringBuffer(COMMENT_START).append(" ").append(
- header.trim().replace("\n", "\n" + COMMENT_START + " "))
- .append("\n").toString());
- }
- // write properties
- Iterator<String> iter = (Iterator<String>) Collections.list(
- props.propertyNames()).iterator();
- while (iter.hasNext()) {
- String key = iter.next();
- writer.write(new StringBuffer(key).append(PROPERTY_DELIMITER)
- .append(props.getProperty(key)).append("\n").toString());
- }
- // write sections
- if (props instanceof Ini) {
- Ini ini = (Ini) props;
- iter = ini.getSections().keySet().iterator();
- while (iter.hasNext()) {
- String sectionName = iter.next();
- writer.write(new StringBuffer(SECTION_START)
- .append(sectionName).append(SECTION_END).append("\n")
- .toString());
- write(ini.getSections().get(sectionName), writer, null);
- }
- }
- // flush, but don't close
- writer.flush();
- }
- /**
- * Calls write(new PrintWriter(out), header).
- */
- public void store(OutputStream out, String header) throws IOException {
- write(this, new PrintWriter(out), header);
- }
- /**
- * Write properties to an OutputStream.
- *
- * @param out
- * the OutputStream used for writing.
- */
- public void save(final OutputStream out) {
- try {
- store(out, null);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- /**
- * Write properties to a PrintStream.
- *
- * @param out
- * the PrintStream used for writing.
- */
- public void list(PrintStream out) {
- try {
- store(out, null);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- /**
- * Write properties to a PrintWriter.
- *
- * @param out
- * the PrintWriter used for writing.
- */
- public void list(PrintWriter out) {
- try {
- write(this, out, null);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }