KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > spi > project > support > ant > AntProjectHelperTest


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.spi.project.support.ant;
21
22 import java.io.File JavaDoc;
23 import java.io.FileOutputStream JavaDoc;
24 import java.io.OutputStream JavaDoc;
25 import java.util.Arrays JavaDoc;
26 import java.util.Collections JavaDoc;
27 import java.util.HashSet JavaDoc;
28 import java.util.Map JavaDoc;
29 import java.util.Properties JavaDoc;
30 import org.netbeans.api.project.Project;
31 import org.netbeans.api.project.ProjectManager;
32 import org.netbeans.api.project.ProjectUtils;
33 import org.netbeans.api.project.TestUtil;
34 import org.netbeans.junit.NbTestCase;
35 import org.netbeans.modules.project.ant.Util;
36 import org.netbeans.spi.project.AuxiliaryConfiguration;
37 import org.netbeans.spi.project.CacheDirectoryProvider;
38 import org.openide.filesystems.FileLock;
39 import org.openide.filesystems.FileObject;
40 import org.openide.filesystems.FileUtil;
41 import org.openide.util.Mutex;
42 import org.openide.xml.XMLUtil;
43 import org.w3c.dom.Document JavaDoc;
44 import org.w3c.dom.Element JavaDoc;
45 import org.w3c.dom.Node JavaDoc;
46 import org.w3c.dom.NodeList JavaDoc;
47
48 /* XXX tests needed:
49  * - testProjectXmlSavedException
50  * try throwing an exception from PXSH.pXS and check that next save is OK
51  * need to delete: assert !modifiedMetadataPaths.isEmpty();
52  * - testMalformedConfigDataProducesLoadException
53  * make a project with broken XML files and check that it does not load
54  * - testCleanCheckout
55  * make sure loading proceeds naturally with a clean checkout, i.e. no nbproject/private/ dir
56  * and that appropriate private.xml and private.properties files are created on demand
57  * (this is perhaps already tested adequately by ProjectGeneratorTest)
58  * - testVCSFriendliness
59  * make various modifications to project/private.xml files and ensure that the
60  * number of lines changed in the diff is kept to a minimum
61  * - testIsProject
62  */

63
64 /**
65  * Test functionality of AntProjectHelper and AntBasedProjectFactorySingleton.
66  * @author Jesse Glick
67  */

68 public class AntProjectHelperTest extends NbTestCase {
69
70     /**
71      * Create test suite.
72      * @param name suite name
73      */

74     public AntProjectHelperTest(String JavaDoc name) {
75         super(name);
76     }
77     
78     private FileObject scratch;
79     private FileObject projdir;
80     private ProjectManager pm;
81     private Project p;
82     private AntProjectHelper h;
83     private AntBasedTestUtil.TestListener l;
84     
85     protected void setUp() throws Exception JavaDoc {
86         super.setUp();
87         scratch = TestUtil.makeScratchDir(this);
88         projdir = scratch.createFolder("proj");
89         TestUtil.createFileFromContent(AntProjectHelperTest.class.getResource("data/project.xml"), projdir, "nbproject/project.xml");
90         TestUtil.createFileFromContent(AntProjectHelperTest.class.getResource("data/private.xml"), projdir, "nbproject/private/private.xml");
91         TestUtil.createFileFromContent(AntProjectHelperTest.class.getResource("data/project.properties"), projdir, "nbproject/project.properties");
92         TestUtil.createFileFromContent(AntProjectHelperTest.class.getResource("data/private.properties"), projdir, "nbproject/private/private.properties");
93         TestUtil.createFileFromContent(AntProjectHelperTest.class.getResource("data/global.properties"), scratch, "userdir/build.properties");
94         TestUtil.setLookup(new Object JavaDoc[] {
95             AntBasedTestUtil.testAntBasedProjectType(),
96         });
97         pm = ProjectManager.getDefault();
98         p = pm.findProject(projdir);
99         h = p.getLookup().lookup(AntProjectHelper.class);
100         l = new AntBasedTestUtil.TestListener();
101     }
102     
103     /**
104      * Test that Ant-based projects are at least recognized as such.
105      * @throws Exception if anything unexpected happens
106      */

107     public void testBasicRecognition() throws Exception JavaDoc {
108         assertNotNull("recognized the project", p);
109         assertEquals("correct project directory", projdir, p.getProjectDirectory());
110         assertEquals("found something in project lookup", "hello", p.getLookup().lookup(String JavaDoc.class));
111     }
112     
113     /**
114      * Test that it is possible to retrieve the main data from project.xml and private.xml.
115      * @throws Exception if anything unexpected happens
116      */

117     public void testGetPrimaryConfigurationData() throws Exception JavaDoc {
118         assertNotNull("Had helper in lookup", h);
119         Element JavaDoc data = h.getPrimaryConfigurationData(true);
120         assertEquals("correct element name", "data", data.getLocalName());
121         assertEquals("correct element namespace", "urn:test:shared", data.getNamespaceURI());
122         Element JavaDoc stuff = Util.findElement(data, "shared-stuff", "urn:test:shared");
123         assertNotNull("had nested stuff in it", stuff);
124         data = h.getPrimaryConfigurationData(false);
125         assertEquals("correct element name", "data", data.getLocalName());
126         assertEquals("correct element namespace", "urn:test:private", data.getNamespaceURI());
127         stuff = Util.findElement(data, "private-stuff", "urn:test:private");
128         assertNotNull("had nested stuff in it", stuff);
129     }
130     
131     /**
132      * Test error recovery from malformed project.xml
133      * @see "#46048"
134      */

135     public void testBrokenPrimaryConfigurationData() throws Exception JavaDoc {
136         // Make an empty, thus invalid, project.xml:
137
TestUtil.createFileFromContent(null, projdir, AntProjectHelper.PROJECT_XML_PATH);
138         AntProjectHelper.QUIETLY_SWALLOW_XML_LOAD_ERRORS = true;
139         Element JavaDoc data;
140         try {
141             data = h.getPrimaryConfigurationData(true);
142         } finally {
143             AntProjectHelper.QUIETLY_SWALLOW_XML_LOAD_ERRORS = false;
144         }
145         assertEquals("correct element name", "data", data.getLocalName());
146         assertEquals("correct element namespace", "urn:test:shared", data.getNamespaceURI());
147         Element JavaDoc stuff = Util.findElement(data, "shared-stuff", "urn:test:shared");
148         assertNull("had no stuff in it", stuff);
149         // Make sure a subsequent save proceeds normally too:
150
data = XMLUtil.createDocument("whatever", "urn:test:shared", null, null).createElementNS("urn:test:shared", "data");
151         data.appendChild(data.getOwnerDocument().createElementNS("urn:test:shared", "details"));
152         h.putPrimaryConfigurationData(data, true);
153         pm.saveProject(p);
154         Document JavaDoc doc = AntBasedTestUtil.slurpXml(h, AntProjectHelper.PROJECT_XML_PATH);
155         Element JavaDoc root = doc.getDocumentElement();
156         Element JavaDoc type = Util.findElement(root, "type", AntProjectHelper.PROJECT_NS);
157         assertEquals("correct restored type", "test", Util.findText(type));
158         Element JavaDoc config = Util.findElement(root, "configuration", AntProjectHelper.PROJECT_NS);
159         assertNotNull("have <configuration>", config);
160         data = Util.findElement(config, "data", "urn:test:shared");
161         assertNotNull("have <data>", data);
162         Element JavaDoc details = Util.findElement(data, "details", "urn:test:shared");
163         assertNotNull("have <details>", details);
164     }
165     
166     /**
167      * Test that after retrieving XML config data, you can't mess up other internal stuff.
168      * @throws Exception if anything unexpected happens
169      */

170     public void testImmutabilityOfGottenConfigurationData() throws Exception JavaDoc {
171         Element JavaDoc data = h.getPrimaryConfigurationData(true);
172         assertNull("no parent for data", data.getParentNode());
173         // XXX assure that modifications to data have no effect on a subsequent call
174
// XXX get the ownerDocument and assure that the tree cannot be modified using it
175
}
176     
177     /**
178      * Test that it is possible to load properties from .properties files.
179      * @throws Exception if anything unexpected happens
180      */

181     public void testGetProperties() throws Exception JavaDoc {
182         EditableProperties ep = h.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
183         assertNotNull("getProperties should never return null", ep);
184         assertEquals("three properties defined", 3, ep.size());
185         assertEquals("shared.prop correct", "value1", ep.get("shared.prop"));
186         assertEquals("overridden.prop correct", "value3", ep.get("overridden.prop"));
187         ep = h.getProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH);
188         assertNotNull("getProperties should never return null", ep);
189         assertEquals("four properties defined", 4, ep.size());
190         assertEquals("private.prop correct", "value2", ep.get("private.prop"));
191         assertEquals("overridden.prop correct", "value4", ep.get("overridden.prop"));
192         ep = h.getProperties("bogus/path.properties");
193         assertNotNull("getProperties should never return null", ep);
194         assertEquals("no properties defined", 0, ep.size());
195     }
196     
197     /**
198      * Test that Ant properties can be evaluated with proper (recursive) substitutions.
199      * @throws Exception if anything unexpected happens
200      */

201     public void testStandardPropertyEvaluator() throws Exception JavaDoc {
202         // Make sure any callbacks happen inside a lock, so changes are not posted asynch:
203
ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction<Void JavaDoc>() {
204             public Void JavaDoc run() throws Exception JavaDoc {
205         PropertyEvaluator pev = h.getStandardPropertyEvaluator();
206         assertEquals("shared.prop correct", "value1", pev.getProperty("shared.prop"));
207         assertEquals("private.prop correct", "value2", pev.getProperty("private.prop"));
208         assertEquals("overridden.prop correct", "value4", pev.getProperty("overridden.prop"));
209         assertEquals("derived.prop correct", "value2:value1:${undefined.prop}", pev.getProperty("derived.prop"));
210         assertEquals("tempdir correct", System.getProperty("java.io.tmpdir") + "/foo", pev.getProperty("tempdir"));
211         assertEquals("global.prop correct", "value5", pev.getProperty("global.prop"));
212         assertEquals("does not have other defs", null, pev.getProperty("bogus.prop"));
213         Map JavaDoc m = pev.getProperties();
214         assertEquals("shared.prop correct", "value1", m.get("shared.prop"));
215         assertEquals("private.prop correct", "value2", m.get("private.prop"));
216         assertEquals("overridden.prop correct", "value4", m.get("overridden.prop"));
217         assertEquals("derived.prop correct", "value2:value1:${undefined.prop}", m.get("derived.prop"));
218         assertEquals("tempdir correct", System.getProperty("java.io.tmpdir") + "/foo", m.get("tempdir"));
219         assertEquals("global.prop correct", "value5", m.get("global.prop"));
220         assertEquals("does not have other defs", null, m.get("bogus.prop"));
221         assertEquals("correct evaluateString", "value1:value2",
222             pev.evaluate("${shared.prop}:${private.prop}"));
223         // #44213: try modifying build.properties.
224
AntBasedTestUtil.TestPCL l = new AntBasedTestUtil.TestPCL();
225         pev.addPropertyChangeListener(l);
226         FileObject buildProperties = scratch.getFileObject("userdir/build.properties");
227         assertNotNull("have build.properties", buildProperties);
228         FileLock lock = buildProperties.lock();
229         OutputStream JavaDoc os = buildProperties.getOutputStream(lock);
230         Properties JavaDoc p = new Properties JavaDoc();
231         p.setProperty("global.prop", "value5a");
232         p.setProperty("global.prop.2", "globalvalue2");
233         p.store(os, null);
234         os.close();
235         lock.releaseLock();
236         assertEquals("two properties fired", new HashSet JavaDoc<String JavaDoc>(Arrays.asList(new String JavaDoc[] {"global.prop", "global.prop.2"})), l.changed);
237         l.reset();
238         assertEquals("global.prop is correct", "value5a", pev.getProperty("global.prop"));
239         assertEquals("global.prop.2 is correct", "globalvalue2", pev.getProperty("global.prop.2"));
240         // #42147: try modifying project.properties and private.properties on disk.
241
FileObject projectProperties = projdir.getFileObject("nbproject/project.properties");
242         assertNotNull("have project.properties", projectProperties);
243         lock = projectProperties.lock();
244         os = projectProperties.getOutputStream(lock);
245         p = new Properties JavaDoc();
246         p.setProperty("overridden.prop", "value3a"); // different, but won't matter
247
p.setProperty("shared.prop", "value1a"); // changed
248
p.setProperty("derived.prop", "${private.prop}:${shared.prop}:${undefined.prop}"); // same literally
249
p.store(os, null);
250         os.close();
251         lock.releaseLock();
252         assertEquals("two properties fired", new HashSet JavaDoc<String JavaDoc>(Arrays.asList(new String JavaDoc[] {"shared.prop", "derived.prop"})), l.changed);
253         l.reset();
254         assertEquals("shared.prop is correct", "value1a", pev.getProperty("shared.prop"));
255         assertEquals("derived.prop correct", "value2:value1a:${undefined.prop}", pev.getProperty("derived.prop"));
256         FileObject privateProperties = projdir.getFileObject("nbproject/private/private.properties");
257         assertNotNull("have private.properties", privateProperties);
258         lock = privateProperties.lock();
259         os = privateProperties.getOutputStream(lock);
260         p = new Properties JavaDoc();
261         p.setProperty("private.prop", "value2a"); // changed
262
p.setProperty("overridden.prop", "value4"); // same
263
p.setProperty("tempdir", "${java.io.tmpdir}/foo"); // same
264
p.setProperty("user.properties.file", "../userdir/build.properties"); // same
265
p.store(os, null);
266         os.close();
267         lock.releaseLock();
268         assertEquals("two properties fired", new HashSet JavaDoc<String JavaDoc>(Arrays.asList(new String JavaDoc[] {"private.prop", "derived.prop"})), l.changed);
269         l.reset();
270         assertEquals("private.prop is correct", "value2a", pev.getProperty("private.prop"));
271         assertEquals("derived.prop correct", "value2a:value1a:${undefined.prop}", pev.getProperty("derived.prop"));
272         // Try deleting project.properties and make sure its values are cleared.
273
projectProperties.delete();
274         assertEquals("two properties fired", new HashSet JavaDoc<String JavaDoc>(Arrays.asList(new String JavaDoc[] {"shared.prop", "derived.prop"})), l.changed);
275         l.reset();
276         assertEquals("shared.prop is gone", null, pev.getProperty("shared.prop"));
277         assertEquals("derived.prop is gone", null, pev.getProperty("derived.prop"));
278         // Now recreate it.
279
projectProperties = projdir.getFileObject("nbproject").createData("project.properties");
280         lock = projectProperties.lock();
281         os = projectProperties.getOutputStream(lock);
282         p = new Properties JavaDoc();
283         p.setProperty("derived.prop", "${private.prop}:${shared.prop}:${undefined.prop.2}"); // restoring w/ changes
284
p.store(os, null);
285         os.close();
286         lock.releaseLock();
287         assertEquals("one property fired", Collections.singleton("derived.prop"), l.changed);
288         l.reset();
289         assertEquals("derived.prop is back", "value2a:${shared.prop}:${undefined.prop.2}", pev.getProperty("derived.prop"));
290         // #44213 cont'd: change user.properties.file and make sure the new definitions are read
291
FileObject buildProperties2 = scratch.getFileObject("userdir").createData("build2.properties");
292         lock = buildProperties2.lock();
293         os = buildProperties2.getOutputStream(lock);
294         p = new Properties JavaDoc();
295         p.setProperty("global.prop", "value5b"); // modified
296
p.setProperty("global.prop.2", "globalvalue2"); // same
297
p.store(os, null);
298         os.close();
299         lock.releaseLock();
300         lock = privateProperties.lock();
301         os = privateProperties.getOutputStream(lock);
302         p = new Properties JavaDoc();
303         p.setProperty("private.prop", "value2a"); // same
304
p.setProperty("overridden.prop", "value4"); // same
305
p.setProperty("tempdir", "${java.io.tmpdir}/foo"); // same
306
p.setProperty("user.properties.file", "../userdir/build2.properties"); // changed
307
p.store(os, null);
308         os.close();
309         lock.releaseLock();
310         assertEquals("two properties fired", new HashSet JavaDoc<String JavaDoc>(Arrays.asList(new String JavaDoc[] {"user.properties.file", "global.prop"})), l.changed);
311         l.reset();
312         assertEquals("user.properties.file is correct", "../userdir/build2.properties", pev.getProperty("user.properties.file"));
313         assertEquals("global.prop is correct", "value5b", pev.getProperty("global.prop"));
314         lock = buildProperties2.lock();
315         os = buildProperties2.getOutputStream(lock);
316         p = new Properties JavaDoc();
317         p.setProperty("global.prop", "value5b"); // same
318
// no global.prop.2
319
p.store(os, null);
320         os.close();
321         lock.releaseLock();
322         assertEquals("one property fired", Collections.singleton("global.prop.2"), l.changed);
323         l.reset();
324         assertEquals("global.prop.2 is gone", null, pev.getProperty("global.prop.2"));
325         // XXX try eval when user.properties.file is not defined (tricky, need to preset netbeans.user)
326
return null;
327             }
328         });
329     }
330     
331     /**
332      * Test that resolving file names relative to the project basedir works.
333      * @throws Exception if anything unexpected happens
334      */

335     public void testResolveFile() throws Exception JavaDoc {
336         // XXX could also be moved to PropertyUtilsTest
337
File JavaDoc scratchF = FileUtil.toFile(scratch);
338         assertNotNull("scratch directory exists on disk", scratchF);
339         File JavaDoc projdirF = FileUtil.toFile(projdir);
340         assertNotNull("project directory exists on disk", projdirF);
341         assertEquals(". resolves to project basedir", projdirF, h.resolveFile("."));
342         assertEquals(". resolves to project basedir", projdir, h.resolveFileObject("."));
343         assertEquals("simple relative path resolves", new File JavaDoc(projdirF, "foo"), h.resolveFile("foo"));
344         assertEquals("simple relative path resolves (but there is no such file object)", null, h.resolveFileObject("foo"));
345         assertEquals("Unix-style ./ resolves", new File JavaDoc(projdirF, "foo"), h.resolveFile("./foo"));
346         assertEquals("DOS-style .\\ resolves", new File JavaDoc(projdirF, "foo"), h.resolveFile(".\\foo"));
347         assertEquals("Unix-style ./ resolves (but there is no such file object)", null, h.resolveFileObject("./foo"));
348         assertEquals("DOS-style ./ resolves (but there is no such file object)", null, h.resolveFileObject(".\\foo"));
349         assertEquals(".. resolves up a dir", scratchF, h.resolveFile(".."));
350         assertEquals(".. resolves up a dir", scratch, h.resolveFileObject(".."));
351         assertEquals("Unix-style ../ resolves up and down", projdirF, h.resolveFile("../proj"));
352         assertEquals("DOS-style ..\\ resolves up and down", projdirF, h.resolveFile("..\\proj"));
353         assertEquals("Unix-style ../ resolves up and down", projdir, h.resolveFileObject("../proj"));
354         assertEquals("DOS-style ..\\ resolves up and down", projdir, h.resolveFileObject("..\\proj"));
355         assertEquals("absolute path is left alone", scratchF, h.resolveFile(scratchF.getAbsolutePath()));
356         assertEquals("absolute path is left alone", scratch, h.resolveFileObject(scratchF.getAbsolutePath()));
357         File JavaDoc somethingElseF = new File JavaDoc(scratchF.getParentFile(), "nonexistent-file-path");
358         assertEquals("absolute (nonexistent) path is left alone", somethingElseF, h.resolveFile(somethingElseF.getAbsolutePath()));
359         assertEquals("absolute (nonexistent) path has no file object", null, h.resolveFileObject(somethingElseF.getAbsolutePath()));
360     }
361     
362     /**
363      * Test that resolving file paths (for example, classpaths) relative to the project basedir works.
364      * Note that Ant permits any kind of path separator;
365      * see {@link PropertyUtils#tokenizePath} for details of the tokenization.
366      * @throws Exception if anything unexpected happens
367      */

368     public void testResolvePath() throws Exception JavaDoc {
369         // XXX could also be moved to PropertyUtilsTest
370
File JavaDoc scratchF = FileUtil.toFile(scratch);
371         assertNotNull("scratch dir exists on disk", scratchF);
372         String JavaDoc scratchS = scratchF.getAbsolutePath();
373         File JavaDoc projdirF = FileUtil.toFile(projdir);
374         assertNotNull("project dir exists on disk", projdirF);
375         String JavaDoc projdirS = projdirF.getAbsolutePath();
376         assertEquals("empty path doesn't need to resolve", "", h.resolvePath(""));
377         assertEquals(". resolves", projdirS, h.resolvePath("."));
378         assertEquals(".. resolves", scratchS, h.resolvePath(".."));
379         assertEquals("Unix-style ../ resolves", projdirS, h.resolvePath("../proj"));
380         assertEquals("DOS-style ..\\ resolves", projdirS, h.resolvePath("..\\proj"));
381         String JavaDoc longpath = projdirS + File.pathSeparator + scratchS + File.pathSeparator + projdirS + File.pathSeparator + projdirS;
382         assertEquals("mixed Unix-style path resolves", longpath, h.resolvePath(".:..:../proj:..\\proj"));
383         assertEquals("mixed DOS-style path resolves", longpath, h.resolvePath(".;..;../proj;..\\proj"));
384         assertEquals("absolute path resolves to itself", scratchS, h.resolvePath(scratchS));
385         // XXX check use of Unix symlinks - don't want them canonicalized
386
// details of tokenization semantics left to PropertyUtilsTest.testTokenizePath
387
}
388     
389     /**
390      * Test that storing changes to .properties files works.
391      * @throws Exception if anything unexpected happens
392      */

393     public void testPutProperties() throws Exception JavaDoc {
394         h.addAntProjectListener(l);
395         EditableProperties ep = h.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
396         assertNotNull("getProperties should never return null", ep);
397         assertEquals("three properties defined", 3, ep.size());
398         ep.put("testprop", "testval");
399         assertTrue("uncommitted changes do not modify project", !pm.isModified(p));
400         assertEquals("uncommitted changes not yet in project properties", null, h.getStandardPropertyEvaluator().getProperty("testprop"));
401         assertEquals("uncommitted changes fire no events", 0, l.events().length);
402         h.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, ep);
403         assertTrue("committed changes do modify project", pm.isModified(p));
404         AntProjectEvent[] evs = l.events();
405         assertEquals("putProperties fires one event", 1, evs.length);
406         assertEquals("correct helper", h, evs[0].getHelper());
407         assertEquals("correct path", AntProjectHelper.PROJECT_PROPERTIES_PATH, evs[0].getPath());
408         assertTrue("expected change", evs[0].isExpected());
409         assertEquals("committed changes are in project properties", "testval", h.getStandardPropertyEvaluator().getProperty("testprop"));
410         Properties JavaDoc props = AntBasedTestUtil.slurpProperties(h, AntProjectHelper.PROJECT_PROPERTIES_PATH);
411         assertNotNull("project.properties already exists", props);
412         assertEquals("project.properties does not yet contain testprop", null, props.getProperty("testprop"));
413         pm.saveProject(p);
414         assertTrue("project is now saved", !pm.isModified(p));
415         assertEquals("saving changes fires no new events", 0, l.events().length);
416         assertEquals("committed & saved changes are in project properties", "testval", h.getStandardPropertyEvaluator().getProperty("testprop"));
417         props = AntBasedTestUtil.slurpProperties(h, AntProjectHelper.PROJECT_PROPERTIES_PATH);
418         assertNotNull("project.properties still exists", props);
419         assertEquals("project.properties now contains testprop", "testval", props.getProperty("testprop"));
420         // #42147: changes made on disk should fire changes to AntProjectListener, not just to the PropertyEvaluator
421
ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction<Void JavaDoc>() {
422             public Void JavaDoc run() throws Exception JavaDoc {
423                 TestUtil.createFileFromContent(null, h.getProjectDirectory(), AntProjectHelper.PROJECT_PROPERTIES_PATH);
424                 return null;
425             }
426         });
427         evs = l.events();
428         assertEquals("touching project.properties fires one event", 1, evs.length);
429         assertEquals("correct helper", h, evs[0].getHelper());
430         assertEquals("correct path", AntProjectHelper.PROJECT_PROPERTIES_PATH, evs[0].getPath());
431         assertFalse("unexpected change", evs[0].isExpected());
432         assertEquals("empty file now", Collections.EMPTY_MAP, h.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH));
433         // XXX try creating and deleting property files
434
// XXX try modifying several property files and saving in a batch
435
// XXX try storing unmodified properties and see what happens
436
// XXX try storing a fresh EditableProperties object not returned from getProperties
437
}
438     
439     /**
440      * Test that writing changes to project.xml and private.xml works.
441      * @throws Exception if anything unexpected happens
442      */

443     public void testPutPrimaryConfigurationData() throws Exception JavaDoc {
444         h.addAntProjectListener(l);
445         Element JavaDoc data = h.getPrimaryConfigurationData(true);
446         assertNotNull("<shared-stuff/> is there to start", Util.findElement(data, "shared-stuff", "urn:test:shared"));
447         assertTrue("project is not initially modified", !pm.isModified(p));
448         assertEquals("gPCD fires no events", 0, l.events().length);
449         assertNotNull("config data has an owner document", data.getOwnerDocument());
450         Element JavaDoc nue = data.getOwnerDocument().createElementNS("urn:test:shared", "misc");
451         data.appendChild(nue);
452         assertTrue("project is not modified after uncommitted change", !pm.isModified(p));
453         assertEquals("no events fired after uncommitted change", 0, l.events().length);
454         assertEquals("after uncommitted change gPCD does not yet have new <misc/>", null, Util.findElement(h.getPrimaryConfigurationData(true), "misc", "urn:test:shared"));
455         h.putPrimaryConfigurationData(data, true);
456         assertTrue("project is modified after committed change", pm.isModified(p));
457         AntProjectEvent[] evs = l.events();
458         assertEquals("putPCD fires one event", 1, evs.length);
459         assertEquals("correct helper", h, evs[0].getHelper());
460         assertEquals("correct path", AntProjectHelper.PROJECT_XML_PATH, evs[0].getPath());
461         assertTrue("expected change", evs[0].isExpected());
462         nue = Util.findElement(h.getPrimaryConfigurationData(true), "misc", "urn:test:shared");
463         assertNotNull("after committed change gPCD has new <misc/>", nue);
464         assertEquals("new element name is correct", "misc", nue.getLocalName());
465         assertEquals("new element namespace is correct", "urn:test:shared", nue.getNamespaceURI());
466         Document JavaDoc doc = AntBasedTestUtil.slurpXml(h, AntProjectHelper.PROJECT_XML_PATH);
467         Element JavaDoc configuration = Util.findElement(doc.getDocumentElement(), "configuration", AntProjectHelper.PROJECT_NS);
468         assertNotNull("still has <configuration> on disk", configuration);
469         data = Util.findElement(configuration, "data", "urn:test:shared");
470         assertNotNull("still has <data> on disk", data);
471         nue = Util.findElement(data, "misc", "urn:test:shared");
472         assertEquals("<misc/> not yet on disk", null, nue);
473         pm.saveProject(p);
474         assertTrue("project is not modified after save", !pm.isModified(p));
475         assertEquals("saving changes fires no new events", 0, l.events().length);
476         nue = Util.findElement(h.getPrimaryConfigurationData(true), "misc", "urn:test:shared");
477         assertNotNull("after save gPCD still has new <misc/>", nue);
478         doc = AntBasedTestUtil.slurpXml(h, AntProjectHelper.PROJECT_XML_PATH);
479         configuration = Util.findElement(doc.getDocumentElement(), "configuration", AntProjectHelper.PROJECT_NS);
480         assertNotNull("still has <configuration> on disk", configuration);
481         data = Util.findElement(configuration, "data", "urn:test:shared");
482         assertNotNull("still has <data> on disk", data);
483         nue = Util.findElement(data, "misc", "urn:test:shared");
484         assertNotNull("<misc/> now on disk", nue);
485         // #42147: changes made on disk should result in firing of an AntProjectEvent
486
ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction<Void JavaDoc>() {
487             public Void JavaDoc run() throws Exception JavaDoc {
488                 TestUtil.createFileFromContent(AntProjectHelperTest.class.getResource("data/project-modified.xml"), projdir, AntProjectHelper.PROJECT_XML_PATH);
489                 return null;
490             }
491         });
492         evs = l.events();
493         assertEquals("writing project.xml on disk fires one event", 1, evs.length);
494         assertEquals("correct helper", h, evs[0].getHelper());
495         assertEquals("correct path", AntProjectHelper.PROJECT_XML_PATH, evs[0].getPath());
496         assertFalse("unexpected change", evs[0].isExpected());
497         assertEquals("correct new display name", "Some New Name", ProjectUtils.getInformation(p).getDisplayName());
498         data = h.getPrimaryConfigurationData(true);
499         Element JavaDoc stuff = Util.findElement(data, "other-shared-stuff", "urn:test:shared");
500         assertNotNull("have <other-shared-stuff/> now", stuff);
501         AuxiliaryConfiguration aux = p.getLookup().lookup(AuxiliaryConfiguration.class);
502         data = aux.getConfigurationFragment("data", "urn:test:shared-aux", true);
503         assertNotNull("have aux <data>", data);
504         stuff = Util.findElement(data, "other-aux-shared-stuff", "urn:test:shared-aux");
505         assertNotNull("have <other-aux-shared-stuff/> now", stuff);
506         // XXX try private.xml too
507
// XXX try modifying both XML files, or different parts of the same, and saving in a batch
508
// XXX try storing unmodified XML fragments and see what happens
509
// XXX try storing a fresh Element not returned from getPrimaryConfigurationData
510
}
511     
512     /**
513      * Test that it is possible for external code to store custom data in project.xml and private.xml.
514      * @throws Exception if anything unexpected happens
515      */

516     public void testExtensibleMetadataProviderImpl() throws Exception JavaDoc {
517         AuxiliaryConfiguration aux = p.getLookup().lookup(AuxiliaryConfiguration.class);
518         assertNotNull("AuxiliaryConfiguration present", aux);
519         CacheDirectoryProvider cdp = p.getLookup().lookup(CacheDirectoryProvider.class);
520         assertNotNull("CacheDirectoryProvider present", cdp);
521         // Check cache dir.
522
FileObject cache = cdp.getCacheDirectory();
523         assertNotNull("has a cache dir", cache);
524         assertTrue("cache dir is a folder", cache.isFolder());
525         assertEquals("cache dir is empty", Collections.EMPTY_LIST, Arrays.asList(cache.getChildren()));
526         cache.createData("foo");
527         cache = cdp.getCacheDirectory();
528         assertEquals("cache contents still there", 1, cache.getChildren().length);
529         // Check read of shared data.
530
h.addAntProjectListener(l);
531         Element JavaDoc data = aux.getConfigurationFragment("data", "urn:test:shared-aux", true);
532         assertNotNull("found shared <data>", data);
533         assertEquals("correct name", "data", data.getLocalName());
534         assertEquals("correct namespace", "urn:test:shared-aux", data.getNamespaceURI());
535         Element JavaDoc stuff = Util.findElement(data, "aux-shared-stuff", "urn:test:shared-aux");
536         assertNotNull("found <aux-shared-stuff/>", stuff);
537         assertEquals("gCF fires no changes", 0, l.events().length);
538         // Check write of shared data.
539
stuff.setAttribute("attr", "val");
540         assertFalse("project not modified by local change", pm.isModified(p));
541         aux.putConfigurationFragment(data, true);
542         assertTrue("now project is modified", pm.isModified(p));
543         AntProjectEvent[] evs = l.events();
544         assertEquals("pCF fires one event", 1, evs.length);
545         assertEquals("correct helper", h, evs[0].getHelper());
546         assertEquals("correct path", AntProjectHelper.PROJECT_XML_PATH, evs[0].getPath());
547         assertTrue("expected change", evs[0].isExpected());
548         pm.saveProject(p);
549         assertEquals("saving project fires no new changes", 0, l.events().length);
550         Document JavaDoc doc = AntBasedTestUtil.slurpXml(h, AntProjectHelper.PROJECT_XML_PATH);
551         Element JavaDoc config = Util.findElement(doc.getDocumentElement(), "configuration", AntProjectHelper.PROJECT_NS);
552         assertNotNull("<configuration> still exists", config);
553         data = Util.findElement(config, "data", "urn:test:shared-aux");
554         assertNotNull("<data> still exists", data);
555         stuff = Util.findElement(data, "aux-shared-stuff", "urn:test:shared-aux");
556         assertNotNull("still have <aux-shared-stuff/>", stuff);
557         assertEquals("attr written correctly", "val", stuff.getAttribute("attr"));
558         // Check read of private data.
559
data = aux.getConfigurationFragment("data", "urn:test:private-aux", false);
560         assertNotNull("found shared <data>", data);
561         assertEquals("correct name", "data", data.getLocalName());
562         assertEquals("correct namespace", "urn:test:private-aux", data.getNamespaceURI());
563         stuff = Util.findElement(data, "aux-private-stuff", "urn:test:private-aux");
564         assertNotNull("found <aux-private-stuff/>", stuff);
565         assertEquals("gCF fires no changes", 0, l.events().length);
566         // Check write of private data.
567
stuff.setAttribute("attr", "val");
568         assertFalse("project not modified by local change", pm.isModified(p));
569         aux.putConfigurationFragment(data, false);
570         assertTrue("now project is modified", pm.isModified(p));
571         evs = l.events();
572         assertEquals("pCF fires one event", 1, evs.length);
573         assertEquals("correct helper", h, evs[0].getHelper());
574         assertEquals("correct path", AntProjectHelper.PRIVATE_XML_PATH, evs[0].getPath());
575         assertTrue("expected change", evs[0].isExpected());
576         pm.saveProject(p);
577         assertEquals("saving project fires no new changes", 0, l.events().length);
578         doc = AntBasedTestUtil.slurpXml(h, AntProjectHelper.PRIVATE_XML_PATH);
579         config = doc.getDocumentElement();
580         data = Util.findElement(config, "data", "urn:test:private-aux");
581         assertNotNull("<data> still exists", data);
582         stuff = Util.findElement(data, "aux-private-stuff", "urn:test:private-aux");
583         assertNotNull("still have <aux-private-stuff/>", stuff);
584         assertEquals("attr written correctly", "val", stuff.getAttribute("attr"));
585         // Check that missing fragments are not returned.
586
Element JavaDoc bogus = aux.getConfigurationFragment("doesn't exist", "bogus", true);
587         assertNull("no such fragment - wrong name/ns", bogus);
588         bogus = aux.getConfigurationFragment("data", "bogus", true);
589         assertNull("no such fragment - wrong ns", bogus);
590         bogus = aux.getConfigurationFragment("doesn't exist", "urn:test:shared-aux", true);
591         assertNull("no such fragment - wrong name", bogus);
592         bogus = aux.getConfigurationFragment("data", "urn:test:shared-aux", false);
593         assertNull("no such fragment - wrong file", bogus);
594         // Try adding a new fragment.
595
Document JavaDoc temp = XMLUtil.createDocument("whatever", null, null, null);
596         data = temp.createElementNS("urn:test:whatever", "hello");
597         data.appendChild(temp.createTextNode("stuff"));
598         assertFalse("project currently unmodified", pm.isModified(p));
599         aux.putConfigurationFragment(data, true);
600         assertTrue("adding frag modified project", pm.isModified(p));
601         evs = l.events();
602         assertEquals("pCF fires one event", 1, evs.length);
603         assertEquals("correct path", AntProjectHelper.PROJECT_XML_PATH, evs[0].getPath());
604         pm.saveProject(p);
605         assertEquals("saving project fires no new changes", 0, l.events().length);
606         data = aux.getConfigurationFragment("hello", "urn:test:whatever", true);
607         assertNotNull("can retrieve new frag", data);
608         doc = AntBasedTestUtil.slurpXml(h, AntProjectHelper.PROJECT_XML_PATH);
609         config = Util.findElement(doc.getDocumentElement(), "configuration", AntProjectHelper.PROJECT_NS);
610         assertNotNull("<configuration> still exists", config);
611         data = Util.findElement(config, "hello", "urn:test:whatever");
612         assertNotNull("<hello> still exists", data);
613         assertEquals("correct nested contents too", "stuff", Util.findText(data));
614         // Try removing a fragment.
615
assertFalse("project is unmodified", pm.isModified(p));
616         assertTrue("can remove new frag", aux.removeConfigurationFragment("hello", "urn:test:whatever", true));
617         assertTrue("project is now modified", pm.isModified(p));
618         assertNull("now frag is gone", aux.getConfigurationFragment("hello", "urn:test:whatever", true));
619         pm.saveProject(p);
620         doc = AntBasedTestUtil.slurpXml(h, AntProjectHelper.PROJECT_XML_PATH);
621         config = Util.findElement(doc.getDocumentElement(), "configuration", AntProjectHelper.PROJECT_NS);
622         assertNotNull("<configuration> still exists", config);
623         data = Util.findElement(config, "hello", "urn:test:whatever");
624         assertNull("now <hello> is gone", data);
625         assertFalse("cannot remove a frag that is not there", aux.removeConfigurationFragment("hello", "urn:test:whatever", true));
626         assertFalse("trying to remove a nonexistent frag does not modify project", pm.isModified(p));
627         
628         // check that created elements are ordered
629
data = temp.createElementNS("namespace", "ccc");
630         aux.putConfigurationFragment(data, true);
631         data = temp.createElementNS("namespace", "bbb");
632         aux.putConfigurationFragment(data, true);
633         data = temp.createElementNS("namespace", "aaa");
634         aux.putConfigurationFragment(data, true);
635         data = temp.createElementNS("namespace-1", "bbb");
636         aux.putConfigurationFragment(data, true);
637         data = temp.createElementNS("name-sp", "bbb");
638         aux.putConfigurationFragment(data, true);
639         data = temp.createElementNS("namespace", "aaaa");
640         aux.putConfigurationFragment(data, true);
641         pm.saveProject(p);
642         doc = AntBasedTestUtil.slurpXml(h, AntProjectHelper.PROJECT_XML_PATH);
643         config = Util.findElement(doc.getDocumentElement(), "configuration", AntProjectHelper.PROJECT_NS);
644         String JavaDoc[] names = new String JavaDoc[]{"aaa-namespace", "aaaa-namespace", "bbb-name-sp", "bbb-namespace", "bbb-namespace-1", "ccc-namespace", "data-urn:test:shared", "data-urn:test:shared-aux"};
645         int count = 0;
646         NodeList JavaDoc list = config.getChildNodes();
647         for (int i=0; i<list.getLength(); i++) {
648             Node JavaDoc n = list.item(i);
649             if (n.getNodeType() != Node.ELEMENT_NODE) {
650                 continue;
651             }
652             assertEquals(names[count], n.getNodeName()+"-"+n.getNamespaceURI());
653             count++;
654         }
655         assertEquals("Elements count does not match", names.length, count);
656         
657         // XXX check that it cannot be used to load or store primary configuration data
658
// or other general fixed metadata
659
// XXX try overwriting data
660
}
661     
662     public void test68872() throws Exception JavaDoc {
663         AuxiliaryConfiguration aux = p.getLookup().lookup(AuxiliaryConfiguration.class);
664         assertNotNull("AuxiliaryConfiguration present", aux);
665
666         Element JavaDoc data = aux.getConfigurationFragment("data", "urn:test:private-aux", false);
667         Element JavaDoc stuff = Util.findElement(data, "aux-private-stuff", "urn:test:private-aux");
668         assertNotNull("found <aux-private-stuff/>", stuff);
669         // Check write of private data.
670
stuff.setAttribute("attr", "val");
671         aux.putConfigurationFragment(data, false);
672         assertTrue("now project is modified", pm.isModified(p));
673         
674         FileObject privateXMLFO = p.getProjectDirectory().getFileObject("nbproject/private/private.xml");
675         
676         assertNotNull(privateXMLFO);
677         
678         File JavaDoc privateXML = FileUtil.toFile(privateXMLFO);
679         
680         privateXML.delete();
681         
682         privateXMLFO.refresh();
683         privateXMLFO.getParent().refresh();
684         
685         pm.saveProject(p);
686         
687         //the file should be renewed with new data:
688
assertTrue(privateXML.exists());
689         
690         //check the data are written:
691
Document JavaDoc doc = AntBasedTestUtil.slurpXml(h, AntProjectHelper.PRIVATE_XML_PATH);
692         Element JavaDoc config = doc.getDocumentElement();
693         data = Util.findElement(config, "data", "urn:test:private-aux");
694         assertNotNull("<data> still exists", data);
695         stuff = Util.findElement(data, "aux-private-stuff", "urn:test:private-aux");
696         assertNotNull("still have <aux-private-stuff/>", stuff);
697         assertEquals("attr written correctly", "val", stuff.getAttribute("attr"));
698         
699         //check that on-disk changes are not ignored if the project is saved:
700
privateXML.delete();
701         
702         privateXMLFO.refresh();
703         privateXMLFO.getParent().refresh();
704         
705         assertNull(aux.getConfigurationFragment("data", "urn:test:private-aux", false));
706     }
707     
708     public void testCreatePropertyProvider() throws Exception JavaDoc {
709         PropertyProvider pp = h.getPropertyProvider(AntProjectHelper.PROJECT_PROPERTIES_PATH);
710         Map JavaDoc/*<String,String>*/ defs = pp.getProperties();
711         assertEquals("correct number of defs", 3, defs.size());
712         assertEquals("correct value", "value1", defs.get("shared.prop"));
713         // Test changes.
714
AntBasedTestUtil.TestCL l = new AntBasedTestUtil.TestCL();
715         pp.addChangeListener(l);
716         EditableProperties p = h.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
717         p.setProperty("foo", "bar");
718         assertFalse("no events from uncommitted changes", l.expect());
719         h.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, p);
720         assertTrue("got a change from setting a property", l.expect());
721         defs = pp.getProperties();
722         assertEquals("correct new size", 4, defs.size());
723         assertEquals("correct new value", "bar", defs.get("foo"));
724         // No-op changes.
725
p = p.cloneProperties();
726         p.setProperty("foo", "bar2");
727         p.setProperty("foo", "bar");
728         h.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, p);
729         assertFalse("no events from no-op changes", l.expect());
730         // Deleting a property file.
731
h.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, null);
732         assertTrue("got a change from removing a property file", l.expect());
733         assertEquals("now have no definitions", Collections.EMPTY_MAP, pp.getProperties());
734         // Start off with no file, then create it.
735
String JavaDoc path = "foo.properties";
736         pp = h.getPropertyProvider(path);
737         pp.addChangeListener(l);
738         assertEquals("no defs initially", Collections.EMPTY_MAP, pp.getProperties());
739         assertNull("no file made yet", h.getProjectDirectory().getFileObject(path));
740         p = new EditableProperties();
741         p.setProperty("one", "1");
742         p.setProperty("two", "2");
743         h.putProperties(path, p);
744         assertTrue("making the file fired a change", l.expect());
745         defs = pp.getProperties();
746         assertEquals("two defs", 2, defs.size());
747         assertEquals("right value #1", "1", defs.get("one"));
748         assertEquals("right value #2", "2", defs.get("two"));
749         assertNull("no file yet saved to disk", h.getProjectDirectory().getFileObject(path));
750         p.setProperty("three", "3");
751         assertFalse("no events from uncomm. change", l.expect());
752         h.putProperties(path, p);
753         assertTrue("now have changed new file", l.expect());
754         defs = pp.getProperties();
755         assertEquals("three defs", 3, defs.size());
756         // XXX test that saving the project fires no additional changes
757
// XXX test changes fired if file modified (or created or removed) on disk
758
}
759
760     /* XXX unable to simulate #50198 in a test environment:
761     public void testMultithreadedAccessToXmlData() throws Exception {
762         class R implements Runnable {
763             private final int x;
764             public R(int x) {
765                 this.x = x;
766             }
767             public void run() {
768                 System.out.println("starting #" + x);
769                 for (int i = 0; i < 1000; i++) {
770                     Element data = h.getPrimaryConfigurationData(true);
771                     Util.findSubElements(data);
772                     if (i % 100 == 0) {
773                         System.out.println("in the middle of #" + x);
774                         try {
775                             Thread.sleep((long) (Math.random() * 25));
776                         } catch (InterruptedException e) {
777                             e.printStackTrace();
778                         }
779                     }
780                 }
781                 System.out.println("finishing #" + x);
782             }
783         }
784         Thread t1 = new Thread(new R(1));
785         Thread t2 = new Thread(new R(2));
786         t1.start();
787         t2.start();
788         t1.join();
789         t2.join();
790     }
791      */

792
793 }
794
Popular Tags