/*
* Copyright (c) 2015 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
*
* Contributors:
* Etienne Studer & Donát Csikós (Gradle Inc.) - initial API and implementation and initial documentation
*/
package org.eclipse.buildship.core.configuration.internal;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.buildship.core.CorePlugin;
import org.eclipse.buildship.core.configuration.GradleProjectMarker;
/**
* Validates the project configuration when a relevant resources changes.
*/
final class GradleProjectValidationResourceDeltaVisitor implements IResourceDeltaVisitor {
private final GradleProjectValidator gradleProjectValidator;
GradleProjectValidationResourceDeltaVisitor(IProject project) {
this.gradleProjectValidator = new GradleProjectValidator(project);
}
/**
* Forces validation of the project.
*
* @return {@code true} if the validation succeeds, {@code false} otherwise
* @throws CoreException thrown if there is a problem with the marker operations
*/
public boolean validate() throws CoreException {
return this.gradleProjectValidator.validate();
}
/**
* Triggers validation of the project if the resource delta affects the project configuration.
*
* @param delta the changed resource
* @return {@code true} if the resource delta's children should be visited
*/
@Override
public boolean visit(IResourceDelta delta) throws CoreException {
IPath settingsFolderProjectRelativePath = this.gradleProjectValidator.getSettingsFolder().getProjectRelativePath();
IPath preferencesFileProjectRelativePath = this.gradleProjectValidator.getPreferencesFile().getProjectRelativePath();
if (delta.getProjectRelativePath().equals(settingsFolderProjectRelativePath)) {
if (delta.getKind() == IResourceDelta.ADDED || delta.getKind() == IResourceDelta.REMOVED) {
// handle the use case when the .settings folder is added or removed
// (this also covers the use case of renaming the .settings folder to something else)
validate();
return false;
}
} else if (delta.getProjectRelativePath().equals(preferencesFileProjectRelativePath)) {
if (delta.getKind() == IResourceDelta.ADDED || delta.getKind() == IResourceDelta.REMOVED || delta.getKind() == IResourceDelta.CHANGED) {
// handle the use case when the gradle.prefs file is added or removed or changed
// (this also covers the use case of renaming the gradle.prefs file to something else)
validate();
return false;
}
}
return true;
}
/**
* Validates the Gradle project configuration and adds error markers to the given {@link org.eclipse.core.resources.IProject} instance if the configuration is missing or
* invalid.
*/
private static final class GradleProjectValidator {
private final IProject project;
private final IFolder settingsFolder;
private final IFile preferencesFile;
private GradleProjectValidator(IProject project) {
this.project = project;
this.settingsFolder = project.getFolder(".settings");
this.preferencesFile = project.getFile(".settings/" + CorePlugin.PLUGIN_ID + ".prefs");
}
public IFolder getSettingsFolder() {
return this.settingsFolder;
}
public IFile getPreferencesFile() {
return this.preferencesFile;
}
/**
* Validates the project configuration and sets error markers if needed.
*
* @return {@code true} if the validation succeeds, {@code false} otherwise
* @throws CoreException thrown if there is a problem with the marker operations
*/
public boolean validate() throws CoreException {
// initially, remove all markers from the project and the preference file
GradleProjectMarker.INSTANCE.removeMarkerFromResourceRecursively(this.project);
// todo (etst) extract i18n keys
//CHECKSTYLE:OFF, required due to false negative in Checkstyle
// validate the existence of the .settings folder
if (!this.settingsFolder.exists()) {
String message = String.format("Missing Gradle project configuration folder: %s", this.settingsFolder.getProjectRelativePath());
GradleProjectMarker.INSTANCE.addMarkerToResource(this.project, message);
return false;
}
// validate the existence of the .settings/gradle.prefs file
else if (!this.preferencesFile.exists()) {
String message = String.format("Missing Gradle project configuration file: %s", this.preferencesFile.getProjectRelativePath());
GradleProjectMarker.INSTANCE.addMarkerToResource(this.project, message);
return false;
}
// validate the state of the .settings/gradle.prefs file
else {
try {
CorePlugin.configurationManager().loadProjectConfiguration(this.project);
} catch (Exception e) {
String message = String.format("Invalid Gradle project configuration file: %s", this.preferencesFile.getProjectRelativePath());
GradleProjectMarker.INSTANCE.addMarkerToResource(this.preferencesFile, message);
return false;
}
}
//CHECKSTYLE:ON
return true;
}
}
}