001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.spi.project.support.ant;
043:
044: import java.io.ByteArrayInputStream;
045: import java.io.ByteArrayOutputStream;
046: import java.io.File;
047: import java.io.FileInputStream;
048: import java.io.FileOutputStream;
049: import java.io.IOException;
050: import java.io.InputStream;
051: import java.io.InputStreamReader;
052: import java.io.OutputStream;
053: import java.io.Reader;
054: import java.net.URI;
055: import java.net.URL;
056: import java.util.Arrays;
057: import java.util.Collections;
058: import java.util.HashMap;
059: import java.util.Iterator;
060: import java.util.Map;
061: import org.netbeans.junit.NbTestCase;
062:
063: public class EditablePropertiesTest extends NbTestCase {
064:
065: public EditablePropertiesTest(String name) {
066: super (name);
067: }
068:
069: public void testLoad() throws Exception {
070: Map<String, String> content = new HashMap<String, String>();
071: for (int i = 1; i <= 26; i++) {
072: content.put("key" + i, "value" + i);
073: }
074: content.put("@!#$%^keyA", "valueA!@#$%^&*(){}");
075: content.put(" =:keyB", "valueB =:");
076: content.put("" + (char) 0x1234 + "keyC", "valueC"
077: + (char) 0x9876);
078: content.put("keyD", "");
079: content.put("keyE", "");
080: content.put("keyF", "");
081: content.put("keyG", "");
082: content.put("keyH", "value#this is not comment");
083: content.put("keyI", "incorrect end: \\u123");
084: // #46234: does not handle bad Unicode escapes well
085: content.put("keyJ", "malformed Unicode escape: \\uabyz");
086:
087: EditableProperties ep = loadTestProperties();
088:
089: for (Map.Entry<String, String> entry : content.entrySet()) {
090: String key = entry.getKey();
091: String value = entry.getValue();
092: String epValue = ep.getProperty(key);
093: assertEquals("Expected value for key " + key
094: + " is different", value, epValue);
095: }
096: int count = 0;
097: for (Map.Entry<String, String> entry : ep.entrySet()) {
098: if (entry.getKey() != null) {
099: count++;
100: }
101: }
102: assertEquals("Number of items in property file", content
103: .keySet().size(), count);
104: }
105:
106: /* Doesn't work; java.util.Properties throws IAE for malformed Unicode escapes:
107: public void testJavaUtilPropertiesEquivalence() throws Exception {
108: Properties p = loadTestJavaUtilProperties();
109: EditableProperties ep = loadTestProperties();
110: Iterator it = p.entrySet().iterator();
111: while (it.hasNext()) {
112: Map.Entry entry = (Map.Entry) it.next();
113: String key = (String) entry.getKey();
114: String val = (String) entry.getValue();
115: assertEquals("right value for " + key, val, ep.getProperty(key));
116: }
117: assertEquals("right number of items", p.size(), ep.size());
118: }
119: */
120:
121: public void testSave() throws Exception {
122: clearWorkDir();
123: EditableProperties ep = loadTestProperties();
124: String dest = getWorkDirPath() + File.separatorChar
125: + "new.properties";
126: saveProperties(ep, dest);
127: assertFile("Saved properties must be the same as original one",
128: filenameOfTestProperties(), dest, (String) null);
129: }
130:
131: public void testClonability() throws Exception {
132: clearWorkDir();
133: EditableProperties ep = loadTestProperties();
134:
135: EditableProperties ep2 = ep.cloneProperties();
136: String dest = getWorkDirPath() + File.separatorChar
137: + "new2.properties";
138: saveProperties(ep2, dest);
139: assertFile(
140: "Saved cloned properties must be the same as original one",
141: filenameOfTestProperties(), dest, (String) null);
142:
143: EditableProperties ep3 = (EditableProperties) ep.clone();
144: dest = getWorkDirPath() + File.separatorChar
145: + "new3.properties";
146: saveProperties(ep3, dest);
147: assertFile(
148: "Saved cloned properties must be the same as original one",
149: filenameOfTestProperties(), dest, (String) null);
150: }
151:
152: // test that modifications changes only necessary parts
153: public void testVersionability() throws Exception {
154: clearWorkDir();
155:
156: EditableProperties ep = loadTestProperties();
157:
158: EditableProperties ep2 = ep.cloneProperties();
159: ep2.setProperty("key24", "new value of key 24");
160: String dest = getWorkDirPath() + File.separatorChar
161: + "mod1.properties";
162: saveProperties(ep2, dest);
163: int res[] = compare(filenameOfTestProperties(), dest);
164: assertEquals("One line modified", 1, res[0]);
165: assertEquals("No lines added", 0, res[1]);
166: assertEquals("No lines removed", 0, res[2]);
167:
168: ep2 = ep.cloneProperties();
169: ep2.setProperty("key23", "new value of key23");
170: dest = getWorkDirPath() + File.separatorChar
171: + "mod2.properties";
172: saveProperties(ep2, dest);
173: res = compare(filenameOfTestProperties(), dest);
174: assertEquals("Four lines modified", 4, res[0]);
175: assertEquals("No lines added", 0, res[1]);
176: assertEquals("No lines removed", 0, res[2]);
177:
178: ep2 = ep.cloneProperties();
179: ep2.put("newkey", "new value");
180: dest = getWorkDirPath() + File.separatorChar
181: + "mod3.properties";
182: saveProperties(ep2, dest);
183: res = compare(filenameOfTestProperties(), dest);
184: assertEquals("No lines modified", 0, res[0]);
185: assertEquals("One line added", 1, res[1]);
186: assertEquals("No lines removed", 0, res[2]);
187:
188: ep2 = ep.cloneProperties();
189: assertNotNull(ep2.get("key14"));
190: ep2.remove("key14");
191: assertNull(ep2.get("key14"));
192: dest = getWorkDirPath() + File.separatorChar
193: + "mod4.properties";
194: saveProperties(ep2, dest);
195: res = compare(filenameOfTestProperties(), dest);
196: assertEquals("No lines modified", 0, res[0]);
197: assertEquals("No lines added", 0, res[1]);
198: assertEquals("Two lines removed", 2, res[2]);
199:
200: ep2 = ep.cloneProperties();
201: ep2.setProperty("key21", new String[] { "first line;",
202: "second line;", "third line" });
203: dest = getWorkDirPath() + File.separatorChar
204: + "mod5.properties";
205: saveProperties(ep2, dest);
206: res = compare(filenameOfTestProperties(), dest);
207: assertEquals("Four lines modified", 4, res[0]);
208: assertEquals("No lines added", 0, res[1]);
209: assertEquals("No lines removed", 0, res[2]);
210: ep2.setProperty("key21", "first line;second line;third line");
211: String dest2 = getWorkDirPath() + File.separatorChar
212: + "mod6.properties";
213: saveProperties(ep2, dest2);
214: res = compare(dest, dest2);
215: assertEquals("Four lines modified", 4, res[0]);
216: assertEquals("No lines added", 0, res[1]);
217: assertEquals("No lines removed", 0, res[2]);
218: }
219:
220: // test that array values are stored correctly
221: public void testArrayValues() throws Exception {
222: EditableProperties ep = new EditableProperties(false);
223: ep.setProperty("key1", new String[] { "1. line;", "2. line;",
224: "3. line" });
225: ep.setProperty("key2", "1. line;2. line;3. line");
226: String output = getAsString(ep);
227: String expected = "key1=\\"
228: + System.getProperty("line.separator")
229: + " 1. line;\\"
230: + System.getProperty("line.separator")
231: + " 2. line;\\"
232: + System.getProperty("line.separator") + " 3. line"
233: + System.getProperty("line.separator")
234: + "key2=1. line;2. line;3. line"
235: + System.getProperty("line.separator");
236: assertEquals(expected, output);
237: assertEquals(ep.getProperty("key1"), "1. line;2. line;3. line");
238: assertEquals(ep.getProperty("key2"), "1. line;2. line;3. line");
239: ep.setProperty("key1", "one; two; three");
240: output = getAsString(ep);
241: expected = "key1=one; two; three"
242: + System.getProperty("line.separator")
243: + "key2=1. line;2. line;3. line"
244: + System.getProperty("line.separator");
245: assertEquals(expected, output);
246: assertEquals(ep.getProperty("key1"), "one; two; three");
247: assertEquals(ep.getProperty("key2"), "1. line;2. line;3. line");
248: ep.setProperty("key2", new String[] { "1. line;", "2. line;",
249: "3. line", "one;", "more;", "line;" });
250: ep.setProperty("key", new String[0]);
251: output = getAsString(ep);
252: expected = "key1=one; two; three"
253: + System.getProperty("line.separator") + "key2=\\"
254: + System.getProperty("line.separator")
255: + " 1. line;\\"
256: + System.getProperty("line.separator")
257: + " 2. line;\\"
258: + System.getProperty("line.separator")
259: + " 3. line\\"
260: + System.getProperty("line.separator") + " one;\\"
261: + System.getProperty("line.separator") + " more;\\"
262: + System.getProperty("line.separator") + " line;"
263: + System.getProperty("line.separator") + "key="
264: + System.getProperty("line.separator"); // #45061
265: assertEquals(expected, output);
266: assertEquals(ep.getProperty("key1"), "one; two; three");
267: assertEquals(ep.getProperty("key2"),
268: "1. line;2. line;3. lineone;more;line;");
269: assertEquals(ep.getProperty("key"), "");
270: }
271:
272: public void testSorting() throws Exception {
273: EditableProperties ep = new EditableProperties(false);
274: ep.setProperty("a", "val-a");
275: ep.setProperty("c", "val-c");
276: ep.put("b", "val-b");
277: String output = getAsString(ep);
278: String expected = "a=val-a"
279: + System.getProperty("line.separator") + "c=val-c"
280: + System.getProperty("line.separator") + "b=val-b"
281: + System.getProperty("line.separator");
282: assertEquals(expected, output);
283:
284: ep = new EditableProperties();
285: ep.setProperty("a", "val-a");
286: ep.setProperty("c", "val-c");
287: ep.put("b", "val-b");
288: output = getAsString(ep);
289: expected = "a=val-a" + System.getProperty("line.separator")
290: + "c=val-c" + System.getProperty("line.separator")
291: + "b=val-b" + System.getProperty("line.separator");
292: assertEquals(expected, output);
293:
294: ep = new EditableProperties(true);
295: ep.setProperty("a", "val-a");
296: ep.setProperty("c", "val-c");
297: ep.put("b", "val-b");
298: output = getAsString(ep);
299: expected = "a=val-a" + System.getProperty("line.separator")
300: + "b=val-b" + System.getProperty("line.separator")
301: + "c=val-c" + System.getProperty("line.separator");
302: assertEquals(expected, output);
303: }
304:
305: // test that changing comments work and modify only comments
306: public void testComment() throws Exception {
307: clearWorkDir();
308:
309: EditableProperties ep = loadTestProperties();
310:
311: EditableProperties ep2 = ep.cloneProperties();
312: ep2
313: .setComment(
314: "key10",
315: new String[] { "# this is new comment for property key 10" },
316: false);
317: String dest = getWorkDirPath() + File.separatorChar
318: + "comment1.properties";
319: saveProperties(ep2, dest);
320: int res[] = compare(filenameOfTestProperties(), dest);
321: assertEquals("No lines modified", 0, res[0]);
322: assertEquals("One line added", 1, res[1]);
323: assertEquals("No lines removed", 0, res[2]);
324:
325: ep2 = ep.cloneProperties();
326: ep2.setComment("key1", new String[] { "# new comment",
327: "# new comment second line" }, true);
328: dest = getWorkDirPath() + File.separatorChar
329: + "comment2.properties";
330: saveProperties(ep2, dest);
331: res = compare(filenameOfTestProperties(), dest);
332: assertEquals("No lines modified", 0, res[0]);
333: assertEquals("Two lines added", 2, res[1]);
334: assertEquals("No lines removed", 0, res[2]);
335:
336: ep2 = ep.cloneProperties();
337: ep2.setComment("key26", new String[] { "# changed comment" },
338: false);
339: dest = getWorkDirPath() + File.separatorChar
340: + "comment3.properties";
341: saveProperties(ep2, dest);
342: res = compare(filenameOfTestProperties(), dest);
343: assertEquals("One line modified", 1, res[0]);
344: assertEquals("No lines added", 0, res[1]);
345: assertEquals("No lines removed", 0, res[2]);
346:
347: ep2 = ep.cloneProperties();
348: ep2.setComment("key25", new String[] { "# one line comment" },
349: false);
350: dest = getWorkDirPath() + File.separatorChar
351: + "comment4.properties";
352: saveProperties(ep2, dest);
353: res = compare(filenameOfTestProperties(), dest);
354: assertEquals("Two lines modified", 2, res[0]);
355: assertEquals("No lines added", 0, res[1]);
356: assertEquals("No lines removed", 0, res[2]);
357:
358: ep2 = ep.cloneProperties();
359: ep2.setComment("key26", ep2.getComment("key26"), true);
360: dest = getWorkDirPath() + File.separatorChar
361: + "comment5.properties";
362: saveProperties(ep2, dest);
363: res = compare(filenameOfTestProperties(), dest);
364: assertEquals("No line modified", 0, res[0]);
365: assertEquals("One line added", 1, res[1]);
366: assertEquals("No lines removed", 0, res[2]);
367:
368: }
369:
370: // test that misc chars are correctly escaped, unicode encoded, etc.
371: public void testEscaping() throws Exception {
372: String umlaut = "" + (char) 252;
373: EditableProperties ep = new EditableProperties(false);
374: ep.setProperty("a a", "a space a");
375: ep.setProperty("b" + (char) 0x4567, "val" + (char) 0x1234);
376: ep.setProperty("@!#$%^\\", "!@#$%^&*(){}\\");
377: ep.setProperty("d\nd", "d\nnewline\nd");
378: ep.setProperty("umlaut", umlaut);
379: ep.setProperty("_a a", new String[] { "a space a" });
380: ep.setProperty("_b" + (char) 0x4567, new String[] { "val"
381: + (char) 0x1234 });
382: ep.setProperty("_@!#$%^\\", new String[] { "!@#$%^&*\\",
383: "(){}\\" });
384: ep.setProperty("_d\nd", new String[] { "d\nnew", "line\nd",
385: "\n", "end" });
386: ep.setProperty("_umlaut", new String[] { umlaut, umlaut });
387: String output = getAsString(ep);
388: String expected = "a\\ a=a space a"
389: + System.getProperty("line.separator")
390: + "b\\u4567=val\\u1234"
391: + System.getProperty("line.separator")
392: + "@!#$%^\\\\=!@#$%^&*(){}\\\\"
393: + System.getProperty("line.separator")
394: + "d\\nd=d\\nnewline\\nd"
395: + System.getProperty("line.separator")
396: + "umlaut=\\u00fc"
397: + System.getProperty("line.separator") + "_a\\ a=\\"
398: + System.getProperty("line.separator")
399: + " a space a"
400: + System.getProperty("line.separator") + "_b\\u4567=\\"
401: + System.getProperty("line.separator")
402: + " val\\u1234"
403: + System.getProperty("line.separator")
404: + "_@!#$%^\\\\=\\"
405: + System.getProperty("line.separator")
406: + " !@#$%^&*\\\\\\"
407: + System.getProperty("line.separator") + " (){}\\\\"
408: + System.getProperty("line.separator") + "_d\\nd=\\"
409: + System.getProperty("line.separator")
410: + " d\\nnew\\"
411: + System.getProperty("line.separator")
412: + " line\\nd\\"
413: + System.getProperty("line.separator") + " \\n\\"
414: + System.getProperty("line.separator") + " end"
415: + System.getProperty("line.separator") + "_umlaut=\\"
416: + System.getProperty("line.separator")
417: + " \\u00fc\\"
418: + System.getProperty("line.separator") + " \\u00fc"
419: + System.getProperty("line.separator");
420: assertEquals(expected, output);
421: assertEquals("a space a", ep.getProperty("a a"));
422: assertEquals("val" + (char) 0x1234, ep.getProperty("b"
423: + (char) 0x4567));
424: assertEquals("!@#$%^&*(){}\\", ep.getProperty("@!#$%^\\"));
425: assertEquals("d\nnewline\nd", ep.getProperty("d\nd"));
426: assertEquals(umlaut, ep.getProperty("umlaut"));
427: assertEquals("a space a", ep.getProperty("_a a"));
428: assertEquals("val" + (char) 0x1234, ep.getProperty("_b"
429: + (char) 0x4567));
430: assertEquals("!@#$%^&*\\(){}\\", ep.getProperty("_@!#$%^\\"));
431: assertEquals("d\nnewline\nd\nend", ep.getProperty("_d\nd"));
432: assertEquals(umlaut + umlaut, ep.getProperty("_umlaut"));
433: }
434:
435: // test that iterator implementation is OK
436: public void testIterator() throws Exception {
437: EditableProperties ep = loadTestProperties();
438: Iterator<Map.Entry<String, String>> it1 = ep.entrySet()
439: .iterator();
440: while (it1.hasNext()) {
441: it1.next();
442: }
443: Iterator<String> it2 = ep.keySet().iterator();
444: while (it2.hasNext()) {
445: it2.next();
446: }
447: it2 = ep.keySet().iterator();
448: while (it2.hasNext()) {
449: it2.next();
450: it2.remove();
451: }
452: ep.put("a", "aval");
453: ep.remove("a");
454: ep = loadTestProperties();
455: it1 = ep.entrySet().iterator();
456: while (it1.hasNext()) {
457: Map.Entry<String, String> entry = it1.next();
458: assertNotNull("Property key cannot be null", entry.getKey());
459: assertNotNull("Property value cannot be null", entry
460: .getValue());
461: entry.setValue(entry.getValue() + "-something-new");
462: }
463: it1 = ep.entrySet().iterator();
464: while (it1.hasNext()) {
465: it1.next();
466: it1.remove();
467: }
468: }
469:
470: // test that syntax errors are survived
471: public void testInvalidPropertiesFile() throws Exception {
472: String invalidProperty = "key=value without correct end\\";
473: ByteArrayInputStream is = new ByteArrayInputStream(
474: invalidProperty.getBytes());
475: EditableProperties ep = new EditableProperties();
476: ep.load(is);
477: assertEquals("Syntax error should be resolved", 1, ep.keySet()
478: .size());
479: assertEquals("value without correct end", ep.getProperty("key"));
480: }
481:
482: public void testNonLatinComments() throws Exception {
483: // #60249.
484: String lsep = System.getProperty("line.separator");
485: EditableProperties p = new EditableProperties();
486: p.setProperty("k", "v");
487: p.setComment("k", new String[] { "# \u0158ekni koment teda!" },
488: false);
489: String expected = "# \\u0158ekni koment teda!" + lsep + "k=v"
490: + lsep;
491: assertEquals("Storing non-Latin chars in comments works",
492: expected, getAsString(p));
493: p = new EditableProperties();
494: p
495: .load(new ByteArrayInputStream(expected
496: .getBytes("ISO-8859-1")));
497: assertEquals("Reading non-Latin chars in comments works",
498: Collections.singletonList("# \u0158ekni koment teda!"),
499: Arrays.asList(p.getComment("k")));
500: p.setProperty("k", "v2");
501: expected = "# \\u0158ekni koment teda!" + lsep + "k=v2" + lsep;
502: assertEquals(
503: "Reading and re-writing non-Latin chars in comments works",
504: expected, getAsString(p));
505: }
506:
507: // helper methods:
508:
509: private String filenameOfTestProperties() {
510: // #50987: never use URL.path for this purpose...
511: return new File(URI.create(EditablePropertiesTest.class
512: .getResource("data/test.properties").toExternalForm()))
513: .getAbsolutePath();
514: }
515:
516: private EditableProperties loadTestProperties() throws IOException {
517: URL u = EditablePropertiesTest.class
518: .getResource("data/test.properties");
519: EditableProperties ep = new EditableProperties();
520: InputStream is = u.openStream();
521: try {
522: ep.load(is);
523: } finally {
524: is.close();
525: }
526: return ep;
527: }
528:
529: /*
530: private Properties loadTestJavaUtilProperties() throws IOException {
531: URL u = EditablePropertiesTest.class.getResource("data/test.properties");
532: Properties p = new Properties();
533: InputStream is = u.openStream();
534: try {
535: p.load(is);
536: } finally {
537: is.close();
538: }
539: return p;
540: }
541: */
542:
543: private void saveProperties(EditableProperties ep, String path)
544: throws Exception {
545: OutputStream os = new FileOutputStream(path);
546: try {
547: ep.store(os);
548: } finally {
549: os.close();
550: }
551: }
552:
553: private int[] compare(String f1, String f2) throws Exception {
554: Reader r1 = null;
555: Reader r2 = null;
556: try {
557: r1 = new InputStreamReader(new FileInputStream(f1),
558: "ISO-8859-1");
559: r2 = new InputStreamReader(new FileInputStream(f2),
560: "ISO-8859-1");
561: return AntBasedTestUtil.countTextDiffs(r1, r2);
562: } finally {
563: if (r1 != null) {
564: r1.close();
565: }
566: if (r2 != null) {
567: r2.close();
568: }
569: }
570: }
571:
572: private String getAsString(EditableProperties ep) throws Exception {
573: ByteArrayOutputStream os = new ByteArrayOutputStream();
574: ep.store(os);
575: os.close();
576: return os.toString("ISO-8859-1");
577: }
578:
579: }
|