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.File;
046: import java.io.FileInputStream;
047: import java.io.IOException;
048: import java.io.InputStream;
049: import java.io.OutputStream;
050: import java.io.PrintWriter;
051: import java.util.ArrayList;
052: import java.util.Arrays;
053: import java.util.Collections;
054: import java.util.HashMap;
055: import java.util.List;
056: import java.util.Map;
057: import java.util.Properties;
058: import junit.framework.TestResult;
059: import org.netbeans.api.project.ProjectManager;
060: import org.netbeans.junit.NbTestCase;
061: import org.openide.filesystems.FileLock;
062: import org.openide.filesystems.FileObject;
063: import org.openide.filesystems.FileSystem;
064: import org.openide.filesystems.FileUtil;
065: import org.openide.util.Mutex;
066: import org.openide.util.NbCollections;
067: import org.openide.util.Utilities;
068: import org.openide.util.test.MockChangeListener;
069: import org.openide.util.test.MockPropertyChangeListener;
070:
071: /**
072: * Test functionality of PropertyUtils.
073: * @author Jesse Glick
074: */
075: public class PropertyUtilsTest extends NbTestCase {
076:
077: public PropertyUtilsTest(String name) {
078: super (name);
079: }
080:
081: public void run(final TestResult result) {
082: ProjectManager.mutex().writeAccess(new Mutex.Action<Void>() {
083: public Void run() {
084: PropertyUtilsTest.super .run(result);
085: return null;
086: }
087: });
088: }
089:
090: private static PropertyEvaluator evaluator(
091: Map<String, String> predefs, List<Map<String, String>> defs) {
092: PropertyProvider[] mainProviders = new PropertyProvider[defs
093: .size()];
094: int i = 0;
095: for (Map<String, String> def : defs) {
096: mainProviders[i++] = PropertyUtils
097: .fixedPropertyProvider(def);
098: }
099: return PropertyUtils.sequentialPropertyEvaluator(PropertyUtils
100: .fixedPropertyProvider(predefs), mainProviders);
101: }
102:
103: private static String evaluate(String prop,
104: Map<String, String> predefs, List<Map<String, String>> defs) {
105: return evaluator(predefs, defs).getProperty(prop);
106: }
107:
108: private static Map<String, String> evaluateAll(
109: Map<String, String> predefs, List<Map<String, String>> defs) {
110: return evaluator(predefs, defs).getProperties();
111: }
112:
113: private static String evaluateString(String text,
114: Map<String, String> predefs, List<Map<String, String>> defs) {
115: return evaluator(predefs, defs).evaluate(text);
116: }
117:
118: public void testEvaluate() throws Exception {
119: // XXX check override order, property name evaluation, $$ escaping, bare or final $,
120: // cyclic errors, undef'd property substitution, no substs in predefs, etc.
121: Map<String, String> m1 = Collections.singletonMap("y", "val");
122: Map<String, String> m2 = new HashMap<String, String>();
123: m2.put("x", "${y}");
124: m2.put("y", "y-${x}");
125: List<Map<String, String>> m1m2 = new ArrayList<Map<String, String>>();
126: m1m2.add(m1);
127: m1m2.add(m2);
128: assertEquals("x evaluates to former y", "val", evaluate("x",
129: Collections.<String, String> emptyMap(), m1m2));
130: assertEquals("first y defines it", "val", evaluate("y",
131: Collections.<String, String> emptyMap(), m1m2));
132: assertEquals("circularity error", null, evaluate("x",
133: Collections.<String, String> emptyMap(), Collections
134: .singletonList(m2)));
135: assertEquals("circularity error", null, evaluate("y",
136: Collections.<String, String> emptyMap(), Collections
137: .singletonList(m2)));
138: m2.clear();
139: m2.put("y", "yval_${z}");
140: m2.put("x", "xval_${y}");
141: m2.put("z", "zval");
142: Map<String, String> all = evaluateAll(Collections
143: .<String, String> emptyMap(), Collections
144: .singletonList(m2));
145: assertNotNull("no circularity error", all);
146: assertEquals("have three properties", 3, all.size());
147: assertEquals("double substitution", "xval_yval_zval", all
148: .get("x"));
149: assertEquals("single substitution", "yval_zval", all.get("y"));
150: assertEquals("no substitution", "zval", all.get("z"));
151: // Yuck. But it failed once, so check it now.
152: Properties p = new Properties();
153: p
154: .load(new ByteArrayInputStream(
155: "project.mylib=../mylib\njavac.classpath=${project.mylib}/build/mylib.jar\nrun.classpath=${javac.classpath}:build/classes"
156: .getBytes("US-ASCII")));
157: all = evaluateAll(Collections.<String, String> emptyMap(),
158: Collections.singletonList(NbCollections
159: .checkedMapByFilter(p, String.class,
160: String.class, true)));
161: assertNotNull("no circularity error", all);
162: assertEquals("javac.classpath correctly substituted",
163: "../mylib/build/mylib.jar", all.get("javac.classpath"));
164: assertEquals("run.classpath correctly substituted",
165: "../mylib/build/mylib.jar:build/classes", all
166: .get("run.classpath"));
167: }
168:
169: public void testTokenizePath() throws Exception {
170: assertEquals("basic tokenization works on ':'", Arrays
171: .asList(new String[] { "foo", "bar" }), Arrays
172: .asList(PropertyUtils.tokenizePath("foo:bar")));
173: assertEquals("basic tokenization works on ';'", Arrays
174: .asList(new String[] { "foo", "bar" }), Arrays
175: .asList(PropertyUtils.tokenizePath("foo;bar")));
176: assertEquals("Unix paths work", Arrays.asList(new String[] {
177: "/foo/bar", "baz/quux" }), Arrays.asList(PropertyUtils
178: .tokenizePath("/foo/bar:baz/quux")));
179: assertEquals("empty components are stripped with ':'", Arrays
180: .asList(new String[] { "foo", "bar" }), Arrays
181: .asList(PropertyUtils.tokenizePath(":foo::bar:")));
182: assertEquals("empty components are stripped with ';'", Arrays
183: .asList(new String[] { "foo", "bar" }), Arrays
184: .asList(PropertyUtils.tokenizePath(";foo;;bar;")));
185: assertEquals("DOS paths are recognized with ';'", Arrays
186: .asList(new String[] { "c:\\foo", "D:\\\\bar" }),
187: Arrays.asList(PropertyUtils
188: .tokenizePath("c:\\foo;D:\\\\bar")));
189: assertEquals("DOS paths are recognized with ':'", Arrays
190: .asList(new String[] { "c:\\foo", "D:\\\\bar" }),
191: Arrays.asList(PropertyUtils
192: .tokenizePath("c:\\foo:D:\\\\bar")));
193: assertEquals("a..z can be drive letters", Arrays
194: .asList(new String[] { "a:\\foo", "z:\\\\bar" }),
195: Arrays.asList(PropertyUtils
196: .tokenizePath("a:\\foo:z:\\\\bar")));
197: assertEquals("A..Z can be drive letters", Arrays
198: .asList(new String[] { "A:\\foo", "Z:\\\\bar" }),
199: Arrays.asList(PropertyUtils
200: .tokenizePath("A:\\foo:Z:\\\\bar")));
201: assertEquals("non-letters are not drives with ';'", Arrays
202: .asList(new String[] { "1", "\\foo", "D:\\\\bar" }),
203: Arrays.asList(PropertyUtils
204: .tokenizePath("1;\\foo;D:\\\\bar")));
205: assertEquals("non-letters are not drives with ':'", Arrays
206: .asList(new String[] { "1", "\\foo", "D:\\\\bar" }),
207: Arrays.asList(PropertyUtils
208: .tokenizePath("1:\\foo:D:\\\\bar")));
209: assertEquals(">1 letters are not drives with ';'", Arrays
210: .asList(new String[] { "ab", "\\foo", "D:\\\\bar" }),
211: Arrays.asList(PropertyUtils
212: .tokenizePath("ab;\\foo;D:\\\\bar")));
213: assertEquals(">1 letters are not drives with ':'", Arrays
214: .asList(new String[] { "ab", "\\foo", "D:\\\\bar" }),
215: Arrays.asList(PropertyUtils
216: .tokenizePath("ab:\\foo:D:\\\\bar")));
217: assertEquals("drives use ':'", Arrays.asList(new String[] {
218: "c", "\\foo", "D:\\\\bar" }),
219: Arrays.asList(PropertyUtils
220: .tokenizePath("c;\\foo;D:\\\\bar")));
221: assertEquals("drives use only one ':'", Arrays
222: .asList(new String[] { "c", "\\foo", "D:\\\\bar" }),
223: Arrays.asList(PropertyUtils
224: .tokenizePath("c::\\foo;D:\\\\bar")));
225: assertEquals("drives use only one drive letter", Arrays
226: .asList(new String[] { "c", "c:\\foo", "D:\\\\bar" }),
227: Arrays.asList(PropertyUtils
228: .tokenizePath("c:c:\\foo;D:\\\\bar")));
229: assertEquals("DOS paths start with '\\'", Arrays
230: .asList(new String[] { "c", "foo", "D:\\\\bar" }),
231: Arrays.asList(PropertyUtils
232: .tokenizePath("c:foo;D:\\\\bar")));
233: assertEquals("DOS paths start with '/'",
234: Arrays.asList(new String[] { "c", "/foo", "D:/bar",
235: "/path" }), Arrays.asList(PropertyUtils
236: .tokenizePath("c;/foo;D:/bar:/path")));
237: assertEquals("empty path handled", Collections.EMPTY_LIST,
238: Arrays.asList(PropertyUtils.tokenizePath("")));
239: assertEquals("effectively empty path handled",
240: Collections.EMPTY_LIST, Arrays.asList(PropertyUtils
241: .tokenizePath(":;:;")));
242: assertEquals(
243: "one letter directories handled",
244: Arrays.asList(new String[] { "c:/foo/c", "/foo/c/bar",
245: "c", "/foo/c", "/bar" }),
246: Arrays
247: .asList(PropertyUtils
248: .tokenizePath("c:/foo/c;/foo/c/bar;c;/foo/c:/bar")));
249: assertEquals("one letter directories handled2", Arrays
250: .asList(new String[] { "c" }), Arrays
251: .asList(PropertyUtils.tokenizePath("c")));
252: }
253:
254: public void testRelativizeFile() throws Exception {
255: clearWorkDir();
256: File tmp = getWorkDir();
257: File d1 = new File(tmp, "d1");
258: File d1f = new File(d1, "f");
259: File d1s = new File(d1, "s p a c e");
260: File d1sf = new File(d1s, "f");
261: File d2 = new File(tmp, "d2");
262: File d2f = new File(d2, "f");
263: // Note that "/tmp/d11".startsWith("/tmp/d1"), hence this being interesting:
264: File d11 = new File(tmp, "d11");
265: // Note: none of these dirs/files exist yet.
266: assertEquals("d1f from d1", "f", PropertyUtils.relativizeFile(
267: d1, d1f));
268: assertEquals("d1 from d1f", "..", PropertyUtils.relativizeFile(
269: d1f, d1)); // #61687
270: assertEquals("d2f from d1", "../d2/f", PropertyUtils
271: .relativizeFile(d1, d2f));
272: assertEquals("d1 from d1", ".", PropertyUtils.relativizeFile(
273: d1, d1));
274: assertEquals("d2 from d1", "../d2", PropertyUtils
275: .relativizeFile(d1, d2));
276: assertEquals("d1s from d1", "s p a c e", PropertyUtils
277: .relativizeFile(d1, d1s));
278: assertEquals("d1sf from d1", "s p a c e/f", PropertyUtils
279: .relativizeFile(d1, d1sf));
280: assertEquals("d11 from d1", "../d11", PropertyUtils
281: .relativizeFile(d1, d11));
282: // Now make them and check that the results are the same.
283: assertTrue("made d1s", d1s.mkdirs());
284: assertTrue("made d1f", d1f.createNewFile());
285: assertTrue("made d1sf", d1sf.createNewFile());
286: assertTrue("made d2", d2.mkdirs());
287: assertTrue("made d2f", d2f.createNewFile());
288: assertEquals("existing d1f from d1", "f", PropertyUtils
289: .relativizeFile(d1, d1f));
290: assertEquals("existing d2f from d1", "../d2/f", PropertyUtils
291: .relativizeFile(d1, d2f));
292: assertEquals("existing d1 from d1", ".", PropertyUtils
293: .relativizeFile(d1, d1));
294: assertEquals("existing d2 from d1", "../d2", PropertyUtils
295: .relativizeFile(d1, d2));
296: assertEquals("existing d1s from d1", "s p a c e", PropertyUtils
297: .relativizeFile(d1, d1s));
298: assertEquals("existing d1sf from d1", "s p a c e/f",
299: PropertyUtils.relativizeFile(d1, d1sf));
300: assertEquals("existing d11 from d1", "../d11", PropertyUtils
301: .relativizeFile(d1, d11));
302: // XXX: the below code should pass on Unix too I guess.
303: if (Utilities.isWindows()) {
304: // test Windows drives:
305: File f1 = new File("C:\\folder\\one");
306: File f2 = new File("D:\\t e m p\\two");
307: assertNull("different drives cannot be relative",
308: PropertyUtils.relativizeFile(f1, f2));
309: f1 = new File("D:\\folder\\one");
310: f2 = new File("D:\\t e m p\\two");
311: assertEquals(
312: "relativization failed for Windows absolute paths",
313: "../../t e m p/two", PropertyUtils.relativizeFile(
314: f1, f2));
315: }
316: }
317:
318: public void testGlobalProperties() throws Exception {
319: clearWorkDir();
320: System.setProperty("netbeans.user", getWorkDir()
321: .getAbsolutePath());
322: File ubp = new File(getWorkDir(), "build.properties");
323: assertFalse("no build.properties yet", ubp.exists());
324: assertEquals("no properties to start", Collections.EMPTY_MAP,
325: PropertyUtils.getGlobalProperties());
326: EditableProperties p = new EditableProperties();
327: p.setProperty("key1", "val1");
328: p.setProperty("key2", "val2");
329: PropertyUtils.putGlobalProperties(p);
330: assertTrue("now have build.properties", ubp.isFile());
331: p = PropertyUtils.getGlobalProperties();
332: assertEquals("two definitions now", 2, p.size());
333: assertEquals("key1 correct", "val1", p.getProperty("key1"));
334: assertEquals("key2 correct", "val2", p.getProperty("key2"));
335: Properties p2 = new Properties();
336: InputStream is = new FileInputStream(ubp);
337: try {
338: p2.load(is);
339: } finally {
340: is.close();
341: }
342: assertEquals("two definitions now from disk", 2, p2.size());
343: assertEquals("key1 correct from disk", "val1", p2
344: .getProperty("key1"));
345: assertEquals("key2 correct from disk", "val2", p2
346: .getProperty("key2"));
347: // Test the property provider too.
348: PropertyProvider gpp = PropertyUtils.globalPropertyProvider();
349: MockChangeListener l = new MockChangeListener();
350: gpp.addChangeListener(l);
351: p = PropertyUtils.getGlobalProperties();
352: assertEquals("correct initial definitions", p, gpp
353: .getProperties());
354: p.setProperty("key3", "val3");
355: assertEquals("still have 2 defs", 2, gpp.getProperties().size());
356: l.assertNoEvents();
357: PropertyUtils.putGlobalProperties(p);
358: l.assertEvent();
359: assertEquals("now have 3 defs", 3, gpp.getProperties().size());
360: assertEquals("right val", "val3", gpp.getProperties().get(
361: "key3"));
362: l.msg("no spurious changes").assertNoEvents();
363: // Test changes made using Filesystems API.
364: p.setProperty("key1", "val1a");
365: FileObject fo = FileUtil.toFileObject(ubp);
366: assertNotNull("there is USER_BUILD_PROPERTIES on disk", fo);
367: FileLock lock = fo.lock();
368: OutputStream os = fo.getOutputStream(lock);
369: p.store(os);
370: os.close();
371: lock.releaseLock();
372: l.msg("got a change from the Filesystems API").assertEvent();
373: assertEquals("still have 3 defs", 3, gpp.getProperties().size());
374: assertEquals("right val for key1", "val1a", gpp.getProperties()
375: .get("key1"));
376: // XXX changes made on disk are not picked up... bad test, or something else?
377: /*
378: Thread.sleep(1000);
379: p.setProperty("key2", "val2a");
380: OutputStream os = new FileOutputStream(ubp);
381: p.store(os);
382: os.close();
383: FileUtil.toFileObject(ubp).getFileSystem().refresh(false);
384: Thread.sleep(1000);
385: assertTrue("got a change from disk", l.expect());
386: assertEquals("still have 3 defs", 3, gpp.getProperties().size());
387: assertEquals("right val for key2", "val2a", gpp.getProperties().get("key2"));
388: */
389: }
390:
391: public void testEvaluateString() throws Exception {
392: Map<String, String> predefs = new HashMap<String, String>();
393: predefs.put("homedir", "/home/me");
394: Map<String, String> defs1 = new HashMap<String, String>();
395: defs1.put("outdirname", "foo");
396: defs1.put("outdir", "${homedir}/${outdirname}");
397: Map<String, String> defs2 = new HashMap<String, String>();
398: defs2.put("outdir2", "${outdir}/subdir");
399: List<Map<String, String>> defs12 = new ArrayList<Map<String, String>>();
400: defs12.add(defs1);
401: defs12.add(defs2);
402: assertEquals("correct evaluated string",
403: "/home/me/foo/subdir is in /home/me", evaluateString(
404: "${outdir2} is in ${homedir}", predefs, defs12));
405: }
406:
407: public void testFixedPropertyProvider() throws Exception {
408: Map<String, String> defs = new HashMap<String, String>();
409: defs.put("key1", "val1");
410: defs.put("key2", "val2");
411: PropertyProvider pp = PropertyUtils.fixedPropertyProvider(defs);
412: assertEquals(defs, pp.getProperties());
413: }
414:
415: public void testPropertiesFilePropertyProvider() throws Exception {
416: clearWorkDir();
417: final FileObject scratch = FileUtil.toFileObject(getWorkDir());
418: PropertyProvider pp = PropertyUtils
419: .propertiesFilePropertyProvider(new File(FileUtil
420: .toFile(scratch), "test.properties"));
421: MockChangeListener l = new MockChangeListener();
422: pp.addChangeListener(l);
423: assertEquals("no defs yet (no file)", Collections.EMPTY_MAP, pp
424: .getProperties());
425: l.assertNoEvents();
426: final FileObject[] testProperties = new FileObject[1];
427: scratch.getFileSystem().runAtomicAction(
428: new FileSystem.AtomicAction() {
429: public void run() throws IOException {
430: testProperties[0] = FileUtil.createData(
431: scratch, "test.properties");
432: FileLock lock = testProperties[0].lock();
433: try {
434: OutputStream os = testProperties[0]
435: .getOutputStream(lock);
436: try {
437:
438: PrintWriter pw = new PrintWriter(os);
439: pw.println("a=aval");
440: pw.flush();
441: } finally {
442: os.close();
443: }
444: } finally {
445: lock.releaseLock();
446: }
447: }
448: });
449: l.msg("got a change when file was created").assertEvent();
450: assertEquals("one key", Collections.singletonMap("a", "aval"),
451: pp.getProperties());
452: FileLock lock = testProperties[0].lock();
453: try {
454: OutputStream os = testProperties[0].getOutputStream(lock);
455: try {
456: PrintWriter pw = new PrintWriter(os);
457: pw.println("a=aval");
458: pw.println("b=bval");
459: pw.flush();
460: } finally {
461: os.close();
462: }
463: } finally {
464: lock.releaseLock();
465: }
466: Map<String, String> m = new HashMap<String, String>();
467: m.put("a", "aval");
468: m.put("b", "bval");
469: l.msg("got a change when file was changed").assertEvent();
470: assertEquals("right properties", m, pp.getProperties());
471: testProperties[0].delete();
472: l.msg("got a change when file was deleted").assertEvent();
473: assertEquals("no defs again (file deleted)", Collections
474: .emptyMap(), pp.getProperties());
475: }
476:
477: public void testSequentialEvaluatorBasic() throws Exception {
478: Map<String, String> defs1 = new HashMap<String, String>();
479: defs1.put("key1", "val1");
480: defs1.put("key2", "val2");
481: defs1.put("key5", "5=${key1}");
482: defs1.put("key6", "6=${key3}");
483: Map<String, String> defs2 = new HashMap<String, String>();
484: defs2.put("key3", "val3");
485: defs2.put("key4", "4=${key1}:${key3}");
486: defs2.put("key7", "7=${undef}");
487: PropertyEvaluator eval = PropertyUtils
488: .sequentialPropertyEvaluator(null, PropertyUtils
489: .fixedPropertyProvider(defs1), PropertyUtils
490: .fixedPropertyProvider(defs2));
491: String[] vals = { "val1", "val2", "val3", "4=val1:val3",
492: "5=val1", "6=${key3}", "7=${undef}", };
493: Map<String, String> all = eval.getProperties();
494: assertEquals("right # of props", vals.length, all.size());
495: for (int i = 1; i <= vals.length; i++) {
496: assertEquals("key" + i + " is correct", vals[i - 1], eval
497: .getProperty("key" + i));
498: assertEquals("key" + i + " is correct in all properties",
499: vals[i - 1], all.get("key" + i));
500: }
501: assertEquals("evaluate works", "5=val1 x ${undef}", eval
502: .evaluate("${key5} x ${undef}"));
503: // And test the preprovider...
504: Map<String, String> predefs = Collections.singletonMap("key3",
505: "preval3");
506: eval = PropertyUtils.sequentialPropertyEvaluator(PropertyUtils
507: .fixedPropertyProvider(predefs), PropertyUtils
508: .fixedPropertyProvider(defs1), PropertyUtils
509: .fixedPropertyProvider(defs2));
510: vals = new String[] { "val1", "val2", "preval3",
511: "4=val1:preval3", "5=val1", "6=preval3", "7=${undef}", };
512: all = eval.getProperties();
513: assertEquals("right # of props", vals.length, all.size());
514: for (int i = 1; i <= vals.length; i++) {
515: assertEquals("key" + i + " is correct", vals[i - 1], eval
516: .getProperty("key" + i));
517: assertEquals("key" + i + " is correct in all properties",
518: vals[i - 1], all.get("key" + i));
519: }
520: assertEquals("evaluate works",
521: "4=val1:preval3 x ${undef} x preval3", eval
522: .evaluate("${key4} x ${undef} x ${key3}"));
523: }
524:
525: public void testSequentialEvaluatorChanges() throws Exception {
526: AntBasedTestUtil.TestMutablePropertyProvider predefs = new AntBasedTestUtil.TestMutablePropertyProvider(
527: new HashMap<String, String>());
528: AntBasedTestUtil.TestMutablePropertyProvider defs1 = new AntBasedTestUtil.TestMutablePropertyProvider(
529: new HashMap<String, String>());
530: AntBasedTestUtil.TestMutablePropertyProvider defs2 = new AntBasedTestUtil.TestMutablePropertyProvider(
531: new HashMap<String, String>());
532: predefs.defs.put("x", "xval1");
533: predefs.defs.put("y", "yval1");
534: defs1.defs.put("a", "aval1");
535: defs1.defs.put("b", "bval1=${x}");
536: defs1.defs.put("c", "cval1=${z}");
537: defs2.defs.put("m", "mval1");
538: defs2.defs.put("n", "nval1=${x}:${b}");
539: defs2.defs.put("o", "oval1=${z}");
540: PropertyEvaluator eval = PropertyUtils
541: .sequentialPropertyEvaluator(predefs, defs1, defs2);
542: MockPropertyChangeListener l = new MockPropertyChangeListener();
543: eval.addPropertyChangeListener(l);
544: Map<String, String> result = new HashMap<String, String>();
545: result.put("x", "xval1");
546: result.put("y", "yval1");
547: result.put("a", "aval1");
548: result.put("b", "bval1=xval1");
549: result.put("c", "cval1=${z}");
550: result.put("m", "mval1");
551: result.put("n", "nval1=xval1:bval1=xval1");
552: result.put("o", "oval1=${z}");
553: assertEquals("correct initial vals", result, eval
554: .getProperties());
555: l.assertEvents();
556: // Change predefs.
557: predefs.defs.put("x", "xval2");
558: predefs.mutated();
559: Map<String, String> oldvals = new HashMap<String, String>();
560: oldvals.put("x", result.get("x"));
561: oldvals.put("b", result.get("b"));
562: oldvals.put("n", result.get("n"));
563: Map<String, String> newvals = new HashMap<String, String>();
564: newvals.put("x", "xval2");
565: newvals.put("b", "bval1=xval2");
566: newvals.put("n", "nval1=xval2:bval1=xval2");
567: result.putAll(newvals);
568: l.assertEventsAndValues(oldvals, newvals);
569: assertEquals("right total values now", result, eval
570: .getProperties());
571: // Change some other defs.
572: defs1.defs.put("z", "zval1");
573: defs1.defs.remove("b");
574: defs1.mutated();
575: defs2.defs.put("m", "mval2");
576: defs2.mutated();
577: oldvals.clear();
578: oldvals.put("b", result.get("b"));
579: oldvals.put("c", result.get("c"));
580: oldvals.put("m", result.get("m"));
581: oldvals.put("n", result.get("n"));
582: oldvals.put("o", result.get("o"));
583: oldvals.put("z", result.get("z"));
584: newvals.clear();
585: newvals.put("b", null);
586: newvals.put("c", "cval1=zval1");
587: newvals.put("m", "mval2");
588: newvals.put("n", "nval1=xval2:${b}");
589: newvals.put("o", "oval1=zval1");
590: newvals.put("z", "zval1");
591: result.putAll(newvals);
592: result.remove("b");
593: l.assertEventsAndValues(oldvals, newvals);
594: assertEquals("right total values now", result, eval
595: .getProperties());
596: }
597:
598: private static final String ILLEGAL_CHARS = " !\"#$%&'()*+,/:;<=>?@[\\]^`{|}~";
599:
600: public void testIsUsablePropertyName() throws Exception {
601: for (int i = 0; i < ILLEGAL_CHARS.length(); i++) {
602: String s = ILLEGAL_CHARS.substring(i, i + 1);
603: assertFalse("Not a valid property name: " + s,
604: PropertyUtils.isUsablePropertyName(s));
605: }
606: for (int i = 127; i < 256; i++) {
607: String s = "" + (char) i;
608: assertFalse("Not a valid property name: " + s + " - " + i,
609: PropertyUtils.isUsablePropertyName(s));
610: }
611: assertFalse("Not a valid property name", PropertyUtils
612: .isUsablePropertyName(ILLEGAL_CHARS));
613: for (int i = 32; i < 127; i++) {
614: String s = "" + (char) i;
615: if (ILLEGAL_CHARS.indexOf((char) i) == -1) {
616: assertTrue("Valid property name: " + s, PropertyUtils
617: .isUsablePropertyName(s));
618: }
619: }
620: assertTrue("Valid property name: java.classpath", PropertyUtils
621: .isUsablePropertyName("java.classpath"));
622: assertFalse("Invalid property name: java#classpath",
623: PropertyUtils.isUsablePropertyName("java#classpath"));
624: assertFalse("Blank name is not valid property name",
625: PropertyUtils.isUsablePropertyName(""));
626: }
627:
628: public void testGetUsablePropertyName() throws Exception {
629: StringBuffer bad = new StringBuffer();
630: StringBuffer good = new StringBuffer();
631: for (int i = 0; i < ILLEGAL_CHARS.length(); i++) {
632: bad.append(ILLEGAL_CHARS.substring(i, i + 1));
633: bad.append("x");
634: good.append("_");
635: good.append("x");
636: }
637: assertEquals("Corrected property name does match", good
638: .toString(), PropertyUtils.getUsablePropertyName(bad
639: .toString()));
640: }
641:
642: public void testSequentialPropertyEvaluatorStringAllocation()
643: throws Exception {
644: // #48449: too many String instances.
645: // String constants used in the test are interned; make sure the results are the same.
646: // Not necessary for the provider to intern strings, just to not copy them.
647: Map<String, String> defs = new HashMap<String, String>();
648: defs.put("pre-a", "pre-a-val");
649: defs.put("pre-b", "pre-b-val");
650: PropertyProvider preprovider = PropertyUtils
651: .fixedPropertyProvider(defs);
652: defs = new HashMap<String, String>();
653: defs.put("main-1-a", "main-1-a-val");
654: defs.put("main-1-b", "main-1-b-val+${pre-b}");
655: PropertyProvider provider1 = PropertyUtils
656: .fixedPropertyProvider(defs);
657: defs = new HashMap<String, String>();
658: defs.put("main-2-a", "main-2-a-val");
659: defs.put("main-2-b", "main-2-b-val+${main-1-b}");
660: PropertyProvider provider2 = PropertyUtils
661: .fixedPropertyProvider(defs);
662: PropertyEvaluator pp = PropertyUtils
663: .sequentialPropertyEvaluator(preprovider, provider1,
664: provider2);
665: defs = pp.getProperties();
666: assertSame("uncopied pre-a", "pre-a-val", defs.get("pre-a"));
667: assertSame("uncopied pre-b", "pre-b-val", defs.get("pre-b"));
668: assertSame("uncopied main-1-a", "main-1-a-val", defs
669: .get("main-1-a"));
670: assertEquals("right main-1-b", "main-1-b-val+pre-b-val", defs
671: .get("main-1-b"));
672: assertSame("uncopied main-2-a", "main-2-a-val", defs
673: .get("main-2-a"));
674: assertEquals("right main-2-b",
675: "main-2-b-val+main-1-b-val+pre-b-val", defs
676: .get("main-2-b"));
677: }
678:
679: }
|