Line 0
Link Here
|
|
|
1 |
/* |
2 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
3 |
* |
4 |
* Copyright 2009 Sun Microsystems, Inc. All rights reserved. |
5 |
* |
6 |
* The contents of this file are subject to the terms of either the GNU |
7 |
* General Public License Version 2 only ("GPL") or the Common |
8 |
* Development and Distribution License("CDDL") (collectively, the |
9 |
* "License"). You may not use this file except in compliance with the |
10 |
* License. You can obtain a copy of the License at |
11 |
* http://www.netbeans.org/cddl-gplv2.html |
12 |
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the |
13 |
* specific language governing permissions and limitations under the |
14 |
* License. When distributing the software, include this License Header |
15 |
* Notice in each file and include the License file at |
16 |
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this |
17 |
* particular file as subject to the "Classpath" exception as provided |
18 |
* by Sun in the GPL Version 2 section of the License file that |
19 |
* accompanied this code. If applicable, add the following below the |
20 |
* License Header, with the fields enclosed by brackets [] replaced by |
21 |
* your own identifying information: |
22 |
* "Portions Copyrighted [year] [name of copyright owner]" |
23 |
* |
24 |
* If you wish your version of this file to be governed by only the CDDL |
25 |
* or only the GPL Version 2, indicate your decision by adding |
26 |
* "[Contributor] elects to include this software in this distribution |
27 |
* under the [CDDL or GPL Version 2] license." If you do not indicate a |
28 |
* single choice of license, a recipient has the option to distribute |
29 |
* your version of this file under either the CDDL, the GPL Version 2 or |
30 |
* to extend the choice of license to its licensees as provided above. |
31 |
* However, if you add GPL Version 2 code and therefore, elected the GPL |
32 |
* Version 2 license, then the option applies only if the new code is |
33 |
* made subject to such option by the copyright holder. |
34 |
* |
35 |
* Contributor(s): |
36 |
* |
37 |
* Portions Copyrighted 2009 Sun Microsystems, Inc. |
38 |
*/ |
39 |
|
40 |
package org.netbeans.modules.java.api.common.queries; |
41 |
|
42 |
import java.beans.PropertyChangeEvent; |
43 |
import java.beans.PropertyChangeListener; |
44 |
import java.io.IOException; |
45 |
import java.net.URL; |
46 |
import java.util.Arrays; |
47 |
import java.util.Collections; |
48 |
import javax.swing.event.ChangeEvent; |
49 |
import javax.swing.event.ChangeListener; |
50 |
import org.netbeans.api.java.classpath.ClassPath; |
51 |
import org.netbeans.api.java.project.JavaProjectConstants; |
52 |
import org.netbeans.api.java.queries.BinaryForSourceQuery; |
53 |
import org.netbeans.api.java.queries.SourceForBinaryQuery; |
54 |
import org.netbeans.api.java.queries.SourceLevelQuery; |
55 |
import org.netbeans.api.java.queries.UnitTestForSourceQuery; |
56 |
import org.netbeans.api.project.Project; |
57 |
import org.netbeans.api.project.ProjectManager; |
58 |
import org.netbeans.api.project.ProjectUtils; |
59 |
import org.netbeans.api.project.SourceGroup; |
60 |
import org.netbeans.api.project.Sources; |
61 |
import org.netbeans.api.queries.FileBuiltQuery; |
62 |
import org.netbeans.api.queries.FileEncodingQuery; |
63 |
import org.netbeans.junit.NbTestCase; |
64 |
import org.netbeans.modules.java.api.common.SourceRoots; |
65 |
import org.netbeans.modules.java.api.common.ant.UpdateHelper; |
66 |
import org.netbeans.modules.java.api.common.ant.UpdateImplementation; |
67 |
import org.netbeans.modules.java.api.common.classpath.ClassPathProviderImpl; |
68 |
import org.netbeans.spi.project.AuxiliaryConfiguration; |
69 |
import org.netbeans.spi.project.support.ant.AntBasedProjectType; |
70 |
import org.netbeans.spi.project.support.ant.AntProjectHelper; |
71 |
import org.netbeans.spi.project.support.ant.EditableProperties; |
72 |
import org.netbeans.spi.project.support.ant.ProjectGenerator; |
73 |
import org.netbeans.spi.project.support.ant.PropertyEvaluator; |
74 |
import org.netbeans.spi.project.support.ant.ReferenceHelper; |
75 |
import org.netbeans.spi.project.support.ant.SourcesHelper; |
76 |
import org.openide.filesystems.FileObject; |
77 |
import org.openide.filesystems.FileUtil; |
78 |
import org.openide.filesystems.test.TestFileUtils; |
79 |
import org.openide.util.ChangeSupport; |
80 |
import org.openide.util.Lookup; |
81 |
import org.openide.util.Mutex; |
82 |
import org.openide.util.lookup.Lookups; |
83 |
import org.openide.util.test.MockLookup; |
84 |
import org.w3c.dom.Document; |
85 |
import org.w3c.dom.Element; |
86 |
|
87 |
/** |
88 |
* Test for #105645 functionality: build/generated-sources/NAME/ roots. |
89 |
*/ |
90 |
public class GeneratedSourceRootTest extends NbTestCase { |
91 |
|
92 |
public GeneratedSourceRootTest(String n) { |
93 |
super(n); |
94 |
} |
95 |
|
96 |
public void testSourceRoots() throws Exception { |
97 |
Project p = createTestProject(true); |
98 |
FileObject d = p.getProjectDirectory(); |
99 |
FileObject src = d.getFileObject("src"); |
100 |
FileObject stuff = d.getFileObject("build/generated-sources/stuff"); |
101 |
SourceGroup[] groups = ProjectUtils.getSources(p).getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA); |
102 |
assertEquals(2, groups.length); |
103 |
assertEquals(src, groups[0].getRootFolder()); |
104 |
assertEquals(d.getFileObject("test"), groups[1].getRootFolder()); |
105 |
ClassPath sourcePath = ClassPath.getClassPath(src, ClassPath.SOURCE); |
106 |
assertEquals(Arrays.asList(src, stuff), Arrays.asList(sourcePath.getRoots())); |
107 |
FileObject moreStuff = FileUtil.createFolder(d, "build/generated-sources/morestuff"); |
108 |
assertEquals(Arrays.asList(src, stuff, moreStuff), Arrays.asList(sourcePath.getRoots())); |
109 |
ClassPath compile = ClassPath.getClassPath(src, ClassPath.COMPILE); |
110 |
assertEquals(compile, ClassPath.getClassPath(stuff, ClassPath.COMPILE)); |
111 |
assertEquals(compile, ClassPath.getClassPath(moreStuff, ClassPath.COMPILE)); |
112 |
assertEquals(ClassPath.getClassPath(src, ClassPath.EXECUTE), ClassPath.getClassPath(stuff, ClassPath.EXECUTE)); |
113 |
assertEquals(ClassPath.getClassPath(src, ClassPath.BOOT), ClassPath.getClassPath(stuff, ClassPath.BOOT)); |
114 |
d.getFileObject("build").delete(); |
115 |
assertEquals(Arrays.asList(src), Arrays.asList(sourcePath.getRoots())); |
116 |
} |
117 |
|
118 |
public void testMiscellaneousQueries() throws Exception { |
119 |
Project p = createTestProject(true); |
120 |
FileObject d = p.getProjectDirectory(); |
121 |
FileObject src = d.getFileObject("src"); |
122 |
FileObject test = d.getFileObject("test"); |
123 |
FileObject stuff = d.getFileObject("build/generated-sources/stuff"); |
124 |
URL classes = new URL(d.getURL(), "build/classes/"); |
125 |
URL testClasses = new URL(d.getURL(), "build/test/classes/"); |
126 |
FileObject xgen = stuff.getFileObject("net/nowhere/XGen.java"); |
127 |
assertEquals(Arrays.asList(src, stuff), Arrays.asList(SourceForBinaryQuery.findSourceRoots(classes).getRoots())); |
128 |
assertEquals(Arrays.asList(test), Arrays.asList(SourceForBinaryQuery.findSourceRoots(testClasses).getRoots())); |
129 |
assertEquals(Collections.singletonList(classes), Arrays.asList(BinaryForSourceQuery.findBinaryRoots(src.getURL()).getRoots())); |
130 |
assertEquals(Collections.singletonList(testClasses), Arrays.asList(BinaryForSourceQuery.findBinaryRoots(test.getURL()).getRoots())); |
131 |
assertEquals(Collections.singletonList(classes), Arrays.asList(BinaryForSourceQuery.findBinaryRoots(stuff.getURL()).getRoots())); |
132 |
assertEquals(Collections.singletonList(src.getURL()), Arrays.asList(UnitTestForSourceQuery.findSources(test))); |
133 |
assertEquals(Collections.singletonList(test.getURL()), Arrays.asList(UnitTestForSourceQuery.findUnitTests(src))); |
134 |
assertEquals("1.5", SourceLevelQuery.getSourceLevel(stuff)); |
135 |
FileBuiltQuery.Status status = FileBuiltQuery.getStatus(xgen); |
136 |
assertNotNull(status); |
137 |
assertFalse(status.isBuilt()); |
138 |
FileUtil.createData(d, "build/classes/net/nowhere/XGen.class"); |
139 |
assertTrue(status.isBuilt()); |
140 |
assertEquals("ISO-8859-2", FileEncodingQuery.getEncoding(xgen).name()); |
141 |
// check also dynamic changes in set of gensrc roots: |
142 |
FileObject moreStuff = FileUtil.createFolder(d, "build/generated-sources/morestuff"); |
143 |
FileObject ygen = FileUtil.createData(moreStuff, "net/nowhere/YGen.java"); |
144 |
assertEquals(Arrays.asList(src, stuff, moreStuff), Arrays.asList(SourceForBinaryQuery.findSourceRoots(classes).getRoots())); |
145 |
assertEquals(Collections.singletonList(classes), Arrays.asList(BinaryForSourceQuery.findBinaryRoots(moreStuff.getURL()).getRoots())); |
146 |
// XXX should previously created Result objects fire changes? ideally yes, but probably unnecessary |
147 |
assertEquals("1.5", SourceLevelQuery.getSourceLevel(moreStuff)); |
148 |
status = FileBuiltQuery.getStatus(ygen); |
149 |
assertNotNull(status); |
150 |
assertFalse(status.isBuilt()); |
151 |
FileUtil.createData(d, "build/classes/net/nowhere/YGen.class"); |
152 |
assertTrue(status.isBuilt()); |
153 |
assertEquals("ISO-8859-2", FileEncodingQuery.getEncoding(ygen).name()); |
154 |
d.getFileObject("build").delete(); |
155 |
assertEquals(Arrays.asList(src), Arrays.asList(SourceForBinaryQuery.findSourceRoots(classes).getRoots())); |
156 |
} |
157 |
|
158 |
public void testFirstGenSrcAddedDynamically() throws Exception { |
159 |
Project p = createTestProject(false); |
160 |
FileObject d = p.getProjectDirectory(); |
161 |
FileObject src = d.getFileObject("src"); |
162 |
URL classes = new URL(d.getURL(), "build/classes/"); |
163 |
ClassPath sourcePath = ClassPath.getClassPath(src, ClassPath.SOURCE); |
164 |
assertEquals(Arrays.asList(src), Arrays.asList(sourcePath.getRoots())); |
165 |
assertEquals(Arrays.asList(src), Arrays.asList(SourceForBinaryQuery.findSourceRoots(classes).getRoots())); |
166 |
// now add the first gensrc root: |
167 |
FileObject stuff = FileUtil.createFolder(d, "build/generated-sources/stuff"); |
168 |
FileObject xgen = FileUtil.createData(stuff, "net/nowhere/XGen.java"); |
169 |
assertEquals(Arrays.asList(src, stuff), Arrays.asList(sourcePath.getRoots())); |
170 |
assertEquals(ClassPath.getClassPath(src, ClassPath.COMPILE), ClassPath.getClassPath(stuff, ClassPath.COMPILE)); |
171 |
assertEquals(Arrays.asList(src, stuff), Arrays.asList(SourceForBinaryQuery.findSourceRoots(classes).getRoots())); |
172 |
assertEquals(Collections.singletonList(classes), Arrays.asList(BinaryForSourceQuery.findBinaryRoots(stuff.getURL()).getRoots())); |
173 |
FileBuiltQuery.Status status = FileBuiltQuery.getStatus(xgen); |
174 |
assertNotNull(status); |
175 |
assertFalse(status.isBuilt()); |
176 |
FileUtil.createData(d, "build/classes/net/nowhere/XGen.class"); |
177 |
assertTrue(status.isBuilt()); |
178 |
} |
179 |
|
180 |
protected @Override void setUp() throws Exception { |
181 |
clearWorkDir(); |
182 |
MockLookup.setInstances(new TestAntBasedProjectType()); |
183 |
} |
184 |
|
185 |
private Project createTestProject(boolean initGenRoot) throws Exception { |
186 |
final FileObject dir = FileUtil.toFileObject(getWorkDir()); |
187 |
TestFileUtils.writeFile(dir, "src/net/nowhere/X.java", |
188 |
"package net.nowhere; public class X {}"); |
189 |
TestFileUtils.writeFile(dir, "test/net/nowhere/XTest.java", |
190 |
"package net.nowhere; public class XTest {}"); |
191 |
if (initGenRoot) { |
192 |
TestFileUtils.writeFile(dir, "build/generated-sources/stuff/net/nowhere/XGen.java", |
193 |
"package net.nowhere; public class XGen {}"); |
194 |
} |
195 |
return ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction<Project>() { |
196 |
public Project run() throws Exception { |
197 |
AntProjectHelper h = ProjectGenerator.createProject(dir, "test"); |
198 |
EditableProperties pp = h.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH); |
199 |
pp.setProperty("src.dir", "src"); |
200 |
pp.setProperty("test.src.dir", "test"); |
201 |
pp.setProperty("build.dir", "build"); |
202 |
pp.setProperty("build.classes.dir", "${build.dir}/classes"); |
203 |
pp.setProperty("build.test.classes.dir", "${build.dir}/test/classes"); |
204 |
pp.setProperty("build.generated.dir", "${build.dir}/generated-sources"); |
205 |
pp.setProperty("javac.classpath", "lib.jar"); |
206 |
pp.setProperty("javac.test.classpath", "${javac.classpath}:junit.jar"); |
207 |
pp.setProperty("run.classpath", "${javac.classpath}:${build.classes.dir}:runlib.jar"); |
208 |
pp.setProperty("run.test.classpath", "${javac.test.classpath}:${build.test.classes.dir}:runlib.jar"); |
209 |
pp.setProperty("dist.dir", "dist"); |
210 |
pp.setProperty("dist.jar", "${dist.dir}/x.jar"); |
211 |
pp.setProperty("javac.source", "1.5"); |
212 |
pp.setProperty("encoding", "ISO-8859-2"); |
213 |
h.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, pp); |
214 |
Element data = h.getPrimaryConfigurationData(true); |
215 |
Document doc = data.getOwnerDocument(); |
216 |
((Element) data.appendChild(doc.createElementNS(NS, "source-roots")). |
217 |
appendChild(doc.createElementNS(NS, "root"))). |
218 |
setAttribute("id", "src.dir"); |
219 |
((Element) data.appendChild(doc.createElementNS(NS, "test-roots")). |
220 |
appendChild(doc.createElementNS(NS, "root"))). |
221 |
setAttribute("id", "test.src.dir"); |
222 |
h.putPrimaryConfigurationData(data, true); |
223 |
Project p = ProjectManager.getDefault().findProject(dir); |
224 |
assertEquals(TestProject.class, p.getClass()); |
225 |
ProjectManager.getDefault().saveProject(p); |
226 |
return p; |
227 |
} |
228 |
}); |
229 |
} |
230 |
|
231 |
private static final String NS = "urn:test"; |
232 |
private static class TestAntBasedProjectType implements AntBasedProjectType { |
233 |
public String getType() { |
234 |
return "test"; |
235 |
} |
236 |
public Project createProject(AntProjectHelper helper) throws IOException { |
237 |
return new TestProject(helper); |
238 |
} |
239 |
public String getPrimaryConfigurationDataElementName(boolean shared) { |
240 |
return "data"; |
241 |
} |
242 |
public String getPrimaryConfigurationDataElementNamespace(boolean shared) { |
243 |
return NS; |
244 |
} |
245 |
} |
246 |
private static class TestProject implements Project { |
247 |
private final AntProjectHelper helper; |
248 |
private Lookup lookup; |
249 |
TestProject(AntProjectHelper helper) { |
250 |
this.helper = helper; |
251 |
} |
252 |
public FileObject getProjectDirectory() { |
253 |
return helper.getProjectDirectory(); |
254 |
} |
255 |
public synchronized Lookup getLookup() { |
256 |
if (lookup == null) { |
257 |
PropertyEvaluator evaluator = helper.getStandardPropertyEvaluator(); |
258 |
AuxiliaryConfiguration aux = helper.createAuxiliaryConfiguration(); |
259 |
ReferenceHelper refHelper = new ReferenceHelper(helper, aux, evaluator); |
260 |
UpdateHelper upHelper = new UpdateHelper(new UpdateImplementation() { |
261 |
public boolean isCurrent() {return true;} |
262 |
public boolean canUpdate() {throw new AssertionError();} |
263 |
public void saveUpdate(EditableProperties props) throws IOException {throw new AssertionError();} |
264 |
public Element getUpdatedSharedConfigurationData() {throw new AssertionError();} |
265 |
public EditableProperties getUpdatedProjectProperties() {throw new AssertionError();} |
266 |
}, helper); |
267 |
SourceRoots src = SourceRoots.create(upHelper, evaluator, refHelper, NS, |
268 |
"source-roots", false, "src.{0}{1}.dir"); |
269 |
SourceRoots test = SourceRoots.create(upHelper, evaluator, refHelper, NS, |
270 |
"test-roots", false, "test.{0}{1}.dir"); |
271 |
lookup = Lookups.fixed( |
272 |
aux, |
273 |
new TestSources(helper, evaluator, src, test), |
274 |
new ClassPathProviderImpl(this.helper, evaluator, src, test), |
275 |
QuerySupport.createCompiledSourceForBinaryQuery(helper, evaluator, src, test), |
276 |
QuerySupport.createBinaryForSourceQueryImplementation(src, test, helper, evaluator), |
277 |
QuerySupport.createUnitTestForSourceQuery(src, test), |
278 |
QuerySupport.createSourceLevelQuery(evaluator), |
279 |
QuerySupport.createFileBuiltQuery(helper, evaluator, src, test), |
280 |
QuerySupport.createFileEncodingQuery(evaluator, "encoding") |
281 |
); |
282 |
} |
283 |
return lookup; |
284 |
} |
285 |
} |
286 |
/** Simplified copy of J2SESources. */ |
287 |
private static class TestSources implements Sources, PropertyChangeListener, ChangeListener { |
288 |
private final AntProjectHelper helper; |
289 |
private final PropertyEvaluator evaluator; |
290 |
private final SourceRoots sourceRoots; |
291 |
private final SourceRoots testRoots; |
292 |
private SourcesHelper sourcesHelper; |
293 |
private Sources delegate; |
294 |
private final ChangeSupport changeSupport = new ChangeSupport(this); |
295 |
TestSources(AntProjectHelper helper, PropertyEvaluator evaluator, SourceRoots sourceRoots, SourceRoots testRoots) { |
296 |
this.helper = helper; |
297 |
this.evaluator = evaluator; |
298 |
this.evaluator.addPropertyChangeListener(this); |
299 |
this.sourceRoots = sourceRoots; |
300 |
this.sourceRoots.addPropertyChangeListener(this); |
301 |
this.testRoots = testRoots; |
302 |
this.testRoots.addPropertyChangeListener(this); |
303 |
initSources(); |
304 |
} |
305 |
public SourceGroup[] getSourceGroups(final String type) { |
306 |
return ProjectManager.mutex().readAccess(new Mutex.Action<SourceGroup[]>() { |
307 |
public SourceGroup[] run() { |
308 |
Sources _delegate; |
309 |
synchronized (TestSources.this) { |
310 |
if (delegate == null) { |
311 |
delegate = initSources(); |
312 |
delegate.addChangeListener(TestSources.this); |
313 |
} |
314 |
_delegate = delegate; |
315 |
} |
316 |
return _delegate.getSourceGroups(type); |
317 |
} |
318 |
}); |
319 |
} |
320 |
private Sources initSources() { |
321 |
sourcesHelper = new SourcesHelper(helper, evaluator); |
322 |
register(sourceRoots); |
323 |
register(testRoots); |
324 |
sourcesHelper.addNonSourceRoot("${build.dir}"); |
325 |
return sourcesHelper.createSources(); |
326 |
} |
327 |
private void register(SourceRoots roots) { |
328 |
String[] propNames = roots.getRootProperties(); |
329 |
String[] rootNames = roots.getRootNames(); |
330 |
for (int i = 0; i < propNames.length; i++) { |
331 |
String prop = propNames[i]; |
332 |
String displayName = roots.getRootDisplayName(rootNames[i], prop); |
333 |
String loc = "${" + prop + "}"; |
334 |
sourcesHelper.addPrincipalSourceRoot(loc, displayName, null, null); |
335 |
sourcesHelper.addTypedSourceRoot(loc, JavaProjectConstants.SOURCES_TYPE_JAVA, displayName, null, null); |
336 |
} |
337 |
} |
338 |
public void addChangeListener(ChangeListener changeListener) { |
339 |
changeSupport.addChangeListener(changeListener); |
340 |
} |
341 |
public void removeChangeListener(ChangeListener changeListener) { |
342 |
changeSupport.removeChangeListener(changeListener); |
343 |
} |
344 |
private void fireChange() { |
345 |
synchronized (this) { |
346 |
if (delegate != null) { |
347 |
delegate.removeChangeListener(this); |
348 |
delegate = null; |
349 |
} |
350 |
} |
351 |
changeSupport.fireChange(); |
352 |
} |
353 |
public void propertyChange(PropertyChangeEvent evt) { |
354 |
String propName = evt.getPropertyName(); |
355 |
if (SourceRoots.PROP_ROOT_PROPERTIES.equals(propName) || "build.dir".equals(propName)) { |
356 |
this.fireChange(); |
357 |
} |
358 |
} |
359 |
public void stateChanged(ChangeEvent event) { |
360 |
this.fireChange(); |
361 |
} |
362 |
} |
363 |
|
364 |
} |