/* * Copyright (c) 2017 the original author or authors. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.eclipse.buildship.core.configuration.internal; import java.io.File; import java.io.IOException; import java.util.Collections; import java.util.List; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.gradleware.tooling.toolingclient.GradleDistribution; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.buildship.core.CorePlugin; import org.eclipse.buildship.core.configuration.BuildConfiguration; import org.eclipse.buildship.core.configuration.ConfigurationManager; import org.eclipse.buildship.core.configuration.ProjectConfiguration; import org.eclipse.buildship.core.configuration.RunConfiguration; import org.eclipse.buildship.core.configuration.WorkspaceConfiguration; import org.eclipse.buildship.core.launch.GradleRunConfigurationAttributes; import org.eclipse.buildship.core.util.file.RelativePathUtils; /** * Default implementation for {@link ConfigurationManager}. */ public class DefaultConfigurationManager implements ConfigurationManager { WorkspaceConfigurationPersistence workspaceConfigurationPersistence = new WorkspaceConfigurationPersistence(); BuildConfigurationPersistence buildConfigurationPersistence = new BuildConfigurationPersistence(); @Override public WorkspaceConfiguration loadWorkspaceConfiguration() { return this.workspaceConfigurationPersistence.readWorkspaceConfig(); } @Override public void saveWorkspaceConfiguration(WorkspaceConfiguration config) { this.workspaceConfigurationPersistence.saveWorkspaceConfiguration(config); } @Override public BuildConfiguration createBuildConfiguration(File rootProjectDirectory, GradleDistribution gradleDistribution, boolean overrideWorkspaceSettings, boolean buildScansEnabled, boolean offlineMode) { BuildConfigurationProperties persistentBuildConfigProperties = new BuildConfigurationProperties(rootProjectDirectory, gradleDistribution, overrideWorkspaceSettings, buildScansEnabled, offlineMode); return new DefaultBuildConfiguration(persistentBuildConfigProperties, loadWorkspaceConfiguration()); } @Override public BuildConfiguration loadBuildConfiguration(File rootDir) { Preconditions.checkNotNull(rootDir); Preconditions.checkArgument(rootDir.exists()); Optional<IProject> projectCandidate = CorePlugin.workspaceOperations().findProjectByLocation(rootDir); BuildConfigurationProperties buildConfigProperties; if (projectCandidate.isPresent()) { IProject project = projectCandidate.get(); try { buildConfigProperties = this.buildConfigurationPersistence.readBuildConfiguratonProperties(project); } catch (Exception e) { // when the project is being imported, the configuration file might not be visible from the // Eclipse resource API; in that case we fall back to raw IO operations // a similar approach is used in JDT core to load the .classpath file // see org.eclipse.jdt.internal.core.JavaProject.readFileEntriesWithException(Map) buildConfigProperties = this.buildConfigurationPersistence.readBuildConfiguratonProperties(project.getLocation().toFile()); } } else { buildConfigProperties = this.buildConfigurationPersistence.readBuildConfiguratonProperties(rootDir); } return new DefaultBuildConfiguration(buildConfigProperties, loadWorkspaceConfiguration()); } @Override public void saveBuildConfiguration(BuildConfiguration configuration) { Preconditions.checkArgument(configuration instanceof DefaultBuildConfiguration, "Unknow configuration type: ", configuration.getClass()); BuildConfigurationProperties properties = ((DefaultBuildConfiguration)configuration).getProperties(); File rootDir = configuration.getRootProjectDirectory(); Optional<IProject> rootProject = CorePlugin.workspaceOperations().findProjectByLocation(rootDir); if (rootProject.isPresent() && rootProject.get().isAccessible()) { this.buildConfigurationPersistence.saveBuildConfiguration(rootProject.get(), properties); } else { this.buildConfigurationPersistence.saveBuildConfiguration(rootDir, properties); } } @Override public ProjectConfiguration createProjectConfiguration(BuildConfiguration configuration, File projectDir) { return new DefaultProjectConfiguration(projectDir, configuration); } @Override public ProjectConfiguration loadProjectConfiguration(IProject project) { String pathToRoot = this.buildConfigurationPersistence.readPathToRoot(project.getLocation().toFile()); File rootDir = relativePathToProjectRoot(project.getLocation(), pathToRoot); BuildConfiguration buildConfig = loadBuildConfiguration(rootDir); return new DefaultProjectConfiguration(project.getLocation().toFile(), buildConfig); } private ProjectConfiguration loadProjectConfiguration(File projectDir) { String pathToRoot = this.buildConfigurationPersistence.readPathToRoot(projectDir); File rootDir = relativePathToProjectRoot(new Path(projectDir.getAbsolutePath()), pathToRoot); BuildConfiguration buildConfig = loadBuildConfiguration(rootDir); return new DefaultProjectConfiguration(projectDir, buildConfig); } @Override public void saveProjectConfiguration(ProjectConfiguration projectConfiguration) { BuildConfiguration buildConfiguration = projectConfiguration.getBuildConfiguration(); File projectDir = projectConfiguration.getProjectDir(); File rootDir = buildConfiguration.getRootProjectDirectory(); String pathToRoot = projectRootToRelativePath(projectDir, rootDir); Optional<IProject> project = CorePlugin.workspaceOperations().findProjectByLocation(projectDir); if (project.isPresent() && project.get().isAccessible()) { this.buildConfigurationPersistence.savePathToRoot(project.get(), pathToRoot); } else { this.buildConfigurationPersistence.savePathToRoot(projectDir, pathToRoot); } saveBuildConfiguration(buildConfiguration); } @Override public void deleteProjectConfiguration(IProject project) { if (project.isAccessible()) { this.buildConfigurationPersistence.deletePathToRoot(project); } else { this.buildConfigurationPersistence.deletePathToRoot(project.getLocation().toFile()); } } @Override public RunConfiguration loadRunConfiguration(ILaunchConfiguration launchConfiguration) { GradleRunConfigurationAttributes attributes = GradleRunConfigurationAttributes.from(launchConfiguration); BuildConfigurationProperties buildConfigProperties; try { BuildConfiguration buildConfig = loadProjectConfiguration(attributes.getWorkingDir()).getBuildConfiguration(); buildConfigProperties = ((DefaultBuildConfiguration)buildConfig).getProperties(); } catch (Exception e) { CorePlugin.logger().debug("Can't load build config from " + attributes.getWorkingDir(), e); buildConfigProperties = new BuildConfigurationProperties(attributes.getWorkingDir(), attributes.getGradleDistribution(), attributes.isOverrideBuildSettings(), attributes.isBuildScansEnabled(), attributes.isOffline()); } RunConfigurationProperties runConfigProperties = new RunConfigurationProperties(attributes.getTasks(), attributes.getGradleDistribution(), attributes.getJavaHome(), attributes.getJvmArguments(), attributes.getArgumentExpressions(), attributes.isShowConsoleView(), attributes.isShowExecutionView(), attributes.isOverrideBuildSettings(), attributes.isBuildScansEnabled(), attributes.isOffline()); return new DefaultRunConfiguration(loadWorkspaceConfiguration(), buildConfigProperties, runConfigProperties); } @Override public RunConfiguration createDefaultRunConfiguration(BuildConfiguration configuration) { return createRunConfiguration(configuration, Collections.<String>emptyList(), null, GradleDistribution.fromBuild(), Collections.<String>emptyList(), Collections.<String>emptyList(), false, false, false, false, false); } @Override public RunConfiguration createRunConfiguration(BuildConfiguration configuration, List<String> tasks, File javaHome, GradleDistribution gradleDistribution, List<String> jvmArguments, List<String> arguments, boolean showExecutionsView, boolean showConsoleView, boolean overrideBuildSettings, boolean buildScansEnabled, boolean offlineMode) { Preconditions.checkArgument(configuration instanceof DefaultBuildConfiguration, "Unknow configuration type: ", configuration.getClass()); DefaultBuildConfiguration buildConfiguration = (DefaultBuildConfiguration) configuration; RunConfigurationProperties runConfig = new RunConfigurationProperties(tasks, gradleDistribution, javaHome, jvmArguments, arguments, showConsoleView, showExecutionsView, overrideBuildSettings, buildScansEnabled, offlineMode); return new DefaultRunConfiguration(loadWorkspaceConfiguration(), buildConfiguration.getProperties(), runConfig); } private static File relativePathToProjectRoot(IPath projectPath, String path) { IPath pathToRoot = new Path(path); return canonicalize(RelativePathUtils.getAbsolutePath(projectPath, pathToRoot).toFile()); } private static File canonicalize(File file) { try { return file.getCanonicalFile(); } catch (IOException e) { throw new IllegalArgumentException(e); } } private static String projectRootToRelativePath(File projectDir, File rootDir) { IPath rootProjectPath = new Path(rootDir.getPath()); IPath projectPath = new Path(projectDir.getPath()); return RelativePathUtils.getRelativePath(projectPath, rootProjectPath).toPortableString(); } }