This is an automated email from the ASF dual-hosted git repository. lkishalmi pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/netbeans.git
The following commit(s) were added to refs/heads/master by this push: new d13f34ba74 Gradle Project shall use the Java from the tooling not runtime. d13f34ba74 is described below commit d13f34ba7422948db84075f7772e15be4274e02b Author: Laszlo Kishalmi <laszlo.kisha...@gmail.com> AuthorDate: Sun Feb 4 07:23:37 2024 -0800 Gradle Project shall use the Java from the tooling not runtime. --- .../gradle/tooling/NbProjectInfoBuilder.java | 23 ++ .../modules/gradle/cache/ProjectInfoDiskCache.java | 2 +- java/gradle.java/apichanges.xml | 22 ++ java/gradle.java/manifest.mf | 1 + java/gradle.java/nbproject/project.properties | 3 +- java/gradle.java/nbproject/project.xml | 1 + .../gradle/java/api/GradleJavaProjectBuilder.java | 9 +- .../gradle/java/api/GradleJavaSourceSet.java | 17 ++ .../classpath/AbstractGradleClassPathImpl.java | 7 +- .../gradle/java/classpath/BootClassPathImpl.java | 43 ++-- .../java/classpath/ClassPathProviderImpl.java | 4 +- .../classpath/GlobalClassPathProviderImpl.java | 44 ++-- .../gradle/java/customizer/Bundle.properties | 1 + .../gradle/java/customizer/SourceSetPanel.form | 45 +++- .../gradle/java/customizer/SourceSetPanel.java | 49 +++- .../gradle/java/nodes/BootCPNodeFactory.java | 280 +++++---------------- .../java/spi/support/JavaToolchainSupport.java | 122 +++++++++ 17 files changed, 371 insertions(+), 302 deletions(-) diff --git a/extide/gradle/netbeans-gradle-tooling/src/main/java/org/netbeans/modules/gradle/tooling/NbProjectInfoBuilder.java b/extide/gradle/netbeans-gradle-tooling/src/main/java/org/netbeans/modules/gradle/tooling/NbProjectInfoBuilder.java index 0362bf0e2f..332c5360d0 100644 --- a/extide/gradle/netbeans-gradle-tooling/src/main/java/org/netbeans/modules/gradle/tooling/NbProjectInfoBuilder.java +++ b/extide/gradle/netbeans-gradle-tooling/src/main/java/org/netbeans/modules/gradle/tooling/NbProjectInfoBuilder.java @@ -105,9 +105,13 @@ import org.gradle.api.tasks.bundling.Jar; import org.gradle.api.tasks.testing.Test; import org.gradle.internal.resolve.ArtifactResolveException; import org.gradle.jvm.JvmLibrary; +import org.gradle.jvm.toolchain.JavaCompiler; import org.gradle.language.base.artifact.SourcesArtifact; import org.gradle.language.java.artifact.JavadocArtifact; import org.gradle.plugin.use.PluginId; +import org.gradle.api.provider.Property; +import org.gradle.jvm.toolchain.JavaInstallationMetadata; +import org.gradle.jvm.toolchain.JavaLauncher; import org.gradle.util.GradleVersion; import org.netbeans.modules.gradle.tooling.internal.NbProjectInfo; import org.netbeans.modules.gradle.tooling.internal.NbProjectInfo.Report; @@ -1205,6 +1209,13 @@ class NbProjectInfoBuilder { o.toString() ); } + + sinceGradle("6.7", () -> { + fetchJavaInstallationMetadata(compileTask).ifPresent( + (meta) -> model.getInfo().put(propBase + lang + "_compiler_java_home", meta.getInstallationPath().getAsFile()) + ); + }); + List<String> compilerArgs; compilerArgs = (List<String>) getProperty(compileTask, "options", "allCompilerArgs"); @@ -1311,6 +1322,18 @@ class NbProjectInfoBuilder { } } + private Optional<JavaInstallationMetadata> fetchJavaInstallationMetadata(Task task) { + Property<JavaLauncher> launcherProperty = (Property<JavaLauncher>) getProperty(task, "javaLauncher"); + if (launcherProperty != null && launcherProperty.isPresent()) { + return Optional.of(launcherProperty.get().getMetadata()); + } + Property<JavaCompiler> compilerProperty = (Property<JavaCompiler>) getProperty(task, "javaCompiler"); + if (compilerProperty != null && compilerProperty.isPresent()) { + return Optional.of(compilerProperty.get().getMetadata()); + } + return Optional.empty(); + } + private void detectArtifacts(NbProjectInfoModel model) { if (project.getPlugins().hasPlugin("java")) { model.getInfo().put("main_jar", getProperty(project, "jar", "archivePath")); diff --git a/extide/gradle/src/org/netbeans/modules/gradle/cache/ProjectInfoDiskCache.java b/extide/gradle/src/org/netbeans/modules/gradle/cache/ProjectInfoDiskCache.java index 5718378b2d..a195c37523 100644 --- a/extide/gradle/src/org/netbeans/modules/gradle/cache/ProjectInfoDiskCache.java +++ b/extide/gradle/src/org/netbeans/modules/gradle/cache/ProjectInfoDiskCache.java @@ -45,7 +45,7 @@ import org.netbeans.modules.gradle.spi.GradleFiles; public final class ProjectInfoDiskCache extends AbstractDiskCache<GradleFiles, QualifiedProjectInfo> { // Increase this number if new info is gathered from the projects. - private static final int COMPATIBLE_CACHE_VERSION = 24; + private static final int COMPATIBLE_CACHE_VERSION = 25; private static final String INFO_CACHE_FILE_NAME = "project-info.ser"; //NOI18N private static final Map<GradleFiles, ProjectInfoDiskCache> DISK_CACHES = Collections.synchronizedMap(new WeakHashMap<>()); diff --git a/java/gradle.java/apichanges.xml b/java/gradle.java/apichanges.xml index dfd5b57876..55a1019a96 100644 --- a/java/gradle.java/apichanges.xml +++ b/java/gradle.java/apichanges.xml @@ -83,6 +83,28 @@ is the proper place. <!-- ACTUAL CHANGES BEGIN HERE: --> <changes> + <change id="sourceset-compiler-javahome"> + <api name="gradle.java.api"/> + <summary>Support for per-language output directories</summary> + <version major="1" minor="26"/> + <date day="4" month="1" year="2024"/> + <author login="lkishalmi"/> + <compatibility semantic="compatible" addition="yes" deprecation="no"/> + <description> + <p> + Gradle 6.7 introduced Java Toolchains to separate Gradle Java Runtime + and the Java used for compilation (and other Java execution). + <code><a href="@TOP@/org/netbeans/modules/gradle/java/api/GradleJavaSourceSet.html#getCompilerJavaHome-org.netbeans.modules.gradle.java.api.GradleJavaSourceSet.SourceType-">GradleJavaSourceSet.getCompilerJavaHome</a></code> has been added to + return the Java Home of the JDK in use for compilation. + </p> + <p> + In addition <code><a href="@TOP@/org/netbeans/modules/gradle/java/spi/support/JavaToolchainSupport.html">JavaToolchainSsupport</a></code> + is provided in order to be easily work with the JDK home directories. + </p> + </description> + <class package="org.netbeans.modules.gradle.java.api" name="GradleJavaSourceSet"/> + <class package="org.netbeans.modules.gradle.java.spi.support" name="JavaToolchainSupport"/> + </change> <change id="sourceset-lang-output"> <api name="gradle.java.api"/> <summary>Support for per-language output directories</summary> diff --git a/java/gradle.java/manifest.mf b/java/gradle.java/manifest.mf index e7b6d301ae..b8aecd0fda 100644 --- a/java/gradle.java/manifest.mf +++ b/java/gradle.java/manifest.mf @@ -3,4 +3,5 @@ AutoUpdate-Show-In-Client: false OpenIDE-Module: org.netbeans.modules.gradle.java OpenIDE-Module-Layer: org/netbeans/modules/gradle/java/layer.xml OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/gradle/java/Bundle.properties +OpenIDE-Module-Java-Dependencies: Java > 17 OpenIDE-Module-Implementation-Version: 1 diff --git a/java/gradle.java/nbproject/project.properties b/java/gradle.java/nbproject/project.properties index 73520f0ec5..6d470bd837 100644 --- a/java/gradle.java/nbproject/project.properties +++ b/java/gradle.java/nbproject/project.properties @@ -16,7 +16,8 @@ # under the License. is.autoload=true -javac.source=1.8 +javac.source=17 +javac.target=17 javac.compilerargs=-Xlint -Xlint:-serial nbm.module.author=Laszlo Kishalmi javadoc.arch=${basedir}/arch.xml diff --git a/java/gradle.java/nbproject/project.xml b/java/gradle.java/nbproject/project.xml index 80c664174f..2bc5d4e31c 100644 --- a/java/gradle.java/nbproject/project.xml +++ b/java/gradle.java/nbproject/project.xml @@ -389,6 +389,7 @@ <package>org.netbeans.modules.gradle.java.api</package> <package>org.netbeans.modules.gradle.java.api.output</package> <package>org.netbeans.modules.gradle.java.spi.debug</package> + <package>org.netbeans.modules.gradle.java.spi.support</package> </public-packages> </data> </configuration> diff --git a/java/gradle.java/src/org/netbeans/modules/gradle/java/api/GradleJavaProjectBuilder.java b/java/gradle.java/src/org/netbeans/modules/gradle/java/api/GradleJavaProjectBuilder.java index 652b2eca17..e8e2c456fd 100644 --- a/java/gradle.java/src/org/netbeans/modules/gradle/java/api/GradleJavaProjectBuilder.java +++ b/java/gradle.java/src/org/netbeans/modules/gradle/java/api/GradleJavaProjectBuilder.java @@ -30,6 +30,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.TreeMap; import org.openide.filesystems.FileUtil; import org.openide.util.lookup.ServiceProvider; import static org.netbeans.modules.gradle.java.api.GradleJavaSourceSet.SourceType; @@ -47,7 +48,7 @@ final class GradleJavaProjectBuilder implements ProjectInfoExtractor.Result { final GradleJavaProject prj = new GradleJavaProject(); GradleJavaProjectBuilder(Map<String, Object> info) { - this.info = info; + this.info = new TreeMap<>(info); } GradleJavaProjectBuilder build() { @@ -85,6 +86,7 @@ final class GradleJavaProjectBuilder implements ProjectInfoExtractor.Result { Map<SourceType, String> sourceComp = new EnumMap<>(SourceType.class); Map<SourceType, String> targetComp = new EnumMap<>(SourceType.class); + Map<SourceType, File> javaHomes = new EnumMap<>(SourceType.class); Map<SourceType, List<String>> compilerArgs = new EnumMap<>(SourceType.class); for (SourceType lang : Arrays.asList(JAVA, GROOVY, SCALA, KOTLIN)) { String sc = (String) info.get("sourceset_" + name + "_" + lang.name() + "_source_compatibility"); @@ -95,6 +97,10 @@ final class GradleJavaProjectBuilder implements ProjectInfoExtractor.Result { if (tc != null) { targetComp.put(lang, tc); } + File javaHome = (File) info.get("sourceset_" + name + "_" + lang.name() + "_compiler_java_home"); + if (javaHome != null) { + javaHomes.put(lang, javaHome); + } List<String> compArgs = (List<String>) info.get("sourceset_" + name + "_" + lang.name() + "_compiler_args"); if (compArgs != null) { compilerArgs.put(lang, Collections.unmodifiableList(compArgs)); @@ -107,6 +113,7 @@ final class GradleJavaProjectBuilder implements ProjectInfoExtractor.Result { } sourceSet.sourcesCompatibility = Collections.unmodifiableMap(sourceComp); sourceSet.targetCompatibility = Collections.unmodifiableMap(targetComp); + sourceSet.compilerJavaHomes = Collections.unmodifiableMap(javaHomes); sourceSet.compilerArgs = Collections.unmodifiableMap(compilerArgs); for (File out : sourceSet.getOutputClassDirs()) { diff --git a/java/gradle.java/src/org/netbeans/modules/gradle/java/api/GradleJavaSourceSet.java b/java/gradle.java/src/org/netbeans/modules/gradle/java/api/GradleJavaSourceSet.java index 9ff163e9e1..c7eb458569 100644 --- a/java/gradle.java/src/org/netbeans/modules/gradle/java/api/GradleJavaSourceSet.java +++ b/java/gradle.java/src/org/netbeans/modules/gradle/java/api/GradleJavaSourceSet.java @@ -89,6 +89,7 @@ public final class GradleJavaSourceSet implements Serializable { Map<SourceType, String> sourcesCompatibility = Collections.emptyMap(); Map<SourceType, String> targetCompatibility = Collections.emptyMap(); + Map<SourceType, File> compilerJavaHomes = Collections.emptyMap(); Map<SourceType, List<String>> compilerArgs = Collections.emptyMap(); boolean testSourceSet; Set<File> outputClassDirs; @@ -600,6 +601,22 @@ public final class GradleJavaSourceSet implements Serializable { return null; } + /** + * Returns the JDK Home directory of the JVM what would be used during the + * compilation. Currently the {@linkplain SourceType#JAVA JAVA}, {@linkplain SourceType#GROOVY GROOVY}, and {@linkplain SourceType#SCALA SCALA} + * are expected to return a non {@code null} value. The home directory + * is determined by using the sourceSet default compile task. In Gradle + * it is possible to define additional compile tasks with different Java Toolchain. + * NetBeans would ignore those. + * + * @param type The source type of the compiler. + * @return The home directory of the JDK used for the default compile task. + * @since 1.26 + */ + public File getCompilerJavaHome(SourceType type) { + return compilerJavaHomes.get(type); + } + /** * Returns the compiler arguments for this source set defined for the given * language. diff --git a/java/gradle.java/src/org/netbeans/modules/gradle/java/classpath/AbstractGradleClassPathImpl.java b/java/gradle.java/src/org/netbeans/modules/gradle/java/classpath/AbstractGradleClassPathImpl.java index 303f5c6a43..512fbca6cb 100644 --- a/java/gradle.java/src/org/netbeans/modules/gradle/java/classpath/AbstractGradleClassPathImpl.java +++ b/java/gradle.java/src/org/netbeans/modules/gradle/java/classpath/AbstractGradleClassPathImpl.java @@ -25,12 +25,12 @@ import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.io.File; import java.net.URL; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; import org.netbeans.api.annotations.common.NonNull; import org.netbeans.api.java.classpath.ClassPath; import org.netbeans.api.project.Project; @@ -105,10 +105,7 @@ abstract class AbstractGradleClassPathImpl implements FlaggedClassPathImplementa @Override public final synchronized List<? extends PathResourceImplementation> getResources() { if (resources == null) { - resources = new ArrayList<>(); - for (URL url : createPath()) { - resources.add(ClassPathSupport.createResource(url)); - } + resources = createPath().stream().map(ClassPathSupport::createResource).toList(); } return resources; } diff --git a/java/gradle.java/src/org/netbeans/modules/gradle/java/classpath/BootClassPathImpl.java b/java/gradle.java/src/org/netbeans/modules/gradle/java/classpath/BootClassPathImpl.java index c1480d211a..9949664b03 100644 --- a/java/gradle.java/src/org/netbeans/modules/gradle/java/classpath/BootClassPathImpl.java +++ b/java/gradle.java/src/org/netbeans/modules/gradle/java/classpath/BootClassPathImpl.java @@ -19,57 +19,44 @@ package org.netbeans.modules.gradle.java.classpath; -import org.netbeans.modules.gradle.api.NbGradleProject; -import org.netbeans.modules.gradle.api.execute.RunUtils; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; +import org.netbeans.modules.gradle.java.spi.support.JavaToolchainSupport; +import java.io.File; import java.net.URL; import java.util.LinkedList; import java.util.List; -import java.util.prefs.PreferenceChangeEvent; -import java.util.prefs.PreferenceChangeListener; import org.netbeans.api.java.classpath.ClassPath; import org.netbeans.api.java.platform.JavaPlatform; -import org.netbeans.api.java.platform.JavaPlatformManager; import org.netbeans.api.project.Project; +import org.netbeans.modules.gradle.java.api.GradleJavaSourceSet; +import static org.netbeans.modules.gradle.java.api.GradleJavaSourceSet.SourceType.JAVA; import org.netbeans.modules.gradle.java.execute.JavaRunUtils; -import org.openide.util.WeakListeners; /** * * @author Laszlo Kishalmi */ -public final class BootClassPathImpl extends AbstractGradleClassPathImpl implements PropertyChangeListener { +public final class BootClassPathImpl extends AbstractSourceSetClassPathImpl { private static final String PROTOCOL_NBJRT = "nbjrt"; //NOI18N - JavaPlatformManager platformManager; final boolean modulesOnly; - public BootClassPathImpl(Project proj) { - this(proj, false); + public BootClassPathImpl(Project proj, String group) { + this(proj, group, false); } @SuppressWarnings("LeakingThisInConstructor") - public BootClassPathImpl(Project proj, boolean modulesOnly) { - super(proj); + public BootClassPathImpl(Project proj, String group, boolean modulesOnly) { + super(proj, group); this.modulesOnly = modulesOnly; - platformManager = JavaPlatformManager.getDefault(); - platformManager.addPropertyChangeListener(WeakListeners.propertyChange(this, platformManager)); - NbGradleProject.getPreferences(project, false).addPreferenceChangeListener((PreferenceChangeEvent evt) -> { - if (RunUtils.PROP_JDK_PLATFORM.equals(evt.getKey())) { - clearResourceCache(); - } - }); - } - - @Override - public void propertyChange(PropertyChangeEvent evt) { - clearResourceCache(); } @Override protected List<URL> createPath() { - JavaPlatform platform = JavaRunUtils.getActivePlatform(project).second(); + JavaToolchainSupport toolchain = JavaToolchainSupport.getDefault(); + GradleJavaSourceSet ss = getSourceSet(); + File jh = ss != null ? ss.getCompilerJavaHome(JAVA) : null; + + JavaPlatform platform = jh != null ? toolchain.platformByHome(jh) : JavaRunUtils.getActivePlatform(project).second(); List<URL> ret = new LinkedList<>(); if (platform != null) { for (ClassPath.Entry entry : platform.getBootstrapLibraries().entries()) { @@ -81,6 +68,4 @@ public final class BootClassPathImpl extends AbstractGradleClassPathImpl impleme } return ret; } - - } diff --git a/java/gradle.java/src/org/netbeans/modules/gradle/java/classpath/ClassPathProviderImpl.java b/java/gradle.java/src/org/netbeans/modules/gradle/java/classpath/ClassPathProviderImpl.java index d09039ff2e..8bd0f3c9eb 100644 --- a/java/gradle.java/src/org/netbeans/modules/gradle/java/classpath/ClassPathProviderImpl.java +++ b/java/gradle.java/src/org/netbeans/modules/gradle/java/classpath/ClassPathProviderImpl.java @@ -311,7 +311,7 @@ public final class ClassPathProviderImpl extends ProjectOpenedHook implements Cl private synchronized ClassPath getBootClassPath() { if (boot == null) { - boot = ClassPathFactory.createClassPath(new BootClassPathImpl(project, false)); + boot = ClassPathFactory.createClassPath(new BootClassPathImpl(project, group, false)); } return boot; } @@ -339,7 +339,7 @@ public final class ClassPathProviderImpl extends ProjectOpenedHook implements Cl private synchronized ClassPath getPlatformModulesPath() { if (platformModules == null) { - platformModules = ClassPathFactory.createClassPath(new BootClassPathImpl(project, true)); + platformModules = ClassPathFactory.createClassPath(new BootClassPathImpl(project, group, true)); } return platformModules; } diff --git a/java/gradle.java/src/org/netbeans/modules/gradle/java/classpath/GlobalClassPathProviderImpl.java b/java/gradle.java/src/org/netbeans/modules/gradle/java/classpath/GlobalClassPathProviderImpl.java index 99305397d0..63a4862f52 100644 --- a/java/gradle.java/src/org/netbeans/modules/gradle/java/classpath/GlobalClassPathProviderImpl.java +++ b/java/gradle.java/src/org/netbeans/modules/gradle/java/classpath/GlobalClassPathProviderImpl.java @@ -66,20 +66,13 @@ public class GlobalClassPathProviderImpl extends ProjectOpenedHook implements Pr if (index < 0) return null; ClassPath cp = cache[index]; if (cp == null) { - switch (type) { - case ClassPath.BOOT: - cp = createClassPath(new BootClassPathImpl(project)); - break; - case ClassPath.SOURCE: - cp = createClassPath(new GradleGlobalClassPathImpl.ProjectSourceClassPathImpl(project, excludeTests)); - break; - case ClassPath.COMPILE: - cp = createClassPath(new GradleGlobalClassPathImpl.ProjectCompileClassPathImpl(project, excludeTests)); - break; - case ClassPath.EXECUTE: - cp = createClassPath(new GradleGlobalClassPathImpl.ProjectRuntimeClassPathImpl(project, excludeTests)); - break; - } + cp = switch (type) { + case ClassPath.BOOT -> createClassPath(new BootClassPathImpl(project, null)); + case ClassPath.SOURCE -> createClassPath(new GradleGlobalClassPathImpl.ProjectSourceClassPathImpl(project, excludeTests)); + case ClassPath.COMPILE -> createClassPath(new GradleGlobalClassPathImpl.ProjectCompileClassPathImpl(project, excludeTests)); + case ClassPath.EXECUTE -> createClassPath(new GradleGlobalClassPathImpl.ProjectRuntimeClassPathImpl(project, excludeTests)); + default -> null; + }; cache[index] = cp; } return cp; @@ -87,22 +80,13 @@ public class GlobalClassPathProviderImpl extends ProjectOpenedHook implements Pr private static int type2Index(String type, boolean excludeTests) { int index; - switch (type) { - case ClassPath.BOOT: - index = BOOT; - break; - case ClassPath.SOURCE: - index = SOURCE; - break; - case ClassPath.COMPILE: - index = COMPILE; - break; - case ClassPath.EXECUTE: - index = RUNTIME; - break; - default: - index = -1; - } + index = switch (type) { + case ClassPath.BOOT -> BOOT; + case ClassPath.SOURCE -> SOURCE; + case ClassPath.COMPILE -> COMPILE; + case ClassPath.EXECUTE -> RUNTIME; + default -> -1; + }; return (index >= 0) && excludeTests ? index + 1 : index; } diff --git a/java/gradle.java/src/org/netbeans/modules/gradle/java/customizer/Bundle.properties b/java/gradle.java/src/org/netbeans/modules/gradle/java/customizer/Bundle.properties index 6797c79d18..9b12690db4 100644 --- a/java/gradle.java/src/org/netbeans/modules/gradle/java/customizer/Bundle.properties +++ b/java/gradle.java/src/org/netbeans/modules/gradle/java/customizer/Bundle.properties @@ -18,3 +18,4 @@ SourceSetPanel.jLabel1.text=Output Classes: SourceSetPanel.jLabel2.text=Output Resources: SourceSetPanel.jLabel3.text=Source/Binary Format: +SourceSetPanel.lbPlatform.text=Java Platform: diff --git a/java/gradle.java/src/org/netbeans/modules/gradle/java/customizer/SourceSetPanel.form b/java/gradle.java/src/org/netbeans/modules/gradle/java/customizer/SourceSetPanel.form index 0afcb8097d..bec08b32fa 100644 --- a/java/gradle.java/src/org/netbeans/modules/gradle/java/customizer/SourceSetPanel.form +++ b/java/gradle.java/src/org/netbeans/modules/gradle/java/customizer/SourceSetPanel.form @@ -37,15 +37,10 @@ <Layout> <DimensionLayout dim="0"> <Group type="103" groupAlignment="0" attributes="0"> - <Group type="102" alignment="0" attributes="0"> + <Group type="102" attributes="0"> <EmptySpace max="-2" attributes="0"/> <Group type="103" groupAlignment="0" attributes="0"> - <Component id="tpDetails" max="32767" attributes="0"/> - <Group type="102" attributes="0"> - <Component id="jLabel3" min="-2" pref="169" max="-2" attributes="0"/> - <EmptySpace max="-2" attributes="0"/> - <Component id="tfSourceLevel" pref="402" max="32767" attributes="0"/> - </Group> + <Component id="tpDetails" pref="580" max="32767" attributes="0"/> <Group type="102" alignment="0" attributes="0"> <Group type="103" groupAlignment="1" max="-2" attributes="0"> <Component id="jLabel1" max="32767" attributes="0"/> @@ -57,6 +52,20 @@ <Component id="tfOutputClasses" max="32767" attributes="0"/> </Group> </Group> + <Group type="102" alignment="0" attributes="0"> + <Group type="103" groupAlignment="0" max="-2" attributes="0"> + <Component id="jLabel3" pref="157" max="32767" attributes="0"/> + <Component id="lbPlatform" max="32767" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <Component id="tfSourceLevel" min="-2" pref="39" max="-2" attributes="0"/> + <EmptySpace min="0" pref="0" max="32767" attributes="0"/> + </Group> + <Component id="jtPlatform" max="32767" attributes="0"/> + </Group> + </Group> </Group> <EmptySpace max="-2" attributes="0"/> </Group> @@ -65,13 +74,18 @@ <DimensionLayout dim="1"> <Group type="103" groupAlignment="0" attributes="0"> <Group type="102" alignment="1" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="lbPlatform" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="jtPlatform" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> <EmptySpace max="-2" attributes="0"/> <Group type="103" groupAlignment="3" attributes="0"> <Component id="jLabel3" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="tfSourceLevel" alignment="3" min="-2" max="-2" attributes="0"/> </Group> <EmptySpace max="-2" attributes="0"/> - <Component id="tpDetails" pref="232" max="32767" attributes="0"/> + <Component id="tpDetails" pref="202" max="32767" attributes="0"/> <EmptySpace max="-2" attributes="0"/> <Group type="103" groupAlignment="0" attributes="0"> <Component id="jLabel1" min="-2" max="-2" attributes="0"/> @@ -257,5 +271,20 @@ <Property name="editable" type="boolean" value="false"/> </Properties> </Component> + <Component class="javax.swing.JLabel" name="lbPlatform"> + <Properties> + <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor"> + <ComponentRef name="jtPlatform"/> + </Property> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/netbeans/modules/gradle/java/customizer/Bundle.properties" key="SourceSetPanel.lbPlatform.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + </Component> + <Component class="javax.swing.JTextField" name="jtPlatform"> + <Properties> + <Property name="editable" type="boolean" value="false"/> + </Properties> + </Component> </SubComponents> </Form> diff --git a/java/gradle.java/src/org/netbeans/modules/gradle/java/customizer/SourceSetPanel.java b/java/gradle.java/src/org/netbeans/modules/gradle/java/customizer/SourceSetPanel.java index adbef5a63f..bc7d2fc54f 100644 --- a/java/gradle.java/src/org/netbeans/modules/gradle/java/customizer/SourceSetPanel.java +++ b/java/gradle.java/src/org/netbeans/modules/gradle/java/customizer/SourceSetPanel.java @@ -36,6 +36,9 @@ import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; +import org.netbeans.api.java.platform.JavaPlatform; +import org.netbeans.modules.gradle.java.spi.support.JavaToolchainSupport; +import org.openide.filesystems.FileObject; import org.openide.util.ImageUtilities; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; @@ -83,6 +86,19 @@ public class SourceSetPanel extends javax.swing.JPanel { this.sourceSet = sourceSet; relativeRoot = relativeTo.toPath(); initComponents(); + + File javaHome = sourceSet.getCompilerJavaHome(GradleJavaSourceSet.SourceType.JAVA); + JavaPlatform platform =JavaPlatform.getDefault(); + if (javaHome != null) { + platform = JavaToolchainSupport.getDefault().platformByHome(javaHome); + } + jtPlatform.setText(platform.getDisplayName()); + + if (platform.isValid()) { + FileObject home = platform.getInstallFolders().iterator().next(); + jtPlatform.setToolTipText(home.getPath()); + } + if (sourceSet.getSourcesCompatibility().equals(sourceSet.getTargetCompatibility())) { tfSourceLevel.setText(sourceSet.getSourcesCompatibility()); } else { @@ -178,6 +194,8 @@ public class SourceSetPanel extends javax.swing.JPanel { tfSourceLevel = new javax.swing.JTextField(); tfOutputResources = new javax.swing.JTextField(); tfOutputClasses = new javax.swing.JTextField(); + lbPlatform = new javax.swing.JLabel(); + jtPlatform = new javax.swing.JTextField(); org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(SourceSetPanel.class, "SourceSetPanel.jLabel1.text")); // NOI18N @@ -218,6 +236,11 @@ public class SourceSetPanel extends javax.swing.JPanel { tfOutputClasses.setEditable(false); + lbPlatform.setLabelFor(jtPlatform); + org.openide.awt.Mnemonics.setLocalizedText(lbPlatform, org.openide.util.NbBundle.getMessage(SourceSetPanel.class, "SourceSetPanel.lbPlatform.text")); // NOI18N + + jtPlatform.setEditable(false); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( @@ -225,11 +248,7 @@ public class SourceSetPanel extends javax.swing.JPanel { .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(tpDetails, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(layout.createSequentialGroup() - .addComponent(jLabel3, javax.swing.GroupLayout.PREFERRED_SIZE, 169, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(tfSourceLevel, javax.swing.GroupLayout.DEFAULT_SIZE, 402, Short.MAX_VALUE)) + .addComponent(tpDetails, javax.swing.GroupLayout.DEFAULT_SIZE, 580, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) @@ -237,18 +256,32 @@ public class SourceSetPanel extends javax.swing.JPanel { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(tfOutputResources) - .addComponent(tfOutputClasses)))) + .addComponent(tfOutputClasses))) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(jLabel3, javax.swing.GroupLayout.DEFAULT_SIZE, 157, Short.MAX_VALUE) + .addComponent(lbPlatform, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(tfSourceLevel, javax.swing.GroupLayout.PREFERRED_SIZE, 39, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, Short.MAX_VALUE)) + .addComponent(jtPlatform)))) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lbPlatform) + .addComponent(jtPlatform, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel3) .addComponent(tfSourceLevel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(tpDetails, javax.swing.GroupLayout.DEFAULT_SIZE, 232, Short.MAX_VALUE) + .addComponent(tpDetails, javax.swing.GroupLayout.DEFAULT_SIZE, 202, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jLabel1) @@ -318,6 +351,8 @@ public class SourceSetPanel extends javax.swing.JPanel { private javax.swing.JScrollPane jScrollPane3; private javax.swing.JScrollPane jScrollPane4; private javax.swing.JScrollPane jScrollPane6; + private javax.swing.JTextField jtPlatform; + private javax.swing.JLabel lbPlatform; private javax.swing.JList<File> lsAnnotationProcessors; private javax.swing.JList<File> lsCompile; private javax.swing.JList<File> lsRuntime; diff --git a/java/gradle.java/src/org/netbeans/modules/gradle/java/nodes/BootCPNodeFactory.java b/java/gradle.java/src/org/netbeans/modules/gradle/java/nodes/BootCPNodeFactory.java index ecb76dcbee..a4155d2fab 100644 --- a/java/gradle.java/src/org/netbeans/modules/gradle/java/nodes/BootCPNodeFactory.java +++ b/java/gradle.java/src/org/netbeans/modules/gradle/java/nodes/BootCPNodeFactory.java @@ -19,39 +19,33 @@ package org.netbeans.modules.gradle.java.nodes; import org.netbeans.modules.gradle.api.NbGradleProject; -import org.netbeans.modules.gradle.api.execute.RunUtils; -import org.netbeans.modules.gradle.java.api.ProjectSourcesClassPathProvider; import static org.netbeans.modules.gradle.java.nodes.Bundle.BootCPNode_displayName; import org.netbeans.modules.gradle.spi.nodes.AbstractGradleNodeList; import org.netbeans.modules.gradle.spi.nodes.NodeUtils; import java.awt.Image; import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.io.CharConversionException; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; -import java.util.concurrent.atomic.AtomicReference; -import java.util.prefs.PreferenceChangeEvent; -import java.util.prefs.PreferenceChangeListener; -import java.util.prefs.Preferences; +import java.util.Set; +import java.util.TreeSet; +import java.util.stream.Collectors; import javax.swing.Action; import javax.swing.Icon; -import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; -import org.netbeans.api.annotations.common.CheckForNull; -import org.netbeans.api.annotations.common.NonNull; import org.netbeans.api.annotations.common.StaticResource; -import org.netbeans.api.java.classpath.ClassPath; import org.netbeans.api.java.platform.JavaPlatform; -import org.netbeans.api.java.platform.JavaPlatformManager; import org.netbeans.api.java.project.JavaProjectConstants; import org.netbeans.api.project.Project; import org.netbeans.api.project.ProjectUtils; import org.netbeans.api.project.SourceGroup; import org.netbeans.api.project.Sources; +import org.netbeans.modules.gradle.java.api.GradleJavaProject; +import org.netbeans.modules.gradle.java.api.GradleJavaSourceSet; +import org.netbeans.modules.gradle.java.api.GradleJavaSourceSet.SourceType; import org.netbeans.modules.gradle.java.execute.JavaRunUtils; +import org.netbeans.modules.gradle.java.spi.support.JavaToolchainSupport; import org.netbeans.spi.project.ui.PathFinder; import org.netbeans.spi.java.project.support.ui.PackageView; import org.netbeans.spi.project.ui.support.NodeFactory; @@ -63,17 +57,12 @@ import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; import org.openide.nodes.FilterNode; import org.openide.nodes.Node; -import org.openide.util.ChangeSupport; import org.openide.util.ImageUtilities; import org.openide.util.Lookup; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; -import org.openide.util.Pair; -import org.openide.util.RequestProcessor; -import org.openide.util.WeakListeners; import org.openide.util.lookup.Lookups; import org.openide.util.lookup.ProxyLookup; -import org.openide.xml.XMLUtil; @NodeFactory.Registration(projectType = NbGradleProject.GRADLE_PROJECT_TYPE, position = 520) public class BootCPNodeFactory implements NodeFactory { @@ -101,7 +90,7 @@ public class BootCPNodeFactory implements NodeFactory { @Override public Node node(Void key) { - return new BootCPNode(new PlatformProvider(p, null)); + return new BootCPNode(p); } @Override @@ -123,8 +112,8 @@ public class BootCPNodeFactory implements NodeFactory { @Messages("BootCPNode_displayName=Java Dependencies") @SuppressWarnings("OverridableMethodCallInConstructor") - BootCPNode(PlatformProvider pp) { - super(Children.create(new BootCPChildren(pp), false), Lookups.singleton(PathFinders.createPathFinder())); + BootCPNode(Project p) { + super(Children.create(new BootCPChildren(p), false), Lookups.singleton(PathFinders.createPathFinder())); setName("BootCPNode"); setDisplayName(BootCPNode_displayName()); } @@ -142,130 +131,83 @@ public class BootCPNodeFactory implements NodeFactory { } // XXX PlatformNode and ActionFilterNode does some of what we want, but cannot be reused - private static class BootCPChildren extends ChildFactory.Detachable<FileObject> implements ChangeListener, PropertyChangeListener { + private record PlatformSourceSet(JavaPlatform platform, Set<GradleJavaSourceSet> sourceSets) {} + private static class BootCPChildren extends ChildFactory.Detachable<PlatformSourceSet> { - private final PlatformProvider pp; - private ClassPath[] endorsed; - private static final FileObject BOOT = FileUtil.createMemoryFileSystem().getRoot(); + private final Project project; - BootCPChildren(PlatformProvider pp) { - this.pp = pp; + BootCPChildren(Project project) { + this.project = project; } @Override protected void addNotify() { - pp.addChangeListener(this); - ProjectSourcesClassPathProvider pvd = pp.project.getLookup().lookup(ProjectSourcesClassPathProvider.class); - endorsed = pvd != null ? pvd.getProjectClassPath(ENDORSED) : new ClassPath[0]; - for (ClassPath cp : endorsed) { - cp.addPropertyChangeListener(this); - } + NbGradleProject.addPropertyChangeListener(project, this::projectChange); } @Override protected void removeNotify() { - pp.removeChangeListener(this); - for (ClassPath cp : endorsed) { - cp.removePropertyChangeListener(this); - } - endorsed = null; + NbGradleProject.removePropertyChangeListener(project, this::projectChange); } @Override - protected boolean createKeys(List<FileObject> roots) { - roots.add(BOOT); - for (ClassPath cp : endorsed) { - roots.addAll(Arrays.asList(cp.getRoots())); + protected boolean createKeys(List<PlatformSourceSet> keys) { + var toolchains = JavaToolchainSupport.getDefault(); + var pss = new HashMap<JavaPlatform, Set<GradleJavaSourceSet>>(); + var ss = GradleJavaProject.get(project).getSourceSets().values(); + for (GradleJavaSourceSet s : ss) { + var home = s.getCompilerJavaHome(SourceType.JAVA); + var platform = home != null ? toolchains.platformByHome(home) : JavaRunUtils.getActivePlatform(project).second(); + var groups = pss.computeIfAbsent(platform, (k) -> new TreeSet<GradleJavaSourceSet>((s1, s2) -> s1.getName().compareTo(s2.getName()))); + groups.add(s); } + pss.forEach((platform, groups) -> keys.add(new PlatformSourceSet(platform, groups))); return true; } @Override - protected Node createNodeForKey(FileObject root) { - return root == BOOT ? new JRENode(pp) : jarNode(new LibrariesSourceGroup(root, root.getNameExt())); + protected Node createNodeForKey(PlatformSourceSet platform) { + return new JRENode(platform); } - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (evt.getPropertyName().equals(ClassPath.PROP_ROOTS)) { + private void projectChange(PropertyChangeEvent evt) { + if (NbGradleProject.PROP_PROJECT_INFO.equals(evt.getPropertyName())) { refresh(false); } } - @Override - public void stateChanged(ChangeEvent e) { - refresh(false); - } - } @NbBundle.Messages({ "# {0} - Platform Display name", "FMT_BrokenPlatform=Broken platform ''{0}''", - "TXT_BrokenPlatform=Broken platform", - "TXT_UnknownPlatform=Loading..." }) - private static class JRENode extends AbstractNode implements ChangeListener { + private static class JRENode extends AbstractNode { - private final PlatformProvider pp; + private final PlatformSourceSet pss; @SuppressWarnings("OverridableMethodCallInConstructor") - private JRENode(PlatformProvider pp) { + private JRENode(PlatformSourceSet pss) { super(new CPChildren(), Lookups.singleton(PathFinders.createPathFinder())); - this.pp = pp; - pp.addChangeListener(this); + this.pss = pss; setIconBaseWithExtension(PLATFORM_ICON); } @Override public String getName() { - return this.getDisplayName(); + return pss.platform().getDisplayName(); } @Override public String getDisplayName() { - final Pair<String, JavaPlatform> platHolder = pp.getPlatform(); - if (platHolder == null) { - return Bundle.TXT_UnknownPlatform(); - } - String name; - final JavaPlatform jp = platHolder.second(); - if (jp != null) { - if (jp.isValid()) { - name = jp.getDisplayName(); - } else { - name = Bundle.FMT_BrokenPlatform(jp.getDisplayName()); - } - } else { - String platformId = platHolder.first(); - if (platformId == null) { - name = Bundle.TXT_BrokenPlatform(); - } else { - name = Bundle.FMT_BrokenPlatform(platformId); - } - } - return name; + String name = pss.platform.isValid() ? pss.platform.getDisplayName(): Bundle.FMT_BrokenPlatform(pss.platform.getDisplayName()); + String groups = pss.sourceSets.stream().map(GradleJavaSourceSet::getName).collect(Collectors.joining(", ", "[", "]")); + return name + " " + groups; } @Override public String getHtmlDisplayName() { - final Pair<String, JavaPlatform> platHolder = pp.getPlatform(); - if (platHolder == null) { - return null; - } - final JavaPlatform jp = platHolder.second(); - if (jp == null || !jp.isValid()) { - String displayName = this.getDisplayName(); - try { - displayName = XMLUtil.toElementContent(displayName); - } catch (CharConversionException ex) { - // OK, no annotation in this case - return null; - } - return "<font color=\"#A40000\">" + displayName + "</font>"; //NOI18N - } else { - return null; - } + return null; } @Override @@ -274,24 +216,21 @@ public class BootCPNodeFactory implements NodeFactory { } @Override + @Messages({ + "# {0} - The path of the Java Platform home", + "# {1} - The list of the sourcesets wher the platform is used", + "TOOLTIP_Platform=<html>Home: {0}<br/>Used in: {1}" + }) public String getShortDescription() { - final Pair<String,JavaPlatform> platHolder = pp.getPlatform(); - if (platHolder != null && platHolder.second() != null && !platHolder.second().getInstallFolders().isEmpty()) { - final FileObject installFolder = platHolder.second().getInstallFolders().iterator().next(); - return FileUtil.getFileDisplayName(installFolder); + if (pss.platform.isValid()) { + FileObject installFolder = pss.platform.getInstallFolders().iterator().next(); + String groups = pss.sourceSets.stream().map(GradleJavaSourceSet::getName).collect(Collectors.joining(", ")); + + return Bundle.TOOLTIP_Platform(FileUtil.getFileDisplayName(installFolder), groups); } else { return super.getShortDescription(); } } - - @Override - public void stateChanged(ChangeEvent e) { - this.fireNameChange(null,null); - this.fireDisplayNameChange(null,null); - ((CPChildren) getChildren()).addNotify(); - } - - } private static class CPChildren extends Children.Keys<SourceGroup> { @@ -315,31 +254,19 @@ public class BootCPNodeFactory implements NodeFactory { } private List<SourceGroup> getKeys () { - final FileObject[] roots = ((JRENode)this.getNode()).pp.getBootstrapLibraries(); - if (roots.length == 0) { - return Collections.<SourceGroup>emptyList(); - } + final FileObject[] roots = ((JRENode)this.getNode()).pss.platform.getBootstrapLibraries().getRoots(); final List<SourceGroup> result = new ArrayList<>(roots.length); for (FileObject root : roots) { - FileObject file; - Icon icon; - Icon openedIcon; - switch (root.toURL().getProtocol()) { - case "jar": - file = FileUtil.getArchiveFile (root); - icon = openedIcon = ImageUtilities.loadImageIcon(ARCHIVE_ICON, false); - break; - case "nbjrt": - file = root; - icon = openedIcon = ImageUtilities.loadImageIcon(MODULE_ICON, false); - break; - default: - file = root; - icon = openedIcon = null; - } - if (file.isValid()) { - result.add (new LibrariesSourceGroup(root,file.getNameExt(),icon, openedIcon)); - } + var protocol = root.toURL().getProtocol(); + FileObject file = "jar".equals(protocol) ? FileUtil.getArchiveRoot(root) : root; + if (file.isValid()) { + Icon icon = switch (protocol) { + case "jar" -> ImageUtilities.loadImageIcon(ARCHIVE_ICON, false); + case "nbjrt" -> ImageUtilities.loadImageIcon(MODULE_ICON, false); + default -> null; + }; + result.add (new LibrariesSourceGroup(root,file.getNameExt(), icon, icon)); + } } return result; } @@ -363,87 +290,4 @@ public class BootCPNodeFactory implements NodeFactory { }; } - - private static final class PlatformProvider implements PropertyChangeListener, PreferenceChangeListener { - - private static final Pair<String,JavaPlatform> BUSY = Pair.<String,JavaPlatform>of(null,null); - private static final RequestProcessor RP = new RequestProcessor(PlatformProvider.class); - - private final Project project; - private final ClassPath boot; - private final AtomicReference<Pair<String,JavaPlatform>> platformCache = new AtomicReference<Pair<String,JavaPlatform>>(); - private final ChangeSupport changeSupport = new ChangeSupport(this); - - public PlatformProvider ( - @NonNull final Project project, - @NonNull final ClassPath boot) { - this.project = project; - this.boot = boot; - final JavaPlatformManager jps = JavaPlatformManager.getDefault(); - jps.addPropertyChangeListener(WeakListeners.propertyChange(this, jps)); - Preferences prefs = NbGradleProject.getPreferences(project, false); - prefs.addPreferenceChangeListener( - WeakListeners.create(PreferenceChangeListener.class, this, prefs)); - NbGradleProject.addPropertyChangeListener(project, WeakListeners.propertyChange(this, NbGradleProject.get(project))); - - if (this.boot != null) { - this.boot.addPropertyChangeListener(WeakListeners.propertyChange(this, this.boot)); - } - } - - @CheckForNull - public Pair<String,JavaPlatform> getPlatform () { - if (platformCache.compareAndSet(null, BUSY)) { - RP.execute(() -> { - platformCache.set(JavaRunUtils.getActivePlatform(project)); - changeSupport.fireChange (); - }); - } - Pair<String,JavaPlatform> res = platformCache.get(); - return res == BUSY ? null : res; - } - - @NonNull - public FileObject[] getBootstrapLibraries() { - final Pair<String, JavaPlatform> jp = getPlatform(); - if (jp == null || jp.second() == null) { - return new FileObject[0]; - } - ClassPath cp = boot; - if (cp == null) { - cp = jp.second().getBootstrapLibraries(); - } - return cp.getRoots(); - } - - public void addChangeListener (ChangeListener l) { - changeSupport.addChangeListener(l); - } - - public void removeChangeListener (ChangeListener l) { - changeSupport.removeChangeListener(l); - } - - @Override - public void propertyChange(PropertyChangeEvent evt) { - final String propName = evt.getPropertyName(); - if (NbGradleProject.PROP_PROJECT_INFO.equals(propName) || - ClassPath.PROP_ROOTS.equals(propName) || - JavaPlatformManager.PROP_INSTALLED_PLATFORMS.equals(propName)) { - platformCache.set(null); - getPlatform(); - } - } - - @Override - public void preferenceChange(PreferenceChangeEvent evt) { - String prefName = evt.getKey(); - if (RunUtils.PROP_JDK_PLATFORM.equals(prefName)) { - platformCache.set(null); - getPlatform(); - } - } - - } - } diff --git a/java/gradle.java/src/org/netbeans/modules/gradle/java/spi/support/JavaToolchainSupport.java b/java/gradle.java/src/org/netbeans/modules/gradle/java/spi/support/JavaToolchainSupport.java new file mode 100644 index 0000000000..eb57f6ef69 --- /dev/null +++ b/java/gradle.java/src/org/netbeans/modules/gradle/java/spi/support/JavaToolchainSupport.java @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.gradle.java.spi.support; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.netbeans.api.java.platform.JavaPlatform; +import org.netbeans.api.java.platform.JavaPlatformManager; +import org.netbeans.modules.gradle.spi.Utils; +import org.netbeans.modules.java.api.common.util.CommonProjectUtils; +import org.netbeans.spi.java.platform.JavaPlatformFactory; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.util.Lookup; +import org.openide.util.NbBundle; + +/** + * Support for creating retrieving JavaPlatforms from their install location + * (home directory). + * + * @since 1.26 + * @author Laszlo Kishalmi + */ +public final class JavaToolchainSupport { + + private final Map<File, JavaPlatform> platformCache; + + private static JavaToolchainSupport instance; + + private JavaToolchainSupport() { + platformCache = new HashMap<>(); + } + + public static JavaToolchainSupport getDefault() { + if (instance == null) { + instance = new JavaToolchainSupport(); + } + return instance; + } + + /** + * Tries to locate a registered {@linkplain JavaPlatform} from its install + * location. If it is not registered among the NetBeans usual Java Platforms + * then a new non-registered one will be created. + * + * @param home The home directory of a Java installation + * @return the {@linkplain JavaPlatform} representing the given directory. + */ + public JavaPlatform platformByHome(File home) { + return platformCache.computeIfAbsent(home, this::detectPlatform); + } + + private JavaPlatform detectPlatform(File home) { + FileObject h = FileUtil.toFileObject(home); + for (JavaPlatform platform : JavaPlatformManager.getDefault().getInstalledPlatforms()) { + if (platform.isValid()) { + FileObject ph = platform.getInstallFolders().iterator().next(); + if (ph.equals(h)) { + return platform; + } + } + } + for (JavaPlatformFactory.Provider pvd : Lookup.getDefault().lookupAll(JavaPlatformFactory.Provider.class)) { + JavaPlatformFactory factory = pvd.forType(CommonProjectUtils.J2SE_PLATFORM_TYPE); + if (factory != null) { + try { + JavaPlatform ret = factory.create(h, toolchainName(home), false); + return ret; + } catch (IOException ex) { + + } + } + } + return null; + } + + private static final Pattern GRADLE_JDK_DIST = Pattern.compile("(\\w+)-(\\d+)-(\\w+)-(\\w+)"); + @NbBundle.Messages({ + "# {0} - JDK Vendor", + "# {1} - Java Feature Version", + "# {2} - JDK Architecture", + "# {3} - JDK OS", + "GRADLE_INSTALLED_JDK_NAME=Java {1} {0} (from Java Toolchain)", + "# {0} - JDK Install folder name", + "# {1} - JDK Install folder path", + "OTHER_JDK_NAME=JDK {0} from {1}" + }) + private static String toolchainName(File home) { + File distDir = home.getParentFile(); + if (distDir != null) { + Matcher m = GRADLE_JDK_DIST.matcher(distDir.getName()); + if (m.matches()) { + String vendor = Utils.capitalize(m.group(1).replace('_', ' ')); + String version = m.group(2); + String arch = m.group(3); + String os = m.group(4); + return Bundle.GRADLE_INSTALLED_JDK_NAME(vendor, version, arch, os); + } + } + return Bundle.OTHER_JDK_NAME(home.getName(), home.getAbsolutePath()); + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@netbeans.apache.org For additional commands, e-mail: commits-h...@netbeans.apache.org For further information about the NetBeans mailing lists, visit: https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists