AbstractNodeJsMojo.java
- /*
- * #%L
- * wcm.io
- * %%
- * Copyright (C) 2014 wcm.io
- * %%
- * Licensed 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.
- * #L%
- */
- package io.wcm.maven.plugins.nodejs.mojo;
- import java.io.File;
- import java.io.IOException;
- import java.util.List;
- import org.apache.commons.lang3.StringUtils;
- import org.apache.maven.artifact.Artifact;
- import org.apache.maven.artifact.DefaultArtifact;
- import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
- import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
- import org.apache.maven.artifact.resolver.ArtifactResolutionException;
- import org.apache.maven.artifact.resolver.ArtifactResolver;
- import org.apache.maven.artifact.versioning.ComparableVersion;
- import org.apache.maven.artifact.versioning.VersionRange;
- import org.apache.maven.execution.MavenSession;
- import org.apache.maven.model.Dependency;
- import org.apache.maven.plugin.AbstractMojo;
- import org.apache.maven.plugin.MojoExecutionException;
- import org.apache.maven.plugins.annotations.Component;
- import org.apache.maven.plugins.annotations.Parameter;
- import org.apache.maven.project.MavenProject;
- import org.codehaus.plexus.util.FileUtils;
- import io.wcm.maven.plugins.nodejs.installation.NodeInstallationInformation;
- import io.wcm.maven.plugins.nodejs.installation.NodeUnarchiveTask;
- /**
- * Common Node.js Mojo functionality.
- */
- public abstract class AbstractNodeJsMojo extends AbstractMojo {
- /**
- * Node.js version (minimum version: 6.3.0). Can be specified with or without "v" prefix.
- */
- @Parameter(property = "nodejs.version", defaultValue = "10.15.3", required = true)
- protected String nodeJsVersion;
- /**
- * NPM version. If not set the NPM version that is bundled with Node.js is used.
- */
- @Parameter(property = "nodejs.npm.version")
- protected String npmVersion;
- /**
- * Default location where Node.js will be extracted to and run from
- */
- @Parameter(property = "nodejs.directory", defaultValue = "${java.io.tmpdir}/nodejs")
- protected File nodeJsDirectory;
- /**
- * Tasks that should be run on Node.js execution.
- * <p>
- * You can define different types of tasks: <code>npmInstallTask</code> or <code>nodeJsTask</code> items.
- * </p>
- * <p>
- * Example 1:
- * </p>
- *
- * <pre>
- * <tasks>
- * <npmInstallTask>
- * <workingDirectory>${frontend.dir}</workingDirectory>
- * </npmInstallTask>
- * <nodeJsTask>
- * <workingDirectory>${frontend.dir}</workingDirectory>
- * <moduleName>grunt-cli</moduleName>
- * <executableName>grunt</executableName>
- * <arguments>
- * <argument>build</argument>
- * </arguments>
- * </nodeJsTask>
- * </tasks>
- * </pre>
- * <p>
- * Example 2:
- * </p>
- *
- * <pre>
- * <tasks>
- * <npmInstallTask>
- * <workingDirectory>${frontend.dir}</workingDirectory>
- * </npmInstallTask>
- * <nodeJsTask>
- * <workingDirectory>${frontend.dir}</workingDirectory>
- * <moduleName>npm</moduleName>
- * <executableName>npm-cli</executableName>
- * <arguments>
- * <argument>run</argument>
- * <argument>test</argument>
- * </arguments>
- * </nodeJsTask>
- * </tasks>
- * </pre>
- */
- @Parameter
- protected List<? extends Task> tasks;
- /**
- * Stop maven build if error occurs.
- */
- @Parameter(defaultValue = "true")
- protected boolean stopOnError;
- /**
- * If set to true all Node.js plugin operations are skipped.
- */
- @Parameter(property = "nodejs.skip")
- protected boolean skip;
- @Parameter(defaultValue = "${project}", readonly = true)
- private MavenProject project;
- @Parameter(defaultValue = "${session}", readonly = true)
- private MavenSession session;
- @Component
- private ArtifactHandlerManager artifactHandlerManager;
- @Component
- private ArtifactResolver resolver;
- private static final ComparableVersion NODEJS_MIN_VERSION = new ComparableVersion("6.3.0");
- /**
- * Installs node js if necessary and performs defined tasks
- * @throws MojoExecutionException Mojo execution exception
- */
- public void run() throws MojoExecutionException {
- if (skip) {
- return;
- }
- if (tasks == null || tasks.isEmpty()) {
- getLog().warn("No Node.js tasks have been defined. Nothing to do.");
- }
- // validate nodejs version
- ComparableVersion nodeJsVersionComparable = new ComparableVersion(cleanupVersion(nodeJsVersion));
- if (nodeJsVersionComparable.compareTo(NODEJS_MIN_VERSION) < 0) {
- throw new MojoExecutionException("This plugin supports Node.js " + NODEJS_MIN_VERSION + " and up.");
- }
- NodeInstallationInformation information = getOrInstallNodeJS();
- if (tasks != null) {
- for (Task task : tasks) {
- task.setLog(getLog());
- task.execute(information);
- }
- }
- }
- private NodeInstallationInformation getOrInstallNodeJS() throws MojoExecutionException {
- NodeInstallationInformation information = NodeInstallationInformation.forVersion(cleanupVersion(nodeJsVersion), npmVersion, nodeJsDirectory);
- try {
- if (!information.getNodeExecutable().exists() || !information.getNpmExecutableBundledWithNodeJs().exists()) {
- getLog().info("Install Node.js to " + information.getNodeJsInstallPath());
- if (!cleanNodeJsInstallPath(information)) {
- throw new MojoExecutionException("Could not delete node js directory: " + information.getNodeJsInstallPath());
- }
- File nodeJsBinary = resolveArtifact(information.getNodeJsDependency());
- FileUtils.copyFile(nodeJsBinary, information.getArchive());
- Task installationTask = new NodeUnarchiveTask(nodeJsDirectory.getAbsolutePath());
- installationTask.setLog(getLog());
- installationTask.execute(information);
- }
- if (StringUtils.isNotEmpty(npmVersion) && !information.getNpmExecutable().exists()) {
- updateNPMExecutable(information);
- }
- }
- catch (java.net.MalformedURLException ex) {
- throw new MojoExecutionException("Malformed provided node URL", ex);
- }
- catch (IOException ex) {
- getLog().error("Failed to get nodeJs from " + information.getNodeJsDependency(), ex);
- throw new MojoExecutionException("Failed to downloading nodeJs from " + information.getNodeJsDependency(), ex);
- }
- catch (MojoExecutionException ex) {
- getLog().error("Execution Exception", ex);
- if (stopOnError) {
- throw new MojoExecutionException("Execution Exception", ex);
- }
- }
- return information;
- }
- private boolean cleanNodeJsInstallPath(NodeInstallationInformation information) {
- File directory = new File(information.getNodeJsInstallPath());
- if (directory.exists()) {
- try {
- FileUtils.deleteDirectory(directory);
- }
- catch (IOException ex) {
- getLog().error(ex);
- return false;
- }
- }
- if (information.getArchive().exists()) {
- if (!information.getArchive().delete()) {
- return false;
- }
- }
- return true;
- }
- /**
- * Makes sure the specified npm version is installed in the base directory, regardless in which environment.
- * @param information Information
- */
- private void updateNPMExecutable(NodeInstallationInformation information) throws MojoExecutionException {
- getLog().info("Installing specified npm version " + npmVersion);
- NpmInstallTask npmInstallTask = new NpmInstallTask();
- npmInstallTask.setLog(getLog());
- npmInstallTask.setNpmBundledWithNodeJs(true);
- npmInstallTask.setArguments(new String[] {
- "--prefix", information.getNpmPrefixPath(), "--global", "npm@" + npmVersion
- });
- npmInstallTask.execute(information);
- }
- @SuppressWarnings("deprecation")
- private File resolveArtifact(Dependency dependency) throws MojoExecutionException {
- Artifact artifact = new DefaultArtifact(dependency.getGroupId(),
- dependency.getArtifactId(),
- VersionRange.createFromVersion(dependency.getVersion()),
- Artifact.SCOPE_PROVIDED,
- dependency.getType(),
- dependency.getClassifier(),
- artifactHandlerManager.getArtifactHandler(dependency.getType()));
- try {
- resolver.resolve(artifact, project.getRemoteArtifactRepositories(), session.getLocalRepository());
- }
- catch (ArtifactResolutionException ex) {
- throw new MojoExecutionException("Unable to get artifact for " + dependency, ex);
- }
- catch (ArtifactNotFoundException ex) {
- throw new MojoExecutionException("Unable to get artifact for " + dependency, ex);
- }
- return artifact.getFile();
- }
- /**
- * Removes "v" prefix from version, if present.
- * @param version Version number
- * @return Version number
- */
- private static String cleanupVersion(String version) {
- return StringUtils.removeStart(version, "v");
- }
- }