All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.modules.gradle.api.GradleBaseProject Maven / Gradle / Ivy

The newest version!
/*
 * 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.api;

import org.netbeans.modules.gradle.spi.GradleFiles;
import org.netbeans.modules.gradle.api.execute.RunUtils;
import java.io.File;
import java.io.Serializable;
import java.nio.file.Path;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.api.project.Project;
import org.netbeans.modules.gradle.GradleModuleFileCache21;
import org.netbeans.modules.gradle.cache.SubProjectDiskCache;
import org.netbeans.modules.gradle.cache.SubProjectDiskCache.SubProjectInfo;
import org.openide.util.TopologicalSortException;
import org.openide.util.Utilities;

/**
 * This object holds the basic information of the Gradle project.
 * 

* Note: Caching / storing this object inn a member field is discouraged. Use * {@link GradleBaseProject#get(Project)} instead. *

* @see org.gradle.api.Project * @since 1.0 * @author Laszlo Kishalmi */ public final class GradleBaseProject implements Serializable, ModuleSearchSupport { public static final String PRIVATE_TASK_GROUP = ""; //NOI18N String name; String group = ""; String description; String version; String path; String status; String parentName; String displayName; File buildDir; File projectDir; File rootDir; String license; Set plugins = Collections.emptySet(); Set gradleClassPath = Collections.emptySet(); Set buildClassPath = Collections.emptySet(); Map subProjects = Collections.emptyMap(); Map includedBuilds = Collections.emptyMap(); Map> tasksByGroup = new HashMap<>(); Map tasksByName = new HashMap<>(); Map netBeansProperties = Collections.emptyMap(); Map componentsByFile = new HashMap<>(); Map configurations = new HashMap<>(); Set outputPaths = Collections.emptySet(); Map projectIds = Collections.emptyMap(); GradleDependency projectDependencyNode; Set problems = Collections.emptySet(); Map> taskDependencies = new HashMap<>(); Map> taskTypes = new HashMap<>(); // @GuardedBy(this) /** * Lazy-computed list of tasks mapped to either tasksByName or created descriptions. */ private transient Map> taskDeepDependencies = new HashMap<>(); transient Boolean resolved = null; GradleBaseProject() { } /** * This Gradle project name. * * * * @return the name of the project */ public String getName() { return name; } public String getPath() { return path; } public String getStatus() { return status; } public String getParentName() { return parentName; } public String getGroup() { return group; } public String getDescription() { return description; } public String getDisplayName() { return displayName; } public boolean isVersionSpecified() { return version != null && !"".equals(version) && !"unspecified".equals(version); // NOI18N } public String getVersion() { return version; } public File getBuildDir() { return buildDir; } public Set getOutputPaths() { return outputPaths; } public File getProjectDir() { return projectDir; } /** * The set of Gradle plugin ids used applied in this project. * * @return the set of applied plugins */ public Set getPlugins() { return plugins; } /** * The project directory of the root project. * @return the root project directory. */ public File getRootDir() { return rootDir; } /** * The classpath used to * @return */ public Set getGradleClassPath() { return gradleClassPath; } public Set getBuildClassPath() { return buildClassPath; } public Map getIncludedBuilds() { return includedBuilds; } /** * Return the list of problems reported by Gradle on * project inspection. In an ideal case that should be an * empty set. * * @return Gradle reported problems during inspection. * * @since 2.27 */ public Set getProblems() { return problems; } /** * Returns true if the project directory is the same as the root project's * project directory, in short if this project is a root project. * * @return true for root Gradle projects */ public boolean isRoot() { return projectDir.equals(rootDir); } /** * Return the value of the property defined {@code netbeans.} as * in this Gradle project or inherited from the root project. * * @param key the property name after the {@code netbeans.} prefix. * @return the property value or {@code null} if it is not defined. */ public String getNetBeansProperty(String key) { return netBeansProperties.get(key); } /** * Returns the license identifier used in this Gradle project. It is * determined by the {@code netbeans.license} property of the project, * if that's not found {@code license} property is used. If even that * would be undefined the license {@code "default"} is used. * @return the project defined license or {@code default} if no license has * been specified. */ public String getLicense() { return license != null ? license : "default"; //NOI18N } /** * Returns the sub-project of this project, in a map as Gradle project path * and project directory pairs. In the current Gradle implementation only * root project can have sub-projects. * * @return the map of sub-projects. */ public Map getSubProjects() { return subProjects; } /** * Finds a GAV for the given project. Returns {@code null} if the project path * is not known (it is not referenced anywhere by this project), or has no known * GAV. The project's own GAV should be always present, if defined by the project * file(s). * * @param projectPath Gradle project path * @return GAV coordinates, or {@code null} * @since 2.27 */ public String findProjectGav(@NonNull String projectPath) { if ("".equals(projectPath) || getPath().equals(projectPath)) { String n = getName(); String g = getGroup(); String v = getVersion(); if (n == null || n.isEmpty() || g == null || g.isEmpty() || v == null || v.isEmpty() || "unspecified".equals(v)) { // NOI18N return null; } return String.format("%s:%s:%s", g, n, v); } return projectIds.get(projectPath); } public Set getTaskGroups() { return Collections.unmodifiableSet(tasksByGroup.keySet()); } public List getTasks(String group) { List ret = tasksByGroup.get(group); return ret != null ? Collections.unmodifiableList(ret) : Collections.emptyList(); } public List getTasks() { return Collections.unmodifiableList(new ArrayList<>(tasksByName.values())); } public Set getTaskNames() { return Collections.unmodifiableSet(tasksByName.keySet()); } public GradleTask getTaskByName(String name) { return tasksByName.get(name); } /** * For a given task, lists all predecessors of the task within the current project. * If tasks from other projects are referenced, they are returned as mock objects, * that have no group and no description and no dependencies. *

* The result is partially sorted so that dependencies always precede the dependent * task. * * @param gt gradle task to inspect * @param directs if true, only direct predecessors are returned * @return list of predecessor tasks. * @since 2.28 */ public List getTaskPredecessors(GradleTask gt, boolean directs) { // sanity check to rule out tasks from other projects or mocks. if (gt.getName() == null || getTaskByName(gt.getName()) != gt) { return Collections.emptyList(); } // do not cache direct dependencies, they're cheap. if (!directs) { synchronized (this) { List cached = taskDeepDependencies.get(gt.getName()); if (cached != null) { return cached; } } } Set paths = new HashSet<>(); Queue toProcess = new ArrayDeque<>(); toProcess.add(gt.getPath()); String taskPath; Map taskNamesAndPaths = new HashMap<>(); boolean first = true; Set ownTasks = new HashSet<>(); while ((taskPath = toProcess.poll()) != null) { if (taskPath.equals("") || !paths.add(taskPath)) { continue; } int lastColon = taskPath.lastIndexOf(':'); // path for the root project (lastColon == 0) is ":". Path for any subproject must not contain a possible colon delimiter between project path and the task. String p = taskPath.substring(0, Math.max(1, lastColon)); String n = taskPath.substring(lastColon + 1); taskNamesAndPaths.put(taskPath, n); if (path.equals(p)) { ownTasks.add(taskPath); if (!directs || first){ // if directs, allow just the 1st level to be added to toProcess. toProcess.addAll(taskDependencies.getOrDefault(n, Collections.emptyList())); } } first = false; } paths.remove(gt.getPath()); Map> edges = new HashMap<>(); for (String tn : ownTasks) { String sn = taskNamesAndPaths.get(tn); for (String pred : taskDependencies.getOrDefault(sn, Collections.emptyList())) { if (pred.isEmpty()) { continue; } edges.computeIfAbsent(pred, (k) -> new ArrayList<>()).add(tn); } } List orderedTasks; try { orderedTasks = Utilities.topologicalSort(paths, edges); } catch (TopologicalSortException ex) { orderedTasks = new ArrayList<>(taskNamesAndPaths.keySet()); } List result = new ArrayList<>(); for (String p : orderedTasks) { String n = taskNamesAndPaths.get(p); GradleTask toAdd = null; if (ownTasks.contains(p)) { toAdd = getTaskByName(n); } if (toAdd == null) { toAdd = new GradleTask(p, n); } result.add(toAdd); } if (!directs) { synchronized (this) { taskDeepDependencies.putIfAbsent(gt.getName(), result); } } return result; } /** * Determines if a task is a subtype of a certain Gradle type. * User-defined tasks may define different names, but the can be identified * by the gradle type they extend or implement. * Use fully qualified API class names for {@code gradleFQN} parameter. * @param gradleFQN the fully qualified type name * @return true, if the task type matches. * @since 2.28 */ public boolean isTaskInstanceOf(String name, String gradleFQN) { Set s = taskTypes.get(name); return s == null ? false : s.contains(gradleFQN); } public Map getConfigurations() { return Collections.unmodifiableMap(configurations); } public Set getProjectDependencies() { Set ret = new HashSet<>(); for (GradleConfiguration conf : configurations.values()) { ret.addAll(conf.getProjects()); } return Collections.unmodifiableSet(ret); } public boolean hasPlugins(String... plugins) { for (String plugin : plugins) { if (!this.plugins.contains(plugin)) return false; } return true; } @Override public Set findModules(String group, String artifact, String version) { Set ret = new HashSet<>(); for (GradleConfiguration conf : configurations.values()) { ret.addAll(conf.findModules(group, artifact, version)); } return Collections.unmodifiableSet(ret); } @Override public Set findModules(String gav) throws IllegalArgumentException { String parts[] = GradleModuleFileCache21.gavSplit(gav); String groupId = parts[0].isEmpty() ? null : parts[0]; String artifactId = parts[1].isEmpty() ? null : parts[1]; String ver = parts[2].isEmpty() ? null : parts[2]; return findModules(groupId, artifactId, ver); } /** * Returns {@code true} if all resolvable configurations are resolved. * @return true - if all resolvable configurations are resolved. */ public boolean isResolved() { if (resolved == null) { boolean b = true; for (GradleConfiguration value : configurations.values()) { if (value.isCanBeResolved()) { b &= value.isResolved(); if (!b) { break; } } } resolved = b; } return resolved; } public boolean isRootOf(GradleBaseProject other) { if (other == null) return false; return isRoot() && !other.isRoot() && subProjects.containsKey(other.name) && projectDir.equals(other.rootDir); } public boolean isSibling(GradleBaseProject other) { if (other == null) return false; return !isRoot() && !other.isRoot() && rootDir.equals(other.rootDir) && !projectDir.equals(other.projectDir); } GradleConfiguration createConfiguration(String name) { GradleConfiguration conf = new GradleConfiguration(name); configurations.put(name, conf); return conf; } /** * Retrieve the actual GradleBaseProject from the given NetBeans * {@link Project project} lookup. If the project is not a Gradle project it * returns {@code null}. It always returns a non-null value for a Gradle * project. * * @see org.netbeans.modules.gradle.api.NbGradleProject.Quality * * @param project a NetBeans project * @return the basic Gradle project info stored for the given project or * {@code null} for non-Gradle projects. */ public static GradleBaseProject get(Project project) { NbGradleProject gp = NbGradleProject.get(project); return gp != null ? gp.projectLookup(GradleBaseProject.class) : null; } static GradleBaseProject getFallback(GradleFiles files) { GradleBaseProject ret = new GradleBaseProject(); ret.name = files.getProjectDir().getName(); ret.projectDir = files.getProjectDir(); ret.buildDir = new File(files.getProjectDir(), "build"); ret.rootDir = files.getRootDir(); ret.version = "unspecified"; SubProjectInfo structure = SubProjectDiskCache.get(files.getRootDir()).loadData(); if (structure != null) { // Note: The structure information might be invalid, though we are just guessing here ret.path = structure.getProjectPath(files.getProjectDir()); ret.description = structure.getProjectDescription(files.getProjectDir()); ret.name = structure.getProjectName(files.getProjectDir()); } if (ret.path == null) { StringBuilder path = new StringBuilder(":"); //NOI18N if (!files.isRootProject()) { Path prjPath = files.getProjectDir().toPath(); Path rootPath = files.getRootDir().toPath(); String separator = ""; Path relPath = rootPath.relativize(prjPath); for(int i = 0; i < relPath.getNameCount() ; i++) { path.append(separator); path.append(relPath.getName(i)); separator = ":"; //NOI18N } } ret.path = path.toString(); } ret.status = "release"; ret.parentName = files.isRootProject() ? null : files.getRootDir().getName(); //Make advanced compile options disabled by default. Map nbprops = new HashMap<>(); nbprops.put(RunUtils.PROP_AUGMENTED_BUILD, "false"); //NOI18N nbprops.put(RunUtils.PROP_COMPILE_ON_SAVE, "false"); //NOI18N ret.netBeansProperties = Collections.unmodifiableMap(nbprops); Map subPrj = Collections.emptyMap(); if (files.isRootProject() && (files.getSettingsScript() != null)) { Set subProjects = GradleFiles.SettingsFile.getSubProjects(files.getSettingsScript()); if (!subProjects.isEmpty()) { subPrj = new HashMap<>(); for (File sp : subProjects) { subPrj.put(sp.getName(), sp); } } } ret.subProjects = Collections.unmodifiableMap(subPrj); Set plugins = new HashSet<>(); File srcDir = new File(files.getProjectDir(), "src"); if (srcDir.isDirectory()) { Set setNames = new HashSet<>(); File[] sourceSets = srcDir.listFiles(); for (File dir : sourceSets) { if (dir.isDirectory()) { if ("dist".equals(dir.getName())) { plugins.add("distribution"); } if (new File(dir, "java").isDirectory()) { plugins.add("java"); } if (new File(dir, "resources").isDirectory()) { plugins.add("java"); } if (new File(dir, "groovy").isDirectory()) { plugins.add("java"); plugins.add("groovy"); plugins.add("groovy-base"); } if (new File(dir, "scala").isDirectory()) { plugins.add("java"); plugins.add("scala"); plugins.add("scala-base"); } if (new File(dir, "webapp").isDirectory()) { plugins.add("java"); plugins.add("war"); } } } if (plugins.contains("java")) { plugins.add("java-base"); plugins.add("base"); } ret.plugins = Collections.unmodifiableSet(plugins); } return ret; } @Override public String toString() { return "GradleBaseProject{" + "name=" + name + ", projectDir=" + projectDir + ", plugins=" + plugins + '}'; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy