jglick's additions to: http://lahoda.info/hg/nb-patches/raw-file/tip/170231-excludes-on-compile-classpath diff --git a/api.java.classpath/src/org/netbeans/api/java/classpath/ClassPath.java b/api.java.classpath/src/org/netbeans/api/java/classpath/ClassPath.java --- a/api.java.classpath/src/org/netbeans/api/java/classpath/ClassPath.java +++ b/api.java.classpath/src/org/netbeans/api/java/classpath/ClassPath.java @@ -57,7 +57,6 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -69,7 +68,9 @@ import org.netbeans.spi.java.classpath.ClassPathImplementation; import org.netbeans.spi.java.classpath.ClassPathProvider; import org.netbeans.spi.java.classpath.FilteringPathResourceImplementation; +import org.netbeans.spi.java.classpath.FilteringPathResourceImplementation2; import org.netbeans.spi.java.classpath.PathResourceImplementation; +import org.netbeans.spi.java.classpath.support.ClassPathSupport; import org.openide.filesystems.FileAttributeEvent; import org.openide.filesystems.FileChangeListener; import org.openide.filesystems.FileEvent; @@ -739,6 +740,15 @@ } /** + * Returns the {@link FilteringPathResourceImplementation2#algorithm} of the filter. + * @return an algorithm, or null if no algorithm is specified + * @since XXX + */ + public String includeAlgorithm() { + return filter instanceof FilteringPathResourceImplementation2 ? ((FilteringPathResourceImplementation2) filter).algorithm() : null; + } + + /** * Check whether a file is included in this entry. * @param file a URL beneath @{link #getURL} * @return true if it is {@link FilteringPathResourceImplementation#includes included} diff --git a/api.java.classpath/src/org/netbeans/modules/java/classpath/SimplePathResourceImplementation.java b/api.java.classpath/src/org/netbeans/modules/java/classpath/SimplePathResourceImplementation.java --- a/api.java.classpath/src/org/netbeans/modules/java/classpath/SimplePathResourceImplementation.java +++ b/api.java.classpath/src/org/netbeans/modules/java/classpath/SimplePathResourceImplementation.java @@ -45,7 +45,7 @@ import org.netbeans.spi.java.classpath.ClassPathImplementation; import java.net.URL; -import org.netbeans.spi.java.classpath.FilteringPathResourceImplementation; +import org.netbeans.spi.java.classpath.FilteringPathResourceImplementation2; import org.netbeans.spi.java.classpath.support.ClassPathSupport.ResourceAcceptor; @@ -53,7 +53,7 @@ * Provides implementation of the single rooted PathResoruceImplementation */ -public final class SimplePathResourceImplementation extends PathResourceBase implements FilteringPathResourceImplementation { +public final class SimplePathResourceImplementation extends PathResourceBase implements FilteringPathResourceImplementation2 { private URL[] url; private final ResourceAcceptor acceptor; @@ -100,4 +100,8 @@ public boolean includes(URL root, String resource) { return acceptor == null || acceptor.includes(root, resource); } + + public String algorithm() { + return acceptor != null ? acceptor.algorithm(url[0]) : null; + } } diff --git a/api.java.classpath/src/org/netbeans/spi/java/classpath/FilteringPathResourceImplementation.java b/api.java.classpath/src/org/netbeans/spi/java/classpath/FilteringPathResourceImplementation.java --- a/api.java.classpath/src/org/netbeans/spi/java/classpath/FilteringPathResourceImplementation.java +++ b/api.java.classpath/src/org/netbeans/spi/java/classpath/FilteringPathResourceImplementation.java @@ -45,6 +45,7 @@ /** * SPI interface for a classpath entry which can include or exclude particular files. + *

Implement {@link FilteringPathResourceImplementation2} if possible. * @author Jesse Glick * @see "issue #49026" * @since org.netbeans.api.java/1 1.13 diff --git a/api.java.classpath/src/org/netbeans/spi/java/classpath/FilteringPathResourceImplementation2.java b/api.java.classpath/src/org/netbeans/spi/java/classpath/FilteringPathResourceImplementation2.java new file mode 100644 --- /dev/null +++ b/api.java.classpath/src/org/netbeans/spi/java/classpath/FilteringPathResourceImplementation2.java @@ -0,0 +1,60 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2009 Sun Microsystems, Inc. + */ + +package org.netbeans.spi.java.classpath; + +/** + * Extended path resource implementation that can be used in caches. + * @since XXX + */ +public interface FilteringPathResourceImplementation2 extends FilteringPathResourceImplementation { + + /** + * Used to track possible changes in includes across JVM sessions, + * when {@link #PROP_INCLUDES} would not be fired. + *

If two implementations return the same (non-null) algorithm token, they must behave + * identically on identical calls to {@link #includes}. If they behave + * identically, it is desirable for them to return the same token. + *

For example, an implementation based on Ant patternsets could somehow + * encode the list of include and exclude patterns into a string. + * @return an arbitrary string, or null to avoid implementing + */ + String algorithm(); + +} diff --git a/api.java.classpath/src/org/netbeans/spi/java/classpath/support/ClassPathSupport.java b/api.java.classpath/src/org/netbeans/spi/java/classpath/support/ClassPathSupport.java --- a/api.java.classpath/src/org/netbeans/spi/java/classpath/support/ClassPathSupport.java +++ b/api.java.classpath/src/org/netbeans/spi/java/classpath/support/ClassPathSupport.java @@ -214,8 +214,13 @@ return ClassPathFactory.createClassPath (createProxyClassPathImplementation(impls)); } + /** + * XXX description + * @since XXX + */ public static interface ResourceAcceptor { public boolean includes(URL root, String resource); + String algorithm(URL root); } } diff --git a/apisupport.project/src/org/netbeans/modules/apisupport/project/ManifestManager.java b/apisupport.project/src/org/netbeans/modules/apisupport/project/ManifestManager.java --- a/apisupport.project/src/org/netbeans/modules/apisupport/project/ManifestManager.java +++ b/apisupport.project/src/org/netbeans/modules/apisupport/project/ManifestManager.java @@ -421,7 +421,7 @@ } public @Override String toString() { - return "PackageExport[" + pkg + (recursive ? "/**" : "") + "]"; // NOI18N + return pkg + (recursive ? ".**" : ".*"); // NOI18N } } diff --git a/apisupport.project/src/org/netbeans/modules/apisupport/project/queries/ClassPathProviderImpl.java b/apisupport.project/src/org/netbeans/modules/apisupport/project/queries/ClassPathProviderImpl.java --- a/apisupport.project/src/org/netbeans/modules/apisupport/project/queries/ClassPathProviderImpl.java +++ b/apisupport.project/src/org/netbeans/modules/apisupport/project/queries/ClassPathProviderImpl.java @@ -47,9 +47,9 @@ import java.io.File; import java.net.URL; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; @@ -59,6 +59,7 @@ import java.util.regex.Pattern; import org.netbeans.api.java.classpath.ClassPath; import org.netbeans.api.java.classpath.JavaClassPathConstants; +import org.netbeans.modules.apisupport.project.ManifestManager; import org.netbeans.spi.java.classpath.ClassPathFactory; import org.netbeans.spi.java.classpath.ClassPathImplementation; import org.netbeans.spi.java.classpath.ClassPathProvider; @@ -66,7 +67,8 @@ import org.netbeans.modules.apisupport.project.NbModuleProject; import org.netbeans.modules.apisupport.project.NbModuleProjectType; import org.netbeans.modules.apisupport.project.Util; -import org.netbeans.spi.java.classpath.FilteringPathResourceImplementation; +import org.netbeans.modules.apisupport.project.universe.ModuleEntry; +import org.netbeans.modules.apisupport.project.universe.ModuleList; import org.netbeans.spi.java.classpath.PathResourceImplementation; import org.netbeans.spi.java.classpath.support.ClassPathSupport.ResourceAcceptor; import org.netbeans.spi.java.project.classpath.support.ProjectClassPathSupport; @@ -264,13 +266,61 @@ } ClassPathImplementation result = ProjectClassPathSupport.createPropertyBasedClassPathImplementation( project.getProjectDirectoryFile(), project.evaluator(), new String[] {prop}, new ResourceAcceptor() { - + // XXX cache some of this for performance (need to listen to project.xml changes) public boolean includes(URL root, String resource) { - boolean result= resource.contains("/api/") || resource.contains("/spi/"); - - System.err.println(resource + "=" + result); - - return result; + File jar = FileUtil.archiveOrDirForURL(root); + if (jar != null) { + for (ModuleEntry entry : ModuleList.getKnownEntries(jar)) { + // Comes from a foreign module; check for public package status. + int idx = resource.lastIndexOf('/'); + if (idx == -1) { + // Default package never accessible. + return false; + } + String pkg = resource.substring(0, idx).replace('/', '.'); + for (ManifestManager.PackageExport export : entry.getPublicPackages()) { + String expPkg = export.getPackage(); + if (pkg.equals(expPkg) || export.isRecursive() && pkg.startsWith(expPkg + ".")) { + return true; + } + } + return haveImplDepOn(entry); + } + } + return true; + } + public String algorithm(URL root) { + File jar = FileUtil.archiveOrDirForURL(root); + if (jar != null) { + for (ModuleEntry entry : ModuleList.getKnownEntries(jar)) { + return haveImplDepOn(entry) ? "impl" : Arrays.toString(entry.getPublicPackages()); // NOI18N + } + } + return null; + } + private boolean haveImplDepOn(ModuleEntry entry) { + Element data = project.getPrimaryConfigurationData(); + Element moduleDependencies = Util.findElement(data, + "module-dependencies", NbModuleProjectType.NAMESPACE_SHARED); // NOI18N + for (Element dep : Util.findSubElements(moduleDependencies)) { + Element cnbEl = Util.findElement(dep, "code-name-base", // NOI18N + NbModuleProjectType.NAMESPACE_SHARED); + String cnb = Util.findText(cnbEl); + if (!cnb.equals(entry.getCodeNameBase())) { + continue; + } + Element runDep = Util.findElement(dep, "run-dependency", // NOI18N + NbModuleProjectType.NAMESPACE_SHARED); + if (runDep == null) { + return true; // ??? + } + if (Util.findElement(runDep, "implementation-version", + NbModuleProjectType.NAMESPACE_SHARED) != null) { // NOI18N + return true; + } + return false; + } + return false; // not found? } }); diff --git a/java.api.common/src/org/netbeans/modules/java/api/common/classpath/SourcePathImplementation.java b/java.api.common/src/org/netbeans/modules/java/api/common/classpath/SourcePathImplementation.java --- a/java.api.common/src/org/netbeans/modules/java/api/common/classpath/SourcePathImplementation.java +++ b/java.api.common/src/org/netbeans/modules/java/api/common/classpath/SourcePathImplementation.java @@ -57,6 +57,7 @@ import org.netbeans.modules.java.api.common.project.ProjectProperties; import org.netbeans.spi.java.classpath.ClassPathImplementation; import org.netbeans.spi.java.classpath.FilteringPathResourceImplementation; +import org.netbeans.spi.java.classpath.FilteringPathResourceImplementation2; import org.netbeans.spi.java.classpath.PathResourceImplementation; import org.netbeans.spi.java.classpath.support.ClassPathSupport; import org.netbeans.spi.project.support.ant.AntProjectHelper; @@ -161,7 +162,7 @@ if (this.resources == null) { List result = new ArrayList(roots.length); for (final URL root : roots) { - class PRI implements FilteringPathResourceImplementation, PropertyChangeListener { + class PRI implements FilteringPathResourceImplementation2, PropertyChangeListener { PropertyChangeSupport pcs = new PropertyChangeSupport(this); PathMatcher matcher; @@ -184,6 +185,10 @@ return matcher.matches(resource, true); } + public String algorithm() { + return evaluator.evaluate("+ ${" + ProjectProperties.INCLUDES + "} - ${" + ProjectProperties.EXCLUDES + "}"); // NOI18N + } + public ClassPathImplementation getContent() { return null; } diff --git a/java.project/src/org/netbeans/spi/java/project/support/ClassPathProviderMerger.java b/java.project/src/org/netbeans/spi/java/project/support/ClassPathProviderMerger.java --- a/java.project/src/org/netbeans/spi/java/project/support/ClassPathProviderMerger.java +++ b/java.project/src/org/netbeans/spi/java/project/support/ClassPathProviderMerger.java @@ -52,6 +52,7 @@ import org.netbeans.spi.java.classpath.ClassPathImplementation; import org.netbeans.spi.java.classpath.ClassPathProvider; import org.netbeans.spi.java.classpath.FilteringPathResourceImplementation; +import org.netbeans.spi.java.classpath.FilteringPathResourceImplementation2; import org.netbeans.spi.java.classpath.PathResourceImplementation; import org.netbeans.spi.project.LookupMerger; import org.openide.filesystems.FileObject; @@ -257,7 +258,7 @@ return new ProxyFilteringCPI(path); } - private static class ProxyFilteringCPI implements FilteringPathResourceImplementation, PropertyChangeListener { + private static class ProxyFilteringCPI implements FilteringPathResourceImplementation2, PropertyChangeListener { private final ClassPath classpath; private final PropertyChangeSupport changeSupport; @@ -307,6 +308,17 @@ this.changeSupport.firePropertyChange(PROP_INCLUDES, null, null); } } + + public String algorithm() { + if (classpath.entries().size() == 1) { + return classpath.entries().get(0).includeAlgorithm(); + } + StringBuilder b = new StringBuilder("["); + for (ClassPath.Entry ent : classpath.entries()) { + b.append(ent.includeAlgorithm()).append(";"); + } + return b.append("]").toString(); + } } diff --git a/java.source/src/org/netbeans/modules/java/source/classpath/CacheClassPath.java b/java.source/src/org/netbeans/modules/java/source/classpath/CacheClassPath.java --- a/java.source/src/org/netbeans/modules/java/source/classpath/CacheClassPath.java +++ b/java.source/src/org/netbeans/modules/java/source/classpath/CacheClassPath.java @@ -124,6 +124,9 @@ public boolean includes(URL root, String resource) { return entry.includes(resource); } + public String algorithm(URL root) { + return entry.includeAlgorithm(); + } }; URL url = entry.getURL(); URL[] sourceUrls;