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 org.netbeans.spi.project.ant.AntBuildExtenderImplementation;
045: import java.io.ByteArrayInputStream;
046: import java.io.File;
047: import java.net.URL;
048: import java.util.Collections;
049: import java.util.List;
050: import org.netbeans.api.project.Project;
051: import org.netbeans.api.project.ProjectManager;
052: import org.netbeans.api.project.TestUtil;
053: import org.netbeans.junit.NbTestCase;
054: import org.netbeans.modules.project.ant.AntBuildExtenderAccessor;
055: import org.netbeans.modules.project.ant.Util;
056: import org.netbeans.spi.project.AuxiliaryConfiguration;
057: import org.openide.filesystems.FileObject;
058: import org.openide.filesystems.FileUtil;
059: import org.openide.util.Utilities;
060: import org.w3c.dom.Document;
061: import org.w3c.dom.Element;
062: import org.w3c.dom.NodeList;
063:
064: /**
065: * Test functionality of GeneratedFilesHelper.
066: * @author Jesse Glick
067: */
068: public class GeneratedFilesHelperTest extends NbTestCase {
069:
070: public GeneratedFilesHelperTest(String name) {
071: super (name);
072: }
073:
074: private FileObject scratch;
075: private FileObject projdir;
076: private FileObject extension1;
077: private ProjectManager pm;
078: private Project p;
079: private AntProjectHelper h;
080: private GeneratedFilesHelper gfh;
081: private ExtImpl extenderImpl;
082:
083: protected void setUp() throws Exception {
084: super .setUp();
085: scratch = TestUtil.makeScratchDir(this );
086: projdir = scratch.createFolder("proj");
087: TestUtil.createFileFromContent(GeneratedFilesHelperTest.class
088: .getResource("data/project.xml"), projdir,
089: "nbproject/project.xml");
090: extension1 = TestUtil.createFileFromContent(
091: GeneratedFilesHelperTest.class
092: .getResource("data/extension1.xml"), projdir,
093: "nbproject/extension1.xml");
094: extenderImpl = new ExtImpl();
095: TestUtil.setLookup(new Object[] { AntBasedTestUtil
096: .testAntBasedProjectType(extenderImpl), });
097: pm = ProjectManager.getDefault();
098: p = pm.findProject(projdir);
099: extenderImpl.project = p;
100: h = p.getLookup().lookup(AntProjectHelper.class);
101: gfh = p.getLookup().lookup(GeneratedFilesHelper.class);
102: assertNotNull(gfh);
103: }
104:
105: /**
106: * Test that creating build-impl.xml from project.xml + build-impl.xsl works.
107: * @throws Exception if anything unexpected happens
108: */
109: public void testGenerateBuildScriptFromStylesheet()
110: throws Exception {
111: // Make sure there is some build-impl.xml.
112: FileObject bi = projdir
113: .getFileObject(GeneratedFilesHelper.BUILD_IMPL_XML_PATH);
114: assertNull("No build-impl.xml yet", bi);
115: // Modify shared data in a project.
116: Element primdata = h.getPrimaryConfigurationData(true);
117: Element oldDisplayName = Util.findElement(primdata,
118: "display-name", "urn:test:shared");
119: assertNotNull("had a <display-name> before", oldDisplayName);
120: Element displayName = primdata.getOwnerDocument()
121: .createElementNS("urn:test:shared", "display-name");
122: displayName.appendChild(primdata.getOwnerDocument()
123: .createTextNode("New Name"));
124: primdata.insertBefore(displayName, oldDisplayName);
125: primdata.removeChild(oldDisplayName);
126: h.putPrimaryConfigurationData(primdata, true);
127: assertTrue("project is modified", pm.isModified(p));
128: pm.saveProject(p);
129: // Ensure that build-impl.xml was (correctly) regenerated.
130: FileObject genfiles = projdir
131: .getFileObject(GeneratedFilesHelper.GENFILES_PROPERTIES_PATH);
132: assertNotNull("genfiles.properties exists", genfiles);
133: bi = projdir
134: .getFileObject(GeneratedFilesHelper.BUILD_IMPL_XML_PATH);
135: assertNotNull(
136: "saving the project with a project.xml change regenerates build-impl.xml",
137: bi);
138: Document doc = AntBasedTestUtil.slurpXml(h,
139: GeneratedFilesHelper.BUILD_IMPL_XML_PATH);
140: Element el = doc.getDocumentElement();
141: assertEquals("build-impl.xml is a <project>", "project", el
142: .getLocalName());
143: assertEquals("<project> has no namespace", null, el
144: .getNamespaceURI());
145: NodeList l = doc.getElementsByTagName("description");
146: assertEquals("one <description> in build-impl.xml", 1, l
147: .getLength());
148: el = (Element) l.item(0);
149: assertEquals("correct description", "New Name", Util
150: .findText(el));
151: // Clear build-impl.xml to test if it is rewritten.
152: bi.delete();
153: // Now make some irrelevant change - e.g. to private.xml - and check that there is no modification.
154: Element data = h.getPrimaryConfigurationData(false);
155: data.setAttribute("someattr", "someval");
156: h.putPrimaryConfigurationData(data, false);
157: assertTrue("project is modified", pm.isModified(p));
158: pm.saveProject(p);
159: bi = projdir
160: .getFileObject(GeneratedFilesHelper.BUILD_IMPL_XML_PATH);
161: assertNull(
162: "saving a private.xml change does not regenerate build-impl.xml",
163: bi);
164: }
165:
166: /**
167: * Test that fooling with a build script in various ways is correctly detected.
168: * @throws Exception if anything unexpected happens
169: */
170: public void testGetBuildScriptState() throws Exception {
171: URL xslt = GeneratedFilesHelperTest.class
172: .getResource("data/build.xsl");
173: URL xslt2 = GeneratedFilesHelperTest.class
174: .getResource("data/build2.xsl");
175: String path = GeneratedFilesHelper.BUILD_XML_PATH;
176: assertEquals("initially there is no build.xml",
177: GeneratedFilesHelper.FLAG_MISSING, gfh
178: .getBuildScriptState(path, xslt));
179: assertEquals("stylesheet version ignored for FLAG_MISSING",
180: GeneratedFilesHelper.FLAG_MISSING, gfh
181: .getBuildScriptState(path, xslt2));
182: gfh.generateBuildScriptFromStylesheet(path, xslt);
183: assertEquals("now build.xml is there and clean", 0, gfh
184: .getBuildScriptState(path, xslt));
185: assertEquals("build.xml is using first stylesheet",
186: GeneratedFilesHelper.FLAG_OLD_STYLESHEET, gfh
187: .getBuildScriptState(path, xslt2));
188: File buildXml = FileUtil.toFile(projdir
189: .getFileObject("build.xml"));
190: assertEquals("one replacement", 1, AntBasedTestUtil
191: .replaceInFile(buildXml, "name=\"somename\"",
192: "name=\"someothername\""));
193: assertEquals("now build.xml is modified",
194: GeneratedFilesHelper.FLAG_MODIFIED, gfh
195: .getBuildScriptState(path, xslt));
196: assertEquals("one replacement", 1, AntBasedTestUtil
197: .replaceInFile(buildXml, "name=\"someothername\"",
198: "name=\"somename\""));
199: assertEquals("now build.xml is clean again", 0, gfh
200: .getBuildScriptState(path, xslt));
201: File projectXml = FileUtil.toFile(projdir
202: .getFileObject("nbproject/project.xml"));
203: assertEquals("one replacement", 1, AntBasedTestUtil
204: .replaceInFile(projectXml, "<name>somename</name>",
205: "<name>newname</name>"));
206: assertEquals("now build.xml is out of date w.r.t. project.xml",
207: GeneratedFilesHelper.FLAG_OLD_PROJECT_XML, gfh
208: .getBuildScriptState(path, xslt));
209: assertEquals(
210: "build.xml is out of date w.r.t. project.xml and new XSLT",
211: GeneratedFilesHelper.FLAG_OLD_PROJECT_XML
212: | GeneratedFilesHelper.FLAG_OLD_STYLESHEET, gfh
213: .getBuildScriptState(path, xslt2));
214: assertEquals("one replacement", 1, AntBasedTestUtil
215: .replaceInFile(buildXml, "name=\"somename\"",
216: "name=\"someothername\""));
217: assertEquals(
218: "build.xml is modified and out of date w.r.t. project.xml",
219: GeneratedFilesHelper.FLAG_OLD_PROJECT_XML
220: | GeneratedFilesHelper.FLAG_MODIFIED, gfh
221: .getBuildScriptState(path, xslt));
222: assertEquals(
223: "build.xml is modified and out of date w.r.t. project.xml and new XSLT",
224: GeneratedFilesHelper.FLAG_OLD_PROJECT_XML
225: | GeneratedFilesHelper.FLAG_MODIFIED
226: | GeneratedFilesHelper.FLAG_OLD_STYLESHEET, gfh
227: .getBuildScriptState(path, xslt2));
228: gfh.generateBuildScriptFromStylesheet(path, xslt2);
229: assertEquals("now regenerated build.xml is up to date", 0, gfh
230: .getBuildScriptState(path, xslt2));
231: // Check newline conventions. First normalize project.xml if running on Windows or Mac.
232: AntBasedTestUtil.replaceInFile(projectXml, "\r\n", "\n");
233: AntBasedTestUtil.replaceInFile(projectXml, "\r", "\n");
234: gfh.generateBuildScriptFromStylesheet(path, xslt);
235: assertEquals("build.xml is clean", 0, gfh.getBuildScriptState(
236: path, xslt));
237: int count = AntBasedTestUtil.replaceInFile(projectXml, "\n",
238: "\r\n");
239: assertTrue("Changed newlines", count > 0);
240: assertEquals(
241: "build.xml is still clean w.r.t. changed newlines in project.xml",
242: 0, gfh.getBuildScriptState(path, xslt));
243: // XXX check also newline changes in stylesheet and build.xml
244: }
245:
246: /**
247: * Test normalization of newlines in CRC-32 computations.
248: * @throws Exception if anything unexpected happens
249: */
250: public void testComputeCrc32() throws Exception {
251: String testDataNl = "hi mom\nhow are you\n";
252: String testDataCrNl = "hi mom\r\nhow are you\r\n";
253: String testDataCr = "hi mom\rhow are you\r";
254: String crcNl = GeneratedFilesHelper
255: .computeCrc32(new ByteArrayInputStream(testDataNl
256: .getBytes("UTF-8")));
257: String crcCrNl = GeneratedFilesHelper
258: .computeCrc32(new ByteArrayInputStream(testDataCrNl
259: .getBytes("UTF-8")));
260: String crcCr = GeneratedFilesHelper
261: .computeCrc32(new ByteArrayInputStream(testDataCr
262: .getBytes("UTF-8")));
263: assertEquals("CRNL normalized -> NL", crcNl, crcCrNl);
264: assertEquals("CR normalized -> NL", crcNl, crcCr);
265: }
266:
267: public void testEolOnWindows() throws Exception {
268: if (Utilities.isWindows()) {
269: URL xslt = GeneratedFilesHelperTest.class
270: .getResource("data/build.xsl");
271: String path = GeneratedFilesHelper.BUILD_XML_PATH;
272: assertEquals("initially there is no build.xml",
273: GeneratedFilesHelper.FLAG_MISSING, gfh
274: .getBuildScriptState(path, xslt));
275: gfh.generateBuildScriptFromStylesheet(path, xslt);
276: assertEquals("now build.xml is there and clean", 0, gfh
277: .getBuildScriptState(path, xslt));
278: File buildXml = FileUtil.toFile(projdir
279: .getFileObject("build.xml"));
280: StringBuffer sb = new StringBuffer(AntBasedTestUtil
281: .slurpText(h, path));
282: boolean ok = true;
283: for (int i = 1; i < sb.length(); i++) {
284: if (sb.charAt(i) == '\n') {
285: if (sb.charAt(i - 1) != '\r') {
286: ok = false;
287: break;
288: }
289: }
290: }
291: assertTrue("generated file has platform line endings", ok);
292: }
293: }
294:
295: private class ExtImpl implements AntBuildExtenderImplementation {
296: Project project;
297: Element newElement;
298: Element oldElement;
299:
300: public List<String> getExtensibleTargets() {
301: return Collections.singletonList("all");
302: }
303:
304: public void updateBuildExtensionMetadata(Element element) {
305: newElement = element;
306: }
307:
308: public Element getBuildExtensionMetadata() {
309: Element el = project.getLookup().lookup(
310: AuxiliaryConfiguration.class)
311: .getConfigurationFragment(
312: AntBuildExtenderAccessor.ELEMENT_ROOT,
313: "urn:test:extension", true);
314: if (el != null) {
315: NodeList nl = el
316: .getElementsByTagName(AntBuildExtenderAccessor.ELEMENT_ROOT);
317: if (nl.getLength() == 1) {
318: return (Element) nl.item(0);
319: }
320: }
321: return null;
322: }
323:
324: public Project getOwningProject() {
325: return project;
326: }
327:
328: }
329:
330: }
|