/**
* 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.node;
import com.liferay.gradle.plugins.node.internal.util.GradleUtil;
import com.liferay.gradle.plugins.node.tasks.DownloadNodeModuleTask;
import com.liferay.gradle.plugins.node.tasks.DownloadNodeTask;
import com.liferay.gradle.plugins.node.tasks.ExecuteNodeTask;
import com.liferay.gradle.plugins.node.tasks.ExecuteNpmTask;
import com.liferay.gradle.plugins.node.tasks.NpmInstallTask;
import com.liferay.gradle.plugins.node.tasks.NpmShrinkwrapTask;
import com.liferay.gradle.plugins.node.tasks.PublishNodeModuleTask;
import groovy.json.JsonSlurper;
import java.io.File;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import org.gradle.api.Action;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.internal.plugins.osgi.OsgiHelper;
import org.gradle.api.specs.Spec;
import org.gradle.api.tasks.Delete;
import org.gradle.api.tasks.TaskContainer;
/**
* @author Andrea Di Giorgi
*/
public class NodePlugin implements Plugin<Project> {
public static final String CLEAN_NPM_TASK_NAME = "cleanNPM";
public static final String DOWNLOAD_NODE_TASK_NAME = "downloadNode";
public static final String EXTENSION_NAME = "node";
public static final String NPM_INSTALL_TASK_NAME = "npmInstall";
public static final String NPM_SHRINKWRAP_TASK_NAME = "npmShrinkwrap";
@Override
public void apply(Project project) {
final NodeExtension nodeExtension = GradleUtil.addExtension(
project, EXTENSION_NAME, NodeExtension.class);
final DownloadNodeTask downloadNodeTask = _addTaskDownloadNode(
project, nodeExtension);
Delete cleanNpmTask = _addTaskCleanNpm(project);
NpmInstallTask npmInstallTask = _addTaskNpmInstall(
project, cleanNpmTask);
_addTaskNpmShrinkwrap(project, cleanNpmTask, npmInstallTask);
_configureTasksDownloadNodeModule(project, npmInstallTask);
_configureTasksExecuteNode(
project, nodeExtension, GradleUtil.isRunningInsideDaemon());
_configureTasksPublishNodeModule(project);
project.afterEvaluate(
new Action<Project>() {
@Override
public void execute(Project project) {
_configureTaskDownloadNodeGlobal(
downloadNodeTask, nodeExtension);
_configureTasksExecuteNpm(project, nodeExtension);
}
});
}
private Delete _addTaskCleanNpm(Project project) {
Delete delete = GradleUtil.addTask(
project, CLEAN_NPM_TASK_NAME, Delete.class);
delete.delete("node_modules", "npm-shrinkwrap.json");
delete.setDescription("Deletes NPM files from this project.");
return delete;
}
private DownloadNodeTask _addTaskDownloadNode(
Project project, final NodeExtension nodeExtension) {
return _addTaskDownloadNode(
project, DOWNLOAD_NODE_TASK_NAME, nodeExtension);
}
private DownloadNodeTask _addTaskDownloadNode(
Project project, String taskName, final NodeExtension nodeExtension) {
DownloadNodeTask downloadNodeTask = GradleUtil.addTask(
project, taskName, DownloadNodeTask.class);
downloadNodeTask.setNodeDir(
new Callable<File>() {
@Override
public File call() throws Exception {
return nodeExtension.getNodeDir();
}
});
downloadNodeTask.setNodeExeUrl(
new Callable<String>() {
@Override
public String call() throws Exception {
return nodeExtension.getNodeExeUrl();
}
});
downloadNodeTask.setNodeUrl(
new Callable<String>() {
@Override
public String call() throws Exception {
return nodeExtension.getNodeUrl();
}
});
downloadNodeTask.setNpmUrl(
new Callable<String>() {
@Override
public String call() throws Exception {
return nodeExtension.getNpmUrl();
}
});
downloadNodeTask.onlyIf(
new Spec<Task>() {
@Override
public boolean isSatisfiedBy(Task task) {
return nodeExtension.isDownload();
}
});
downloadNodeTask.setDescription(
"Downloads Node.js in the project build directory.");
return downloadNodeTask;
}
private NpmInstallTask _addTaskNpmInstall(
Project project, Delete cleanNpmTask) {
NpmInstallTask npmInstallTask = GradleUtil.addTask(
project, NPM_INSTALL_TASK_NAME, NpmInstallTask.class);
npmInstallTask.mustRunAfter(cleanNpmTask);
npmInstallTask.setDescription(
"Installs Node packages from package.json.");
npmInstallTask.setNpmInstallRetries(2);
return npmInstallTask;
}
private NpmShrinkwrapTask _addTaskNpmShrinkwrap(
Project project, Delete cleanNpmTask, NpmInstallTask npmInstallTask) {
NpmShrinkwrapTask npmShrinkwrapTask = GradleUtil.addTask(
project, NPM_SHRINKWRAP_TASK_NAME, NpmShrinkwrapTask.class);
npmShrinkwrapTask.dependsOn(cleanNpmTask, npmInstallTask);
npmShrinkwrapTask.setDescription(
"Locks down the versions of a package's dependencies in order to " +
"control which versions of each dependency will be used.");
return npmShrinkwrapTask;
}
private void _configureTaskDownloadNodeGlobal(
DownloadNodeTask downloadNodeTask, NodeExtension nodeExtension) {
if (!nodeExtension.isDownload() || !nodeExtension.isGlobal()) {
return;
}
Project project = downloadNodeTask.getProject();
Project rootProject = project.getRootProject();
DownloadNodeTask rootDownloadNodeTask = null;
TaskContainer taskContainer = rootProject.getTasks();
Set<DownloadNodeTask> rootDownloadNodeTasks = taskContainer.withType(
DownloadNodeTask.class);
File nodeDir = downloadNodeTask.getNodeDir();
String nodeExeUrl = downloadNodeTask.getNodeExeUrl();
String nodeUrl = downloadNodeTask.getNodeUrl();
for (DownloadNodeTask curRootDownloadNodeTask : rootDownloadNodeTasks) {
if (nodeDir.equals(curRootDownloadNodeTask.getNodeDir()) &&
nodeExeUrl.equals(curRootDownloadNodeTask.getNodeExeUrl()) &&
nodeUrl.equals(curRootDownloadNodeTask.getNodeUrl())) {
rootDownloadNodeTask = curRootDownloadNodeTask;
break;
}
}
if (rootDownloadNodeTask == null) {
String taskName = DOWNLOAD_NODE_TASK_NAME;
if (!rootDownloadNodeTasks.isEmpty()) {
taskName += rootDownloadNodeTasks.size();
}
rootDownloadNodeTask = _addTaskDownloadNode(
rootProject, taskName, nodeExtension);
}
downloadNodeTask.deleteAllActions();
downloadNodeTask.dependsOn(rootDownloadNodeTask);
}
private void _configureTaskDownloadNodeModule(
DownloadNodeModuleTask downloadNodeModuleTask,
final NpmInstallTask npmInstallTask) {
downloadNodeModuleTask.onlyIf(
new Spec<Task>() {
@Override
public boolean isSatisfiedBy(Task task) {
DownloadNodeModuleTask downloadNodeModuleTask =
(DownloadNodeModuleTask)task;
File moduleDir = downloadNodeModuleTask.getModuleDir();
File moduleParentDir = moduleDir.getParentFile();
if (!moduleParentDir.equals(
npmInstallTask.getNodeModulesDir())) {
return true;
}
File packageJsonFile = npmInstallTask.getPackageJsonFile();
if (!packageJsonFile.exists()) {
return true;
}
String moduleName = downloadNodeModuleTask.getModuleName();
JsonSlurper jsonSlurper = new JsonSlurper();
Map<String, Object> packageJsonMap =
(Map<String, Object>)jsonSlurper.parse(packageJsonFile);
Map<String, Object> dependenciesJsonMap =
(Map<String, Object>)packageJsonMap.get("dependencies");
if ((dependenciesJsonMap != null) &&
dependenciesJsonMap.containsKey(moduleName)) {
return false;
}
dependenciesJsonMap =
(Map<String, Object>)packageJsonMap.get(
"devDependencies");
if ((dependenciesJsonMap != null) &&
dependenciesJsonMap.containsKey(moduleName)) {
return false;
}
return true;
}
});
}
private void _configureTaskExecuteNode(
ExecuteNodeTask executeNodeTask, final NodeExtension nodeExtension,
boolean useGradleExec) {
executeNodeTask.setNodeDir(
new Callable<File>() {
@Override
public File call() throws Exception {
if (nodeExtension.isDownload()) {
return nodeExtension.getNodeDir();
}
return null;
}
});
executeNodeTask.setUseGradleExec(useGradleExec);
}
private void _configureTaskExecuteNpm(
ExecuteNpmTask executeNpmTask, NodeExtension nodeExtension) {
executeNpmTask.args(nodeExtension.getNpmArgs());
}
private void _configureTaskPublishNodeModule(
PublishNodeModuleTask publishNodeModuleTask) {
final Project project = publishNodeModuleTask.getProject();
publishNodeModuleTask.setModuleDescription(
new Callable<String>() {
@Override
public String call() throws Exception {
return project.getDescription();
}
});
publishNodeModuleTask.setModuleName(
new Callable<String>() {
@Override
public String call() throws Exception {
String moduleName = _osgiHelper.getBundleSymbolicName(
project);
int pos = moduleName.indexOf('.');
if (pos != -1) {
moduleName = moduleName.substring(pos + 1);
moduleName = moduleName.replace('.', '-');
}
return moduleName;
}
});
publishNodeModuleTask.setModuleVersion(
new Callable<Object>() {
@Override
public Object call() throws Exception {
return project.getVersion();
}
});
}
private void _configureTasksDownloadNodeModule(
Project project, final NpmInstallTask npmInstallTask) {
TaskContainer taskContainer = project.getTasks();
taskContainer.withType(
DownloadNodeModuleTask.class,
new Action<DownloadNodeModuleTask>() {
@Override
public void execute(
DownloadNodeModuleTask downloadNodeModuleTask) {
_configureTaskDownloadNodeModule(
downloadNodeModuleTask, npmInstallTask);
}
});
}
private void _configureTasksExecuteNode(
Project project, final NodeExtension nodeExtension,
final boolean useGradleExec) {
TaskContainer taskContainer = project.getTasks();
taskContainer.withType(
ExecuteNodeTask.class,
new Action<ExecuteNodeTask>() {
@Override
public void execute(ExecuteNodeTask executeNodeTask) {
_configureTaskExecuteNode(
executeNodeTask, nodeExtension, useGradleExec);
}
});
}
private void _configureTasksExecuteNpm(
Project project, final NodeExtension nodeExtension) {
TaskContainer taskContainer = project.getTasks();
taskContainer.withType(
ExecuteNpmTask.class,
new Action<ExecuteNpmTask>() {
@Override
public void execute(ExecuteNpmTask executeNpmTask) {
_configureTaskExecuteNpm(executeNpmTask, nodeExtension);
}
});
}
private void _configureTasksPublishNodeModule(Project project) {
TaskContainer taskContainer = project.getTasks();
taskContainer.withType(
PublishNodeModuleTask.class,
new Action<PublishNodeModuleTask>() {
@Override
public void execute(
PublishNodeModuleTask publishNodeModuleTask) {
_configureTaskPublishNodeModule(publishNodeModuleTask);
}
});
}
private static final OsgiHelper _osgiHelper = new OsgiHelper();
}