/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.gradle.plugins.defaults;
import com.liferay.gradle.plugins.defaults.internal.util.GradleUtil;
import com.liferay.gradle.util.Validator;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.gradle.api.Plugin;
import org.gradle.api.UncheckedIOException;
import org.gradle.api.initialization.ProjectDescriptor;
import org.gradle.api.initialization.Settings;
/**
* @author Andrea Di Giorgi
*/
public class LiferaySettingsPlugin implements Plugin<Settings> {
public static final String PROJECT_PATH_PREFIX_PROPERTY_NAME =
"project.path.prefix";
@Override
public void apply(Settings settings) {
File rootDir = settings.getRootDir();
Path rootDirPath = rootDir.toPath();
String projectPathPrefix = GradleUtil.getProperty(
settings, PROJECT_PATH_PREFIX_PROPERTY_NAME, "");
if (Validator.isNotNull(projectPathPrefix)) {
if (projectPathPrefix.charAt(0) != ':') {
projectPathPrefix = ":" + projectPathPrefix;
}
if (projectPathPrefix.charAt(projectPathPrefix.length() - 1) ==
':') {
projectPathPrefix = projectPathPrefix.substring(
0, projectPathPrefix.length() - 1);
}
}
try {
_includeProjects(
settings, rootDirPath, rootDirPath, projectPathPrefix);
}
catch (IOException ioe) {
throw new UncheckedIOException(ioe);
}
}
private Set<Path> _getDirPaths(String key, Path rootDirPath) {
String dirNamesString = System.getProperty(key);
if (Validator.isNull(dirNamesString)) {
return Collections.emptySet();
}
Set<Path> dirPaths = new HashSet<>();
for (String dirName : dirNamesString.split(",")) {
dirPaths.add(rootDirPath.resolve(dirName));
}
return dirPaths;
}
private <T extends Enum<T>> Set<T> _getFlags(
String prefix, Class<T> clazz) {
Set<T> flags = EnumSet.allOf(clazz);
Iterator<T> iterator = flags.iterator();
while (iterator.hasNext()) {
T flag = iterator.next();
String flagName = flag.toString();
flagName = flagName.replace('_', '.');
flagName = flagName.toLowerCase();
if (!Boolean.getBoolean(prefix + flagName)) {
iterator.remove();
}
}
return flags;
}
private ProjectDirType _getProjectDirType(Path dirPath) {
if (Files.exists(dirPath.resolve("build.xml"))) {
return ProjectDirType.ANT_PLUGIN;
}
if (Files.exists(dirPath.resolve("bnd.bnd"))) {
return ProjectDirType.MODULE;
}
if (Files.exists(dirPath.resolve("gulpfile.js"))) {
return ProjectDirType.THEME;
}
return ProjectDirType.UNKNOWN;
}
private void _includeProject(
Settings settings, Path projectDirPath, Path projectPathRootDirPath,
String projectPathPrefix) {
Path relativePath = projectPathRootDirPath.relativize(projectDirPath);
String projectPath = relativePath.toString();
projectPath =
projectPathPrefix + ":" +
projectPath.replace(File.separatorChar, ':');
settings.include(new String[] {projectPath});
ProjectDescriptor projectDescriptor = settings.findProject(projectPath);
projectDescriptor.setProjectDir(projectDirPath.toFile());
}
private void _includeProjects(
final Settings settings, final Path rootDirPath,
final Path projectPathRootDirPath, final String projectPathPrefix)
throws IOException {
final String buildProfile = System.getProperty("build.profile");
final Set<Path> excludedDirPaths = _getDirPaths(
"build.exclude.dirs", rootDirPath);
final Set<Path> includedDirPaths = _getDirPaths(
"build.include.dirs", rootDirPath);
final Set<ProjectDirType> excludedProjectDirTypes = _getFlags(
"build.exclude.", ProjectDirType.class);
Files.walkFileTree(
rootDirPath,
new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(
Path dirPath, BasicFileAttributes basicFileAttributes) {
if (dirPath.equals(rootDirPath)) {
return FileVisitResult.CONTINUE;
}
if (excludedDirPaths.contains(dirPath)) {
return FileVisitResult.SKIP_SUBTREE;
}
ProjectDirType projectDirType = _getProjectDirType(dirPath);
if (projectDirType == ProjectDirType.UNKNOWN) {
return FileVisitResult.CONTINUE;
}
if (excludedProjectDirTypes.contains(projectDirType)) {
return FileVisitResult.SKIP_SUBTREE;
}
if (!includedDirPaths.isEmpty() &&
!_startsWith(dirPath, includedDirPaths)) {
return FileVisitResult.SKIP_SUBTREE;
}
if (Validator.isNotNull(buildProfile) &&
Files.notExists(
dirPath.resolve(".lfrbuild-" + buildProfile))) {
return FileVisitResult.SKIP_SUBTREE;
}
_includeProject(
settings, dirPath, projectPathRootDirPath,
projectPathPrefix);
return FileVisitResult.SKIP_SUBTREE;
}
});
}
private boolean _startsWith(Path path, Iterable<Path> parentPaths) {
for (Path parentPath : parentPaths) {
if (path.startsWith(parentPath)) {
return true;
}
}
return false;
}
private static enum ProjectDirType {
ANT_PLUGIN, MODULE, THEME, UNKNOWN
}
}