Browse Source

style

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@687617 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 17 years ago
parent
commit
0fccd329c1
2 changed files with 253 additions and 209 deletions
  1. +136
    -115
      src/main/org/apache/tools/ant/util/LayoutPreservingProperties.java
  2. +117
    -94
      src/tests/junit/org/apache/tools/ant/util/LayoutPreservingPropertiesTest.java

+ 136
- 115
src/main/org/apache/tools/ant/util/LayoutPreservingProperties.java View File

@@ -79,31 +79,32 @@ import java.util.Properties;
*/ */
public class LayoutPreservingProperties extends Properties { public class LayoutPreservingProperties extends Properties {
private static final String LS = System.getProperty("line.separator"); private static final String LS = System.getProperty("line.separator");
/** /**
* Logical lines have escaping and line continuation taken care of. Comments
* and blank lines are logical lines; they are not removed.
* Logical lines have escaping and line continuation taken care
* of. Comments and blank lines are logical lines; they are not
* removed.
*/ */
private ArrayList logicalLines = new ArrayList(); private ArrayList logicalLines = new ArrayList();
/** /**
* Position in the <code>logicalLines</code> list, keyed by property name. * Position in the <code>logicalLines</code> list, keyed by property name.
*/ */
private HashMap keyedPairLines = new HashMap(); private HashMap keyedPairLines = new HashMap();
/** /**
* Flag to indicate that, when we remove a property from the file, we * Flag to indicate that, when we remove a property from the file, we
* also want to remove the comments that precede it. * also want to remove the comments that precede it.
*/ */
private boolean removeComments; private boolean removeComments;
/** /**
* Create a new, empty, Properties collection, with no defaults. * Create a new, empty, Properties collection, with no defaults.
*/ */
public LayoutPreservingProperties() { public LayoutPreservingProperties() {
super(); super();
} }
/** /**
* Create a new, empty, Properties collection, with the specified defaults. * Create a new, empty, Properties collection, with the specified defaults.
* @param defaults the default property values * @param defaults the default property values
@@ -113,58 +114,63 @@ public class LayoutPreservingProperties extends Properties {
} }


/** /**
* Returns <code>true</code> if comments are removed along with properties, or
* <code>false</code> otherwise. If <code>true</code>, then when a property is
* removed, the comment preceding it in the original file is removed also.
* @return <code>true</code> if leading comments are removed when a property is
* removed; <code>false</code> otherwise
* Returns <code>true</code> if comments are removed along with
* properties, or <code>false</code> otherwise. If
* <code>true</code>, then when a property is removed, the comment
* preceding it in the original file is removed also.
* @return <code>true</code> if leading comments are removed when
* a property is removed; <code>false</code> otherwise
*/ */
public boolean isRemoveComments() { public boolean isRemoveComments() {
return removeComments; return removeComments;
} }
/** /**
* Sets the behaviour for comments accompanying properties that are being
* removed. If <code>true</code>, then when a property is removed, the comment
* preceding it in the original file is removed also.
* @param val <code>true</code> if leading comments are to be removed when a property is
* removed; <code>false</code> otherwise
* Sets the behaviour for comments accompanying properties that
* are being removed. If <code>true</code>, then when a property
* is removed, the comment preceding it in the original file is
* removed also.
* @param val <code>true</code> if leading comments are to be
* removed when a property is removed; <code>false</code>
* otherwise
*/ */
public void setRemoveComments(boolean val) { public void setRemoveComments(boolean val) {
removeComments = val; removeComments = val;
} }
public void load(InputStream inStream) throws IOException { public void load(InputStream inStream) throws IOException {
String s = readLines(inStream); String s = readLines(inStream);
byte[] ba = s.getBytes("ISO-8859-1"); byte[] ba = s.getBytes("ISO-8859-1");
ByteArrayInputStream bais = new ByteArrayInputStream(ba); ByteArrayInputStream bais = new ByteArrayInputStream(ba);
super.load(bais); super.load(bais);
} }
public Object put(Object key, Object value) throws NullPointerException { public Object put(Object key, Object value) throws NullPointerException {
Object obj = super.put(key, value); Object obj = super.put(key, value);
// the above call will have failed if key or value are null // the above call will have failed if key or value are null
innerSetProperty(key.toString(), value.toString()); innerSetProperty(key.toString(), value.toString());
return obj; return obj;
} }
public Object setProperty(String key, String value) throws NullPointerException {

public Object setProperty(String key, String value)
throws NullPointerException {
Object obj = super.setProperty(key, value); Object obj = super.setProperty(key, value);
// the above call will have failed if key or value are null // the above call will have failed if key or value are null
innerSetProperty(key, value); innerSetProperty(key, value);
return obj; return obj;
} }
/** /**
* Store a new key-value pair, or add a new one. The normal functionality is
* taken care of by the superclass in the call to {@link #setProperty}; this
* method takes care of this classes extensions.
* Store a new key-value pair, or add a new one. The normal
* functionality is taken care of by the superclass in the call to
* {@link #setProperty}; this method takes care of this classes
* extensions.
* @param key the key of the property to be stored * @param key the key of the property to be stored
* @param value the value to be stored * @param value the value to be stored
*/ */
private void innerSetProperty(String key, String value) { private void innerSetProperty(String key, String value) {
value = escapeValue(value); value = escapeValue(value);
if (keyedPairLines.containsKey(key)) { if (keyedPairLines.containsKey(key)) {
Integer i = (Integer) keyedPairLines.get(key); Integer i = (Integer) keyedPairLines.get(key);
Pair p = (Pair) logicalLines.get(i.intValue()); Pair p = (Pair) logicalLines.get(i.intValue());
@@ -177,13 +183,13 @@ public class LayoutPreservingProperties extends Properties {
logicalLines.add(p); logicalLines.add(p);
} }
} }
public void clear() { public void clear() {
super.clear(); super.clear();
keyedPairLines.clear(); keyedPairLines.clear();
logicalLines.clear(); logicalLines.clear();
} }
public Object remove(Object key) { public Object remove(Object key) {
Object obj = super.remove(key); Object obj = super.remove(key);
Integer i = (Integer) keyedPairLines.remove(key); Integer i = (Integer) keyedPairLines.remove(key);
@@ -195,9 +201,10 @@ public class LayoutPreservingProperties extends Properties {
} }
return obj; return obj;
} }
public Object clone() { public Object clone() {
LayoutPreservingProperties dolly = (LayoutPreservingProperties) super.clone();
LayoutPreservingProperties dolly =
(LayoutPreservingProperties) super.clone();
dolly.keyedPairLines = (HashMap) this.keyedPairLines.clone(); dolly.keyedPairLines = (HashMap) this.keyedPairLines.clone();
dolly.logicalLines = (ArrayList) this.logicalLines.clone(); dolly.logicalLines = (ArrayList) this.logicalLines.clone();
for (int j = 0; j < dolly.logicalLines.size(); j++) { for (int j = 0; j < dolly.logicalLines.size(); j++) {
@@ -210,7 +217,7 @@ public class LayoutPreservingProperties extends Properties {
} }
return dolly; return dolly;
} }
/** /**
* Echo the lines of the properties (including blanks and comments) to the * Echo the lines of the properties (including blanks and comments) to the
* stream. * stream.
@@ -232,7 +239,7 @@ public class LayoutPreservingProperties extends Properties {
} }
} }
} }
/** /**
* Save the properties to a file. * Save the properties to a file.
* @param dest the file to write to * @param dest the file to write to
@@ -242,15 +249,15 @@ public class LayoutPreservingProperties extends Properties {
store(fos, null); store(fos, null);
fos.close(); fos.close();
} }
public void store(OutputStream out, String header) throws IOException { public void store(OutputStream out, String header) throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(out, "ISO-8859-1"); OutputStreamWriter osw = new OutputStreamWriter(out, "ISO-8859-1");
if (header != null) { if (header != null) {
osw.write("#" + header + LS); osw.write("#" + header + LS);
} }
osw.write("#" + (new Date()).toString() + LS); osw.write("#" + (new Date()).toString() + LS);
boolean writtenSep = false; boolean writtenSep = false;
for (Iterator i = logicalLines.iterator();i.hasNext();) { for (Iterator i = logicalLines.iterator();i.hasNext();) {
LogicalLine line = (LogicalLine) i.next(); LogicalLine line = (LogicalLine) i.next();
@@ -268,46 +275,48 @@ public class LayoutPreservingProperties extends Properties {
} }
osw.close(); osw.close();
} }
/** /**
* Reads a properties file into an internally maintained collection of logical
* lines (possibly spanning physcial lines), which make up the comments, blank
* lines and properties of the file.
* Reads a properties file into an internally maintained
* collection of logical lines (possibly spanning physcial lines),
* which make up the comments, blank lines and properties of the
* file.
* @param is the stream from which to read the data * @param is the stream from which to read the data
*/ */
private String readLines(InputStream is) throws IOException { private String readLines(InputStream is) throws IOException {
InputStreamReader isr = new InputStreamReader(is, "ISO-8859-1"); InputStreamReader isr = new InputStreamReader(is, "ISO-8859-1");
BufferedReader br = new BufferedReader(isr); BufferedReader br = new BufferedReader(isr);
if (logicalLines.size() > 0) { if (logicalLines.size() > 0) {
// we add a blank line for spacing // we add a blank line for spacing
logicalLines.add(new Blank()); logicalLines.add(new Blank());
} }
String s = br.readLine(); String s = br.readLine();
boolean continuation = false; boolean continuation = false;
boolean comment = false; boolean comment = false;
StringBuffer fileBuffer = new StringBuffer(); StringBuffer fileBuffer = new StringBuffer();
StringBuffer logicalLineBuffer = new StringBuffer(); StringBuffer logicalLineBuffer = new StringBuffer();
while (s != null) { while (s != null) {
fileBuffer.append(s).append(LS); fileBuffer.append(s).append(LS);
if (continuation) { if (continuation) {
// put in the line feed that was removed // put in the line feed that was removed
s = "\n" + s; s = "\n" + s;
} else { } else {
// could be a comment, if first non-whitespace is a # or !
// could be a comment, if first non-whitespace is a # or !
comment = s.matches("^( |\t|\f)*(#|!).*"); comment = s.matches("^( |\t|\f)*(#|!).*");
} }
// continuation if not a comment and the line ends is an odd number of backslashes

// continuation if not a comment and the line ends is an
// odd number of backslashes
if (!comment) { if (!comment) {
continuation = requiresContinuation(s); continuation = requiresContinuation(s);
} }
logicalLineBuffer.append(s); logicalLineBuffer.append(s);
if (!continuation) { if (!continuation) {
LogicalLine line = null; LogicalLine line = null;
if (comment) { if (comment) {
@@ -331,12 +340,14 @@ public class LayoutPreservingProperties extends Properties {
} }
return fileBuffer.toString(); return fileBuffer.toString();
} }
/** /**
* Returns <code>true</code> if the line represented by <code>s</code> is to be continued
* on the next line of the file, or <code>false</code> otherwise.
* Returns <code>true</code> if the line represented by
* <code>s</code> is to be continued on the next line of the file,
* or <code>false</code> otherwise.
* @param s the contents of the line to examine * @param s the contents of the line to examine
* @return <code>true</code> if the line is to be continued, <code>false</code> otherwise
* @return <code>true</code> if the line is to be continued,
* <code>false</code> otherwise
*/ */
private boolean requiresContinuation(String s) { private boolean requiresContinuation(String s) {
char[] ca = s.toCharArray(); char[] ca = s.toCharArray();
@@ -348,10 +359,11 @@ public class LayoutPreservingProperties extends Properties {
int tb = ca.length - i - 1; int tb = ca.length - i - 1;
return tb % 2 == 1; return tb % 2 == 1;
} }
/** /**
* Unescape the string according to the rules for a Properites file, as laid out in
* the docs for <a href="http://java.sun.com/j2se/1.3/docs/api/java/util/Properties.html">java.util.Properties</a>.
* Unescape the string according to the rules for a Properites
* file, as laid out in the docs for <a
* href="http://java.sun.com/j2se/1.3/docs/api/java/util/Properties.html">java.util.Properties</a>.
* @param s the string to unescape (coming from the source file) * @param s the string to unescape (coming from the source file)
* @return the unescaped string * @return the unescaped string
*/ */
@@ -367,7 +379,7 @@ public class LayoutPreservingProperties extends Properties {
* Any other slash is ignored, so * Any other slash is ignored, so
* \b becomes 'b'. * \b becomes 'b'.
*/ */
char[] ch = new char[s.length() + 1]; char[] ch = new char[s.length() + 1];
s.getChars(0, s.length(), ch, 0); s.getChars(0, s.length(), ch, 0);
ch[s.length()] = '\n'; ch[s.length()] = '\n';
@@ -404,10 +416,10 @@ public class LayoutPreservingProperties extends Properties {
} }
return buffy.toString(); return buffy.toString();
} }
/** /**
* Retrieve the unicode character whose code is listed at position <code>i</code>
* in the character array <code>ch</code>.
* Retrieve the unicode character whose code is listed at position
* <code>i</code> in the character array <code>ch</code>.
* @param ch the character array containing the unicode character code * @param ch the character array containing the unicode character code
* @return the character extracted * @return the character extracted
*/ */
@@ -415,41 +427,46 @@ public class LayoutPreservingProperties extends Properties {
String s = new String(ch, i, 4); String s = new String(ch, i, 4);
return (char) Integer.parseInt(s, 16); return (char) Integer.parseInt(s, 16);
} }
/** /**
* Escape the string <code>s</code> according to the rules in the docs for
* <a href="http://java.sun.com/j2se/1.3/docs/api/java/util/Properties.html">java.util.Properties</a>.
* Escape the string <code>s</code> according to the rules in the
* docs for <a
* href="http://java.sun.com/j2se/1.3/docs/api/java/util/Properties.html">java.util.Properties</a>.
* @param s the string to escape * @param s the string to escape
* @return the escaped string * @return the escaped string
*/ */
private String escapeValue(String s) { private String escapeValue(String s) {
return escape(s, false); return escape(s, false);
} }
/** /**
* Escape the string <code>s</code> according to the rules in the docs for
* <a href="http://java.sun.com/j2se/1.3/docs/api/java/util/Properties.html">java.util.Properties</a>.
* This method escapes all the whitespace, not just the stuff at the beginning.
* Escape the string <code>s</code> according to the rules in the
* docs for <a
* href="http://java.sun.com/j2se/1.3/docs/api/java/util/Properties.html">java.util.Properties</a>.
* This method escapes all the whitespace, not just the stuff at
* the beginning.
* @param s the string to escape * @param s the string to escape
* @return the escaped string * @return the escaped string
*/ */
private String escapeName(String s) { private String escapeName(String s) {
return escape(s, true); return escape(s, true);
} }
/** /**
* Escape the string <code>s</code> according to the rules in the docs for
* <a href="http://java.sun.com/j2se/1.3/docs/api/java/util/Properties.html">java.util.Properties</a>.
* Escape the string <code>s</code> according to the rules in the
* docs for <a
* href="http://java.sun.com/j2se/1.3/docs/api/java/util/Properties.html">java.util.Properties</a>.
* @param s the string to escape * @param s the string to escape
* @param escapeAllSpaces if <code>true</code> the method escapes all the spaces,
* if <code>false</code>, it escapes only the leading whitespace
* @param escapeAllSpaces if <code>true</code> the method escapes
* all the spaces, if <code>false</code>, it escapes only the
* leading whitespace
* @return the escaped string * @return the escaped string
*/ */
private String escape(String s, boolean escapeAllSpaces) { private String escape(String s, boolean escapeAllSpaces) {
if (s == null) { if (s == null) {
return null; return null;
} }
char[] ch = new char[s.length()]; char[] ch = new char[s.length()];
s.getChars(0, s.length(), ch, 0); s.getChars(0, s.length(), ch, 0);
String forEscaping = "\t\f\r\n\\:=#!"; String forEscaping = "\t\f\r\n\\:=#!";
@@ -476,9 +493,10 @@ public class LayoutPreservingProperties extends Properties {
} }
return buffy.toString(); return buffy.toString();
} }
/** /**
* Return the unicode escape sequence for a character, in the form \u005CuNNNN.
* Return the unicode escape sequence for a character, in the form
* \u005CuNNNN.
* @param ch the character to encode * @param ch the character to encode
* @return the unicode escape sequence * @return the unicode escape sequence
*/ */
@@ -489,66 +507,68 @@ public class LayoutPreservingProperties extends Properties {
buffy.append(hex); buffy.append(hex);
return buffy.toString(); return buffy.toString();
} }
/** /**
* Remove the comments in the leading up the {@link logicalLines} list leading
* up to line <code>pos</code>.
* Remove the comments in the leading up the {@link logicalLines}
* list leading up to line <code>pos</code>.
* @param pos the line number to which the comments lead * @param pos the line number to which the comments lead
*/ */
private void removeCommentsEndingAt(int pos) { private void removeCommentsEndingAt(int pos) {
/* We want to remove comments preceding this position. Step back counting
* blank lines (call this range B1) until we hit something non-blank. If
* what we hit is not a comment, then exit. If what we hit is a comment,
* then step back counting comment lines (call this range C1). Nullify
* lines in C1 and B1.
/* We want to remove comments preceding this position. Step
* back counting blank lines (call this range B1) until we hit
* something non-blank. If what we hit is not a comment, then
* exit. If what we hit is a comment, then step back counting
* comment lines (call this range C1). Nullify lines in C1 and
* B1.
*/ */
int end = pos - 1; int end = pos - 1;
// step pos back until it hits something non-blank // step pos back until it hits something non-blank
for (pos = end; pos > 0; pos--) { for (pos = end; pos > 0; pos--) {
if (!(logicalLines.get(pos) instanceof Blank)) { if (!(logicalLines.get(pos) instanceof Blank)) {
break; break;
} }
} }
// if the thing it hits is not a comment, then we have nothing to remove

// if the thing it hits is not a comment, then we have nothing
// to remove
if (!(logicalLines.get(pos) instanceof Comment)) { if (!(logicalLines.get(pos) instanceof Comment)) {
return; return;
} }
// step back until we hit the start of the comment // step back until we hit the start of the comment
for (; pos >= 0; pos--) { for (; pos >= 0; pos--) {
if (!(logicalLines.get(pos) instanceof Comment)) { if (!(logicalLines.get(pos) instanceof Comment)) {
break; break;
} }
} }
// now we want to delete from pos+1 to end // now we want to delete from pos+1 to end
for (pos++ ;pos <= end; pos++) { for (pos++ ;pos <= end; pos++) {
logicalLines.set(pos, null); logicalLines.set(pos, null);
} }
} }
/** /**
* A logical line of the properties input stream. * A logical line of the properties input stream.
*/ */
private static abstract class LogicalLine { private static abstract class LogicalLine {
private String text; private String text;
public LogicalLine(String text) { public LogicalLine(String text) {
this.text = text; this.text = text;
} }
public void setText(String text) { public void setText(String text) {
this.text = text; this.text = text;
} }
public String toString() { public String toString() {
return text; return text;
} }
} }
/** /**
* A blank line of the input stream. * A blank line of the input stream.
*/ */
@@ -557,7 +577,7 @@ public class LayoutPreservingProperties extends Properties {
super(""); super("");
} }
} }
/** /**
* A comment line of the input stream. * A comment line of the input stream.
*/ */
@@ -566,48 +586,49 @@ public class LayoutPreservingProperties extends Properties {
super(text); super(text);
} }
} }
/** /**
* A key-value pair from the input stream. This may span more than one physical
* line, but it is constitutes as a single logical line.
* A key-value pair from the input stream. This may span more than
* one physical line, but it is constitutes as a single logical
* line.
*/ */
private static class Pair extends LogicalLine implements Cloneable { private static class Pair extends LogicalLine implements Cloneable {
private String name; private String name;
private String value; private String value;
private boolean added; private boolean added;
public Pair(String text) { public Pair(String text) {
super(text); super(text);
parsePair(text); parsePair(text);
} }
public Pair(String name, String value) { public Pair(String name, String value) {
this(name + "=" + value); this(name + "=" + value);
} }
public String getName() { public String getName() {
return name; return name;
} }
public String getValue() { public String getValue() {
return value; return value;
} }
public void setValue(String value) { public void setValue(String value) {
this.value = value; this.value = value;
setText(name + "=" + value); setText(name + "=" + value);
} }
public boolean isNew() { public boolean isNew() {
return added; return added;
} }
public void setNew(boolean val) { public void setNew(boolean val) {
added = val; added = val;
} }
public Object clone() { public Object clone() {
Object dolly = null;
Object dolly = null;
try { try {
dolly = super.clone(); dolly = super.clone();
} }
@@ -617,7 +638,7 @@ public class LayoutPreservingProperties extends Properties {
} }
return dolly; return dolly;
} }
private void parsePair(String text) { private void parsePair(String text) {
// need to find first non-escaped '=', ':', '\t' or ' '. // need to find first non-escaped '=', ':', '\t' or ' '.
int pos = findFirstSeparator(text); int pos = findFirstSeparator(text);
@@ -633,12 +654,12 @@ public class LayoutPreservingProperties extends Properties {
// trim leading whitespace only // trim leading whitespace only
name = stripStart(name, " \t\f"); name = stripStart(name, " \t\f");
} }
private String stripStart(String s, String chars) { private String stripStart(String s, String chars) {
if (s == null) { if (s == null) {
return null; return null;
} }
int i = 0; int i = 0;
for (;i < s.length(); i++) { for (;i < s.length(); i++) {
if (chars.indexOf(s.charAt(i)) == -1) { if (chars.indexOf(s.charAt(i)) == -1) {
@@ -650,29 +671,29 @@ public class LayoutPreservingProperties extends Properties {
} }
return s.substring(i); return s.substring(i);
} }
private int findFirstSeparator(String s) { private int findFirstSeparator(String s) {
// Replace double backslashes with underscores so that they don't // Replace double backslashes with underscores so that they don't
// confuse us looking for '\t' or '\=', for example, but they also // confuse us looking for '\t' or '\=', for example, but they also
// don't change the position of other characters // don't change the position of other characters
s = s.replaceAll("\\\\\\\\", "__"); s = s.replaceAll("\\\\\\\\", "__");
// Replace single backslashes followed by separators, so we don't // Replace single backslashes followed by separators, so we don't
// pick them up // pick them up
s = s.replaceAll("\\\\=", "__"); s = s.replaceAll("\\\\=", "__");
s = s.replaceAll("\\\\:", "__"); s = s.replaceAll("\\\\:", "__");
s = s.replaceAll("\\\\ ", "__"); s = s.replaceAll("\\\\ ", "__");
s = s.replaceAll("\\\\t", "__"); s = s.replaceAll("\\\\t", "__");
// Now only the unescaped separators are left // Now only the unescaped separators are left
return indexOfAny(s, " :=\t"); return indexOfAny(s, " :=\t");
} }
private int indexOfAny(String s, String chars) { private int indexOfAny(String s, String chars) {
if (s == null || chars == null) { if (s == null || chars == null) {
return -1; return -1;
} }
int p = s.length() + 1; int p = s.length() + 1;
for (int i = 0; i < chars.length(); i++) { for (int i = 0; i < chars.length(); i++) {
int x = s.indexOf(chars.charAt(i)); int x = s.indexOf(chars.charAt(i));


+ 117
- 94
src/tests/junit/org/apache/tools/ant/util/LayoutPreservingPropertiesTest.java View File

@@ -30,43 +30,45 @@ public class LayoutPreservingPropertiesTest extends TestCase {
public LayoutPreservingPropertiesTest(String s) { public LayoutPreservingPropertiesTest(String s) {
super(s); super(s);
} }
/**
* Tests that a properties file read by the LayoutPreservingPropertiesFile
* and then saves the properties in it.

/**
* Tests that a properties file read by the
* LayoutPreservingPropertiesFile and then saves the properties in
* it.
*/ */
public void testPreserve() throws Exception { public void testPreserve() throws Exception {
File simple = new File(System.getProperty("root"), "src/etc/testcases/util/simple.properties");
FileInputStream fis = new FileInputStream(simple);
File simple = new File(System.getProperty("root"),
"src/etc/testcases/util/simple.properties");
FileInputStream fis = new FileInputStream(simple);
LayoutPreservingProperties lpf = new LayoutPreservingProperties(); LayoutPreservingProperties lpf = new LayoutPreservingProperties();
lpf.load(fis); lpf.load(fis);
File tmp = File.createTempFile("tmp", "props"); File tmp = File.createTempFile("tmp", "props");
tmp.deleteOnExit(); tmp.deleteOnExit();
lpf.saveAs(tmp); lpf.saveAs(tmp);
// now compare original and tmp for property equivalence // now compare original and tmp for property equivalence
Properties originalProps = new Properties(); Properties originalProps = new Properties();
originalProps.load(new FileInputStream(simple)); originalProps.load(new FileInputStream(simple));
Properties tmpProps = new Properties(); Properties tmpProps = new Properties();
tmpProps.load(new FileInputStream(tmp)); tmpProps.load(new FileInputStream(tmp));
assertEquals("properties corrupted", originalProps, tmpProps); assertEquals("properties corrupted", originalProps, tmpProps);
// and now make sure that the comments made it into the new file // and now make sure that the comments made it into the new file
String s = readFile(tmp); String s = readFile(tmp);
assertTrue("missing comment", s.indexOf("# a comment") > -1); assertTrue("missing comment", s.indexOf("# a comment") > -1);
assertTrue("missing comment", s.indexOf("! more comment") > -1); assertTrue("missing comment", s.indexOf("! more comment") > -1);
} }
/**
/**
* Tests that names and value are properly escaped when being * Tests that names and value are properly escaped when being
* written out. * written out.
*/ */
public void testEscaping() throws Exception { public void testEscaping() throws Exception {
LayoutPreservingProperties lpf = new LayoutPreservingProperties(); LayoutPreservingProperties lpf = new LayoutPreservingProperties();
lpf.setProperty(" prop one ", " leading and trailing spaces "); lpf.setProperty(" prop one ", " leading and trailing spaces ");
lpf.setProperty("prop\ttwo", "contains\ttab"); lpf.setProperty("prop\ttwo", "contains\ttab");
lpf.setProperty("prop\nthree", "contains\nnewline"); lpf.setProperty("prop\nthree", "contains\nnewline");
@@ -77,15 +79,16 @@ public class LayoutPreservingPropertiesTest extends TestCase {
lpf.setProperty("prop=eight", "contains=equals"); lpf.setProperty("prop=eight", "contains=equals");
lpf.setProperty("prop#nine", "contains#hash"); lpf.setProperty("prop#nine", "contains#hash");
lpf.setProperty("prop!ten", "contains!exclamation"); lpf.setProperty("prop!ten", "contains!exclamation");
File tmp = File.createTempFile("tmp", "props"); File tmp = File.createTempFile("tmp", "props");
tmp.deleteOnExit(); tmp.deleteOnExit();
lpf.saveAs(tmp); lpf.saveAs(tmp);
// and check that the resulting file looks okay // and check that the resulting file looks okay
String s = readFile(tmp); String s = readFile(tmp);
assertTrue(s.indexOf("\\ prop\\ one\\ =\\ \\ leading and trailing spaces ") > -1);

assertTrue(s.indexOf("\\ prop\\ one\\ =\\ \\ leading and trailing"
+ " spaces ") > -1);
assertTrue(s.indexOf("prop\\ttwo=contains\\ttab") > -1); assertTrue(s.indexOf("prop\\ttwo=contains\\ttab") > -1);
assertTrue(s.indexOf("prop\\nthree=contains\\nnewline") > -1); assertTrue(s.indexOf("prop\\nthree=contains\\nnewline") > -1);
assertTrue(s.indexOf("prop\\rfour=contains\\rcarraige return") > -1); assertTrue(s.indexOf("prop\\rfour=contains\\rcarraige return") > -1);
@@ -95,190 +98,210 @@ public class LayoutPreservingPropertiesTest extends TestCase {
assertTrue(s.indexOf("prop\\#nine=contains\\#hash") > -1); assertTrue(s.indexOf("prop\\#nine=contains\\#hash") > -1);
assertTrue(s.indexOf("prop\\!ten=contains\\!exclamation") > -1); assertTrue(s.indexOf("prop\\!ten=contains\\!exclamation") > -1);
} }
/**
/**
* Tests that properties are correctly indexed, so that when we set * Tests that properties are correctly indexed, so that when we set
* an existing property, it updates the logical line, and it doesn't * an existing property, it updates the logical line, and it doesn't
* append a new one. * append a new one.
*/ */
public void testOverwrite() throws Exception { public void testOverwrite() throws Exception {
File unusual = new File(System.getProperty("root"), "src/etc/testcases/util/unusual.properties");
FileInputStream fis = new FileInputStream(unusual);
File unusual = new File(System.getProperty("root"),
"src/etc/testcases/util/unusual.properties");
FileInputStream fis = new FileInputStream(unusual);
LayoutPreservingProperties lpf = new LayoutPreservingProperties(); LayoutPreservingProperties lpf = new LayoutPreservingProperties();
lpf.load(fis); lpf.load(fis);
lpf.setProperty(" prop one ", "new one"); lpf.setProperty(" prop one ", "new one");
lpf.setProperty("prop\ttwo", "new two"); lpf.setProperty("prop\ttwo", "new two");
lpf.setProperty("prop\nthree", "new three"); lpf.setProperty("prop\nthree", "new three");
File tmp = File.createTempFile("tmp", "props"); File tmp = File.createTempFile("tmp", "props");
tmp.deleteOnExit(); tmp.deleteOnExit();
lpf.saveAs(tmp); lpf.saveAs(tmp);
// and check that the resulting file looks okay // and check that the resulting file looks okay
String s = readFile(tmp); String s = readFile(tmp);
assertTrue(s.indexOf("\\ prop\\ one\\ =\\ \\ leading and trailing spaces ") == -1);

assertTrue(s.indexOf("\\ prop\\ one\\ =\\ \\ leading and"
+ " trailing spaces ") == -1);
assertTrue(s.indexOf("\\ prop\\ one\\ =new one") > -1); assertTrue(s.indexOf("\\ prop\\ one\\ =new one") > -1);
assertTrue(s.indexOf("prop\\ttwo=contains\\ttab") == -1); assertTrue(s.indexOf("prop\\ttwo=contains\\ttab") == -1);
assertTrue(s.indexOf("prop\\ttwo=new two") > -1); assertTrue(s.indexOf("prop\\ttwo=new two") > -1);
assertTrue(s.indexOf("prop\\nthree=contains\\nnewline") == -1); assertTrue(s.indexOf("prop\\nthree=contains\\nnewline") == -1);
assertTrue(s.indexOf("prop\\nthree=new three") > -1); assertTrue(s.indexOf("prop\\nthree=new three") > -1);
} }
public void testStoreWithHeader() throws Exception { public void testStoreWithHeader() throws Exception {
File simple = new File(System.getProperty("root"), "src/etc/testcases/util/simple.properties");
FileInputStream fis = new FileInputStream(simple);
File simple = new File(System.getProperty("root"),
"src/etc/testcases/util/simple.properties");
FileInputStream fis = new FileInputStream(simple);
LayoutPreservingProperties lpf = new LayoutPreservingProperties(); LayoutPreservingProperties lpf = new LayoutPreservingProperties();
lpf.load(fis); lpf.load(fis);
File tmp = File.createTempFile("tmp", "props"); File tmp = File.createTempFile("tmp", "props");
tmp.deleteOnExit(); tmp.deleteOnExit();
FileOutputStream fos = new FileOutputStream(tmp); FileOutputStream fos = new FileOutputStream(tmp);
lpf.store(fos, "file-header"); lpf.store(fos, "file-header");
fos.close(); fos.close();
// and check that the resulting file looks okay // and check that the resulting file looks okay
String s = readFile(tmp); String s = readFile(tmp);
assertTrue("should have had header ", s.startsWith("#file-header")); assertTrue("should have had header ", s.startsWith("#file-header"));
} }
public void testClear() throws Exception { public void testClear() throws Exception {
File simple = new File(System.getProperty("root"), "src/etc/testcases/util/simple.properties");
FileInputStream fis = new FileInputStream(simple);
File simple = new File(System.getProperty("root"),
"src/etc/testcases/util/simple.properties");
FileInputStream fis = new FileInputStream(simple);
LayoutPreservingProperties lpf = new LayoutPreservingProperties(); LayoutPreservingProperties lpf = new LayoutPreservingProperties();
lpf.load(fis); lpf.load(fis);
lpf.clear(); lpf.clear();
File tmp = File.createTempFile("tmp", "props"); File tmp = File.createTempFile("tmp", "props");
tmp.deleteOnExit(); tmp.deleteOnExit();
lpf.saveAs(tmp); lpf.saveAs(tmp);
// and check that the resulting file looks okay // and check that the resulting file looks okay
String s = readFile(tmp); String s = readFile(tmp);
assertTrue("should have had no properties ", s.indexOf("prop.alpha") == -1);
assertTrue("should have had no properties ", s.indexOf("prop.beta") == -1);
assertTrue("should have had no properties ", s.indexOf("prop.gamma") == -1);
assertTrue("should have had no comments", s.indexOf("# a comment") == -1);
assertTrue("should have had no comments", s.indexOf("! more comment") == -1);
assertTrue("should have had no comments", s.indexOf("# now a line wrapping one") == -1);

assertTrue("should have had no properties ",
s.indexOf("prop.alpha") == -1);
assertTrue("should have had no properties ",
s.indexOf("prop.beta") == -1);
assertTrue("should have had no properties ",
s.indexOf("prop.gamma") == -1);

assertTrue("should have had no comments",
s.indexOf("# a comment") == -1);
assertTrue("should have had no comments",
s.indexOf("! more comment") == -1);
assertTrue("should have had no comments",
s.indexOf("# now a line wrapping one") == -1);
} }
public void testRemove() throws Exception { public void testRemove() throws Exception {
File simple = new File(System.getProperty("root"), "src/etc/testcases/util/simple.properties");
FileInputStream fis = new FileInputStream(simple);
File simple = new File(System.getProperty("root"),
"src/etc/testcases/util/simple.properties");
FileInputStream fis = new FileInputStream(simple);
LayoutPreservingProperties lpf = new LayoutPreservingProperties(); LayoutPreservingProperties lpf = new LayoutPreservingProperties();
lpf.load(fis); lpf.load(fis);
lpf.remove("prop.beta"); lpf.remove("prop.beta");
File tmp = File.createTempFile("tmp", "props"); File tmp = File.createTempFile("tmp", "props");
tmp.deleteOnExit(); tmp.deleteOnExit();
lpf.saveAs(tmp); lpf.saveAs(tmp);
// and check that the resulting file looks okay // and check that the resulting file looks okay
String s = readFile(tmp); String s = readFile(tmp);
assertTrue("should not have had prop.beta", s.indexOf("prop.beta") == -1);
assertTrue("should have had prop.beta's comment", s.indexOf("! more comment") > -1);

assertTrue("should not have had prop.beta",
s.indexOf("prop.beta") == -1);
assertTrue("should have had prop.beta's comment",
s.indexOf("! more comment") > -1);
} }
public void testRemoveWithComment() throws Exception { public void testRemoveWithComment() throws Exception {
File simple = new File(System.getProperty("root"), "src/etc/testcases/util/simple.properties");
FileInputStream fis = new FileInputStream(simple);
File simple = new File(System.getProperty("root"),
"src/etc/testcases/util/simple.properties");
FileInputStream fis = new FileInputStream(simple);
LayoutPreservingProperties lpf = new LayoutPreservingProperties(); LayoutPreservingProperties lpf = new LayoutPreservingProperties();
lpf.load(fis); lpf.load(fis);
lpf.setRemoveComments(true); lpf.setRemoveComments(true);
lpf.remove("prop.beta"); lpf.remove("prop.beta");
File tmp = File.createTempFile("tmp", "props"); File tmp = File.createTempFile("tmp", "props");
tmp.deleteOnExit(); tmp.deleteOnExit();
lpf.saveAs(tmp); lpf.saveAs(tmp);
// and check that the resulting file looks okay // and check that the resulting file looks okay
String s = readFile(tmp); String s = readFile(tmp);
assertTrue("should not have had prop.beta", s.indexOf("prop.beta") == -1);
assertTrue("should not have had prop.beta's comment", s.indexOf("! more comment") == -1);

assertTrue("should not have had prop.beta",
s.indexOf("prop.beta") == -1);
assertTrue("should not have had prop.beta's comment",
s.indexOf("! more comment") == -1);
} }
public void testClone() throws Exception { public void testClone() throws Exception {
File simple = new File(System.getProperty("root"), "src/etc/testcases/util/simple.properties");
FileInputStream fis = new FileInputStream(simple);
File simple = new File(System.getProperty("root"),
"src/etc/testcases/util/simple.properties");
FileInputStream fis = new FileInputStream(simple);
LayoutPreservingProperties lpf1 = new LayoutPreservingProperties(); LayoutPreservingProperties lpf1 = new LayoutPreservingProperties();
lpf1.load(fis); lpf1.load(fis);
LayoutPreservingProperties lpf2 = (LayoutPreservingProperties) lpf1.clone();

LayoutPreservingProperties lpf2 =
(LayoutPreservingProperties) lpf1.clone();

lpf2.setProperty("prop.new", "a new property"); lpf2.setProperty("prop.new", "a new property");
lpf2.setProperty("prop.beta", "a new value for beta"); lpf2.setProperty("prop.beta", "a new value for beta");
assertEquals("size of original is wrong", 3, lpf1.size()); assertEquals("size of original is wrong", 3, lpf1.size());
assertEquals("size of clone is wrong", 4, lpf2.size()); assertEquals("size of clone is wrong", 4, lpf2.size());
File tmp1 = File.createTempFile("tmp", "props"); File tmp1 = File.createTempFile("tmp", "props");
tmp1.deleteOnExit(); tmp1.deleteOnExit();
lpf1.saveAs(tmp1); lpf1.saveAs(tmp1);
String s1 = readFile(tmp1); String s1 = readFile(tmp1);
File tmp2 = File.createTempFile("tmp", "props"); File tmp2 = File.createTempFile("tmp", "props");
tmp2.deleteOnExit(); tmp2.deleteOnExit();
lpf2.saveAs(tmp2); lpf2.saveAs(tmp2);
String s2 = readFile(tmp2); String s2 = readFile(tmp2);
// check original is untouched // check original is untouched
assertTrue("should have had 'simple'", s1.indexOf("simple") > -1); assertTrue("should have had 'simple'", s1.indexOf("simple") > -1);
assertTrue("should not have had prop.new", s1.indexOf("prop.new") == -1); assertTrue("should not have had prop.new", s1.indexOf("prop.new") == -1);
// check clone has the changes // check clone has the changes
assertTrue("should have had 'a new value for beta'", s2.indexOf("a new value for beta") > -1);
assertTrue("should have had 'a new value for beta'",
s2.indexOf("a new value for beta") > -1);
assertTrue("should have had prop.new", s2.indexOf("prop.new") > -1); assertTrue("should have had prop.new", s2.indexOf("prop.new") > -1);
} }
public void testPreserveEsacpeName() throws Exception { public void testPreserveEsacpeName() throws Exception {
LayoutPreservingProperties lpf = new LayoutPreservingProperties(); LayoutPreservingProperties lpf = new LayoutPreservingProperties();
File unusual = new File(System.getProperty("root"), "src/etc/testcases/util/unusual.properties");
FileInputStream fis = new FileInputStream(unusual);
File unusual = new File(System.getProperty("root"),
"src/etc/testcases/util/unusual.properties");
FileInputStream fis = new FileInputStream(unusual);
lpf.load(fis); lpf.load(fis);
lpf.setProperty("prop:seven", "new value for seven"); lpf.setProperty("prop:seven", "new value for seven");
lpf.setProperty("prop=eight", "new value for eight"); lpf.setProperty("prop=eight", "new value for eight");
lpf.setProperty("prop eleven", "new value for eleven"); lpf.setProperty("prop eleven", "new value for eleven");
lpf.setProperty("alpha", "new value for alpha"); lpf.setProperty("alpha", "new value for alpha");
lpf.setProperty("beta", "new value for beta"); lpf.setProperty("beta", "new value for beta");
File tmp = File.createTempFile("tmp", "props"); File tmp = File.createTempFile("tmp", "props");
tmp.deleteOnExit(); tmp.deleteOnExit();
lpf.saveAs(tmp); lpf.saveAs(tmp);
// and check that the resulting file looks okay // and check that the resulting file looks okay
String s = readFile(tmp); String s = readFile(tmp);
assertTrue(s.indexOf("prop\\:seven=new value for seven") > -1); assertTrue(s.indexOf("prop\\:seven=new value for seven") > -1);
assertTrue(s.indexOf("prop\\=eight=new value for eight") > -1); assertTrue(s.indexOf("prop\\=eight=new value for eight") > -1);
assertTrue(s.indexOf("prop\\ eleven=new value for eleven") > -1); assertTrue(s.indexOf("prop\\ eleven=new value for eleven") > -1);
assertTrue(s.indexOf("alpha=new value for alpha") > -1); assertTrue(s.indexOf("alpha=new value for alpha") > -1);
assertTrue(s.indexOf("beta=new value for beta") > -1); assertTrue(s.indexOf("beta=new value for beta") > -1);
assertTrue(s.indexOf("prop\\:seven=contains\\:colon") == -1); assertTrue(s.indexOf("prop\\:seven=contains\\:colon") == -1);
assertTrue(s.indexOf("prop\\=eight=contains\\=equals") == -1); assertTrue(s.indexOf("prop\\=eight=contains\\=equals") == -1);
assertTrue(s.indexOf("alpha:set with a colon") == -1); assertTrue(s.indexOf("alpha:set with a colon") == -1);
assertTrue(s.indexOf("beta set with a space") == -1); assertTrue(s.indexOf("beta set with a space") == -1);
} }
private String readFile(File f) throws IOException { private String readFile(File f) throws IOException {
FileInputStream fis = new FileInputStream(f);
InputStreamReader isr = new InputStreamReader(fis);
String s = FileUtils.readFully(isr);
isr.close();
fis.close();
return s;
FileInputStream fis = new FileInputStream(f);
InputStreamReader isr = new InputStreamReader(fis);
String s = FileUtils.readFully(isr);
isr.close();
fis.close();
return s;
} }
} }

Loading…
Cancel
Save