--- a/java.j2seproject/nbproject/project.xml +++ a/java.j2seproject/nbproject/project.xml @@ -180,7 +180,7 @@ 1 - 1.25 + 1.26 --- a/java.j2seproject/src/org/netbeans/modules/java/j2seproject/J2SESources.java +++ a/java.j2seproject/src/org/netbeans/modules/java/j2seproject/J2SESources.java @@ -160,7 +160,7 @@ ProjectManager.mutex().postWriteRequest(new Runnable() { public void run() { if (!externalRootsRegistered) { - sourcesHelper.registerExternalRoots(FileOwnerQuery.EXTERNAL_ALGORITHM_TRANSIENT); + sourcesHelper.registerExternalRoots(FileOwnerQuery.EXTERNAL_ALGORITHM_TRANSIENT, false); externalRootsRegistered = true; } } --- a/project.ant/apichanges.xml +++ a/project.ant/apichanges.xml @@ -104,7 +104,25 @@ - + + + Added method SourcesHelper.registerExternalRoots with minimalSubfolders parameter + + + + + +

+ Added SourcesHelper.registerExternalRoots with additional parameter + minimalSubfolders controlling how the roots having an explicit include + list are registered. When true only those subfolders which are included + (or folders directly containing included files) will be registered, otherwise the + whole source root is registered. +

+
+ + +
Enhance AntArtifact support with ability to specify build.xml location and name --- a/project.ant/manifest.mf +++ a/project.ant/manifest.mf @@ -1,6 +1,6 @@ Manifest-Version: 1.0 OpenIDE-Module: org.netbeans.modules.project.ant/1 -OpenIDE-Module-Specification-Version: 1.25 +OpenIDE-Module-Specification-Version: 1.26 OpenIDE-Module-Layer: org/netbeans/modules/project/ant/resources/mf-layer.xml OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/project/ant/Bundle.properties OpenIDE-Module-Install: org/netbeans/modules/project/ant/AntProjectModule.class --- a/project.ant/src/org/netbeans/spi/project/support/ant/SourcesHelper.java +++ a/project.ant/src/org/netbeans/spi/project/support/ant/SourcesHelper.java @@ -100,7 +100,7 @@ } return project.resolveFile(val); } - public Collection getIncludeRoots() { + public Collection getIncludeRoots(boolean minimalSubfolders) { File loc = getActualLocation(); if (loc != null) { FileObject fo = FileUtil.toFileObject(loc); @@ -258,9 +258,12 @@ @Override - public Collection getIncludeRoots() { - Collection supe = super.getIncludeRoots(); - if (supe.size() == 1) { + public Collection getIncludeRoots(boolean minimalSubfolders) { + Collection supe = super.getIncludeRoots(minimalSubfolders); + if (!minimalSubfolders) { + return supe; + } + else if (supe.size() == 1) { Set roots = new HashSet(); computeIncludeExcludePatterns(); for (File r : matcher.findIncludedRoots()) { @@ -296,6 +299,7 @@ private final List ownedFiles = new ArrayList(); private final List typedSourceRoots = new ArrayList(); private int registeredRootAlgorithm; + private boolean minimalSubfolders; /** * If not null, external roots that we registered the last time. * Used when a property change is encountered, to see if the set of external @@ -513,10 +517,65 @@ * given SourcesHelper object */ public void registerExternalRoots(int algorithm) throws IllegalArgumentException, IllegalStateException { + registerExternalRoots(algorithm, true); + } + + /** + * Register all external source or non-source roots using {@link FileOwnerQuery#markExternalOwner}. + *

+ * Only roots added by {@link #addPrincipalSourceRoot} and {@link #addNonSourceRoot} + * are considered. They are registered if (and only if) they in fact fall + * outside of the project directory, and of course only if the folders really + * exist on disk. Currently it is not defined when this file existence check + * is done (e.g. when this method is first called, or periodically) or whether + * folders which are created subsequently will be registered, so project type + * providers are encouraged to create all desired external roots before calling + * this method. + *

+ *

+ * If the actual value of the location changes (due to changes being + * fired from the property evaluator), roots which were previously internal + * and are now external will be registered, and roots which were previously + * external and are now internal will be unregistered. The (un-)registration + * will be done using the same algorithm as was used initially. + *

+ *

+ * If a minimalSubfolders is true and an explicit include list is configured + * for a principal source root, only those subfolders which are included + * (or folders directly containing included files) + * will be registered, otherwise the whole source root is registered. + * Note that the source root, or an included subfolder, will + * be registered even if it contains excluded files or folders beneath it. + *

+ *

+ * Calling this method causes the helper object to hold strong references to the + * current external roots, which helps a project satisfy the requirements of + * {@link FileOwnerQuery#EXTERNAL_ALGORITHM_TRANSIENT}. + *

+ *

+ * You may not call this method inside the project's constructor, as + * it requires the actual project to exist and be registered in {@link ProjectManager}. + * Typically you would use {@link org.openide.util.Mutex#postWriteRequest} to run it + * later, if you were creating the helper in your constructor, since the project construction + * normally occurs in read access. + *

+ * @param algorithm an external root registration algorithm as per + * {@link FileOwnerQuery#markExternalOwner} + * @param minimalSubfolders controls how the roots having an explicit include list + * are registered. When true only those subfolders which are included + * (or folders directly containing included files) will be registered, + * otherwise the whole source root is registered. + * @throws IllegalArgumentException if the algorithm is unrecognized + * @throws IllegalStateException if this method is called more than once on a + * given SourcesHelper object + * @since 1.26 + */ + public void registerExternalRoots (int algorithm, boolean minimalSubfolders) throws IllegalArgumentException, IllegalStateException { if (lastRegisteredRoots != null) { throw new IllegalStateException("registerExternalRoots was already called before"); // NOI18N } registeredRootAlgorithm = algorithm; + this.minimalSubfolders = minimalSubfolders; remarkExternalRoots(); } @@ -539,7 +598,7 @@ // that was last computed, and just check if that has changed... otherwise we wind // up calling APH.resolveFileObject repeatedly (for each property change) for (Root r : allRoots) { - for (FileObject loc : r.getIncludeRoots()) { + for (FileObject loc : r.getIncludeRoots(minimalSubfolders)) { if (FileUtil.getRelativePath(pdir, loc) != null) { // Inside projdir already. Skip it. continue; --- a/project.ant/test/unit/src/org/netbeans/spi/project/support/ant/SourcesHelperTest.java +++ a/project.ant/test/unit/src/org/netbeans/spi/project/support/ant/SourcesHelperTest.java @@ -562,6 +562,59 @@ assertExcluded("but that does not apply to other children", gg1, "javax/lang/Foo.java"); // } + + public void testMinimalSubfolders () throws Exception { + scratch = TestUtil.makeScratchDir(this); // have our own setup + maindir = scratch.createFolder("dir"); + projdir = maindir.createFolder("proj-dir"); + src1dir = maindir.createFolder("src1"); + + // + FileUtil.createData(src1dir, "com/sun/tools/javac/Main.java"); + FileUtil.createData(src1dir, "com/sun/tools/internal/ws/processor/model/java/JavaArrayType.java"); + FileUtil.createData(src1dir, "sun/tools/javac/Main.java"); + FileUtil.createData(src1dir, "sunw/io/Serializable.java"); + FileUtil.createData(src1dir, "java/lang/Byte.java"); + FileUtil.createData(src1dir, "java/text/resources/Messages.properties"); + FileUtil.createData(src1dir, "java/text/resources/Messages_zh.properties"); + FileUtil.createData(src1dir, "java/text/resources/Messages_zh_TW.properties"); + FileUtil.createData(src1dir, "java/text/resources/x_y/z.properties"); + // + + // + h = ProjectGenerator.createProject(projdir, "test"); + project = ProjectManager.getDefault().findProject(projdir); + EditableProperties p = h.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH); + p.setProperty("src1.dir", "../src1"); + // + // + p.setProperty("src1.includes", "com/sun/tools/**"); + // + // + h.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, p); + ProjectManager.getDefault().saveProject(project); + //minimalSubfolders = true + sh = new SourcesHelper(h, h.getStandardPropertyEvaluator()); + sh.addPrincipalSourceRoot("${src1.dir}", "${src1.includes}", "${src1.excludes}", "Sources #1", null, null); + sh.addTypedSourceRoot("${src1.dir}", "${src1.includes}", "${src1.excludes}", "java", "Packages #1", null, null); + sh.registerExternalRoots(FileOwnerQuery.EXTERNAL_ALGORITHM_TRANSIENT, true); + Sources s = sh.createSources(); + SourceGroup[] groups = s.getSourceGroups("java"); + SourceGroup g1 = groups[0]; + assertEquals("Packages #1", g1.getDisplayName()); + assertNull(FileOwnerQuery.getOwner(src1dir)); + //minimalSubfolders = false + sh = new SourcesHelper(h, h.getStandardPropertyEvaluator()); + sh.addPrincipalSourceRoot("${src1.dir}", "${src1.includes}", "${src1.excludes}", "Sources #1", null, null); + sh.addTypedSourceRoot("${src1.dir}", "${src1.includes}", "${src1.excludes}", "java", "Packages #1", null, null); + sh.registerExternalRoots(FileOwnerQuery.EXTERNAL_ALGORITHM_TRANSIENT, false); + s = sh.createSources(); + groups = s.getSourceGroups("java"); + g1 = groups[0]; + assertEquals("Packages #1", g1.getDisplayName()); + assertEquals(project, FileOwnerQuery.getOwner(src1dir)); + } + private static void assertIncluded(String message, SourceGroup g, String resource) { FileObject f = g.getRootFolder().getFileObject(resource); assertNotNull(resource, f);