| /* |
| * 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.GradleArtifactStore; |
| import static org.netbeans.modules.gradle.api.GradleDependency.*; |
| import org.netbeans.modules.gradle.spi.ProjectInfoExtractor; |
| import java.io.File; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.LinkedHashMap; |
| import java.util.LinkedHashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.TreeMap; |
| import java.util.TreeSet; |
| import org.netbeans.modules.gradle.GradleModuleFileCache21; |
| import org.netbeans.modules.gradle.spi.GradleSettings; |
| import org.openide.util.lookup.ServiceProvider; |
| |
| /** |
| * This is the de-serialization support class for GradleBaseProject. |
| * |
| * @author Laszlo Kishalmi |
| */ |
| @SuppressWarnings("unchecked") |
| class GradleBaseProjectBuilder implements ProjectInfoExtractor.Result { |
| |
| final static Map<String, List<String>> DEPENDENCY_TO_PLUGIN = new LinkedHashMap<>(); |
| |
| static { |
| addDependencyPlugin("javax:javaee-api:.*", "ejb", "jpa"); |
| addDependencyPlugin("javax:javaee-web-api:.*", "ejb", "jpa"); |
| addDependencyPlugin("javaee:javaee-api:.*", "ejb"); |
| addDependencyPlugin("org.hibernate.javax.persistence:hibernate-jpa-2.0-api:.*", "jpa"); |
| addDependencyPlugin("org.hibernate.javax.persistence:hibernate-jpa-2.1-api:.*", "jpa"); |
| addDependencyPlugin("org.eclipse.persistence:javax.persistence:.*", "jpa"); |
| } |
| |
| private static void addDependencyPlugin(String dependency, String... plugins) { |
| DEPENDENCY_TO_PLUGIN.put(dependency, Arrays.asList(plugins)); |
| } |
| |
| final Map<String, Object> info; |
| final GradleBaseProject prj = new GradleBaseProject(); |
| final Set<String> problems = new LinkedHashSet<>(); |
| final GradleArtifactStore artifactSore = GradleArtifactStore.getDefault(); |
| |
| GradleBaseProjectBuilder(Map<String, Object> info) { |
| this.info = new TreeMap<>(info); |
| } |
| |
| void build() { |
| processBasicInfo(); |
| processTasks(); |
| processDependencies(); |
| processDependencyPlugins(); |
| } |
| |
| void processBasicInfo() { |
| prj.name = (String) info.get("project_name"); |
| prj.path = (String) info.get("project_path"); |
| prj.status = (String) info.get("project_status"); |
| prj.parentName = (String) info.get("project_parent_name"); |
| prj.displayName = (String) info.get("project_display_name"); |
| prj.description = (String) info.get("project_description"); |
| prj.group = (String) info.get("project_group"); |
| prj.buildDir = (File) info.get("project_buildDir"); |
| prj.projectDir = (File) info.get("project_projectDir"); |
| prj.rootDir = (File) info.get("project_rootDir"); |
| prj.version = (String) info.get("project_version"); |
| prj.license = (String) info.get("license"); |
| |
| prj.plugins = new TreeSet<>(createSet((Set<String>) info.get("plugins"))); |
| Map<String, File> rawSubprojects = (Map<String, File>) info.get("project_subProjects"); |
| Map<String, File> refinedSubprojects = (Map<String, File>) info.get("project_subProjects"); |
| for (Map.Entry<String, File> entry : rawSubprojects.entrySet()) { |
| refinedSubprojects.put(entry.getKey(), entry.getValue().isAbsolute() ? entry.getValue() : new File(prj.rootDir, entry.getValue().toString())); |
| } |
| prj.subProjects = Collections.unmodifiableMap(refinedSubprojects); |
| prj.includedBuilds = (Map<String, File>) info.get("project_includedBuilds"); |
| if (info.containsKey("buildClassPath")) { |
| prj.buildClassPath = (Set<File>) info.get("buildClassPath"); |
| } |
| if (info.containsKey("nbprops")) { |
| Map<String,String> props = new HashMap<>((Map<String,String>) info.get("nbprops")); |
| prj.netBeansProperties = Collections.unmodifiableMap(props); |
| } |
| } |
| |
| void processTasks() { |
| Set<String[]> tasks = (Set<String[]>) info.get("tasks"); |
| if (tasks != null) { |
| for (String[] arr : tasks) { |
| GradleTask task = new GradleTask(arr[0], arr[1], arr[2], arr[3]); |
| prj.tasksByName.put(task.getName(), task); |
| List<GradleTask> group = prj.tasksByGroup.get(task.getGroup()); |
| if (group == null) { |
| group = new ArrayList<>(); |
| prj.tasksByGroup.put(task.getGroup(), group); |
| } |
| group.add(task); |
| } |
| } |
| } |
| |
| void processDependencies() { |
| |
| File gradleUserHome = (File) info.get("gradle_user_home"); |
| gradleUserHome = gradleUserHome != null ? gradleUserHome : GradleSettings.getDefault().getGradleUserHome(); |
| |
| Set<File> sourceSetOutputs = new HashSet<>(); |
| Set<String> sourceSetNames = (Set<String>) info.get("sourcesets"); |
| if (sourceSetNames != null) { |
| for (String name : sourceSetNames) { |
| Set<File> dirs = (Set<File>) info.get("sourceset_" + name + "_output_classes"); |
| sourceSetOutputs.addAll(dirs); |
| sourceSetOutputs.add((File) info.get("sourceset_" + name + "_output_resources")); |
| } |
| } |
| prj.outputPaths = createSet(sourceSetOutputs); |
| |
| Set<String> configurationNames = createSet((Set<String>) info.get("configurations")); |
| Map<String, File> prjs = (Map<String, File>) info.get("project_dependencies"); |
| prjs = prjs != null ? prjs : Collections.<String, File>emptyMap(); |
| |
| Map<String, Set<File>> arts = (Map<String, Set<File>>) info.get("resolved_jvm_artifacts"); |
| arts = arts != null ? arts : Collections.<String, Set<File>>emptyMap(); |
| Map<String, Set<File>> sources = (Map<String, Set<File>>) info.get("resolved_sources_artifacts"); |
| sources = sources != null ? sources : Collections.<String, Set<File>>emptyMap(); |
| Map<String, Set<File>> javadocs = (Map<String, Set<File>>) info.get("resolved_javadoc_artifacts"); |
| javadocs = javadocs != null ? javadocs : Collections.<String, Set<File>>emptyMap(); |
| |
| Map<String, String> unresolvedProblems = (Map<String, String>) info.get("unresolved_problems"); |
| unresolvedProblems = unresolvedProblems != null ? unresolvedProblems : Collections.<String, String>emptyMap(); |
| Map<String, ModuleDependency> components = new HashMap<>(); |
| for (Map.Entry<String, Set<File>> entry : arts.entrySet()) { |
| String componentId = entry.getKey(); |
| // Looking at cache first as we might have the chance to find Sources and Javadocs |
| ModuleDependency dep = resolveModuleDependency(gradleUserHome, componentId); |
| if (!dep.getArtifacts().equals(entry.getValue())) { |
| dep = new ModuleDependency(componentId, entry.getValue()); |
| } |
| components.put(componentId, dep); |
| if (sources.containsKey(componentId)) { |
| dep.sources = sources.get(entry.getKey()); |
| } |
| if (javadocs.containsKey(componentId)) { |
| dep.javadoc = javadocs.get(entry.getKey()); |
| } |
| } |
| Map<String, ProjectDependency> projects = new HashMap<>(); |
| for (Map.Entry<String, File> entry : prjs.entrySet()) { |
| ProjectDependency dep = new ProjectDependency(entry.getKey(), entry.getValue()); |
| projects.put(entry.getKey(), dep); |
| } |
| Map<String, UnresolvedDependency> unresolved = new HashMap<>(); |
| for (Map.Entry<String, String> entry : unresolvedProblems.entrySet()) { |
| UnresolvedDependency dep = new UnresolvedDependency(entry.getKey()); |
| dep.problem = entry.getValue(); |
| unresolved.put(entry.getKey(), dep); |
| } |
| if (configurationNames != null) { |
| for (String name : configurationNames) { |
| GradleConfiguration conf = prj.createConfiguration(name); |
| conf.modules = new HashSet<>(); |
| Boolean nonResolvingConf = (Boolean)info.get("configuration_" + name + "_non_resolving"); |
| conf.canBeResolved = nonResolvingConf != null ? !nonResolvingConf : true; |
| Set<String> requiredComponents = (Set<String>) info.get("configuration_" + name + "_components"); |
| if (requiredComponents != null) { |
| for (String c : requiredComponents) { |
| ModuleDependency dep = components.get(c); |
| if (dep != null) { |
| conf.modules.add(dep); |
| } else { |
| dep = resolveModuleDependency(gradleUserHome, c); |
| if (dep != null) { |
| components.put(c, dep); |
| conf.modules.add(dep); |
| } else { |
| // NETBEANS-5161: This could happen on composite projects |
| // TODO: Implement composite project module dependency |
| } |
| } |
| } |
| } |
| conf.projects = new HashSet<>(); |
| Set<String> requiredProjects = (Set<String>) info.get("configuration_" + name + "_projects"); |
| if (requiredProjects != null) { |
| for (String p : requiredProjects) { |
| conf.projects.add(projects.get(p)); |
| } |
| } |
| conf.unresolved = new HashSet<>(); |
| Set<String> unresolvedComp = (Set<String>) info.get("configuration_" + name + "_unresolved"); |
| if (unresolvedComp != null) { |
| for (String u : unresolvedComp) { |
| conf.unresolved.add(unresolved.get(u)); |
| } |
| } |
| Set<File> files = (Set<File>) info.get("configuration_" + name + "_files"); |
| if (files != null) { |
| files = new HashSet<>(files); |
| files.removeAll(sourceSetOutputs); |
| } |
| conf.files = new FileCollectionDependency(createSet(files)); |
| Boolean transitive = (Boolean) info.get("configuration_" + name + "_transitive"); |
| conf.transitive = transitive == null ? true : transitive; |
| |
| conf.description = (String) info.get("configuration_" + name + "_description"); |
| } |
| for (String name : configurationNames) { |
| GradleConfiguration conf = prj.configurations.get(name); |
| Set<String> extendsFrom = (Set<String>) info.get("configuration_" + name + "_extendsFrom"); |
| Set<GradleConfiguration> parents = new HashSet<>(); |
| if (extendsFrom != null) { |
| for (String n : extendsFrom) { |
| parents.add(prj.configurations.get(n)); |
| } |
| } |
| conf.extendsFrom = createSet(parents); |
| } |
| |
| } |
| |
| // Create file -> component map |
| for (ModuleDependency dep : components.values()) { |
| for (File f : dep.getArtifacts()) { |
| prj.componentsByFile.put(f, dep); |
| } |
| for (File f : dep.getSources()) { |
| prj.componentsByFile.put(f, dep); |
| } |
| for (File f : dep.getJavadoc()) { |
| prj.componentsByFile.put(f, dep); |
| } |
| } |
| |
| // Add detailed problems on unresolved dependencies |
| problems.addAll(unresolvedProblems.values()); |
| } |
| |
| private ModuleDependency resolveModuleDependency(File gradleUserHome, String c) { |
| GradleModuleFileCache21 moduleCache = GradleModuleFileCache21.getGradleFileCache(gradleUserHome.toPath()); |
| try { |
| GradleModuleFileCache21.CachedArtifactVersion artVersion = moduleCache.resolveModule(c); |
| Set<File> binaries = artifactSore.getBinaries(c); |
| if (((binaries == null) || binaries.isEmpty()) && (artVersion.getBinary() != null)) { |
| binaries = Collections.singleton(artVersion.getBinary().getPath().toFile()); |
| } |
| ModuleDependency ret = new ModuleDependency(c, binaries); |
| if (artVersion.getSources() != null) { |
| ret.sources = Collections.singleton(artVersion.getSources().getPath().toFile()); |
| } |
| if (artVersion.getJavaDoc() != null) { |
| ret.javadoc = Collections.singleton(artVersion.getJavaDoc().getPath().toFile()); |
| } |
| return ret; |
| } catch (IllegalArgumentException iae) { |
| // NETBEANS-5161: This could happen on composite projects |
| return null; |
| } |
| } |
| |
| private void processDependencyPlugins() { |
| GradleConfiguration compile = prj.configurations.get("compile"); //NOI18N |
| if (compile != null) { |
| Set<GradleConfiguration> parents = compile.getAllParents(); |
| for (GradleConfiguration config : parents) { |
| for (String dependency : DEPENDENCY_TO_PLUGIN.keySet()) { |
| if (!config.findModules(dependency).isEmpty()) { |
| prj.plugins.addAll(DEPENDENCY_TO_PLUGIN.get(dependency)); |
| } |
| } |
| } |
| } |
| } |
| |
| |
| private <T> Set<T> createSet(Set<T> origin) { |
| if (origin == null) { |
| return Collections.<T>emptySet(); |
| } |
| switch (origin.size()) { |
| case 0: |
| return Collections.<T>emptySet(); |
| case 1: |
| return Collections.singleton(origin.iterator().next()); |
| default: { |
| return Collections.unmodifiableSet(origin); |
| } |
| } |
| } |
| |
| @Override |
| @SuppressWarnings("rawtypes") |
| public Set getExtract() { |
| return Collections.singleton(prj); |
| } |
| |
| @Override |
| public Set<String> getProblems() { |
| return Collections.unmodifiableSet(problems); |
| } |
| |
| @ServiceProvider(service = ProjectInfoExtractor.class, position = Integer.MIN_VALUE) |
| @SuppressWarnings("rawtypes") |
| public static final class Extractor implements ProjectInfoExtractor { |
| |
| @Override |
| public Result extract(Map<String, Object> props, Map<Class, Object> otherInfo) { |
| GradleBaseProjectBuilder result = new GradleBaseProjectBuilder(props); |
| result.build(); |
| return result; |
| } |
| |
| @Override |
| public Result fallback(GradleFiles files) { |
| return new DefaultResult(GradleBaseProject.getFallback(files)); |
| } |
| |
| } |
| } |