org.wisdom.maven.mojos.RunMojo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of wisdom-maven-plugin Show documentation
Show all versions of wisdom-maven-plugin Show documentation
The Maven Wisdom Plugin allows building applications for Wisdom.
The newest version!
/*
* #%L
* Wisdom-Framework
* %%
* Copyright (C) 2013 - 2014 Wisdom Framework
* %%
* 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 org.wisdom.maven.mojos;
import com.google.common.collect.ImmutableList;
import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.execution.DefaultMavenExecutionRequest;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.execution.ProjectDependencyGraph;
import org.apache.maven.lifecycle.LifecycleExecutor;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.*;
import org.apache.maven.project.*;
import org.codehaus.plexus.PlexusConstants;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.context.Context;
import org.codehaus.plexus.context.ContextException;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
import java.io.File;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Mojo running a 'watched' instance of Wisdom. It deploys the applications and monitor for changes. On each change,
* the Maven 'watch' pipeline is triggered to re-deploy the bundle, or update configurations and files.
*/
@Mojo(name = "run", threadSafe = false,
// We need to use the TEST scope to let Surefire access its dependencies.
requiresDependencyResolution = ResolutionScope.TEST,
requiresProject = true
)
@Execute(phase = LifecyclePhase.PACKAGE)
public class RunMojo extends AbstractWisdomMojo implements Contextualizable {
/**
* Enables / disables the pom file monitoring.
*/
@Parameter(defaultValue = "${pom.watching}")
protected boolean pomFileMonitoring = true;
/**
* The last modification date of the project's pom.xml file. This field is required on Windows as the exit code
* and not propagated correctly.
*/
private long lastPomFileModification;
/**
* Component used to build the Maven project from the pom file.
*/
@Component
private ProjectBuilder projectBuilder;
/**
* The component used to execute the second Maven execution.
*/
@Component
private LifecycleExecutor lifecycleExecutor;
/**
* The plexus container.
*/
private PlexusContainer container;
/**
* Sets to false to indicate that we are executing a nested 'build'.
*/
private boolean initialBuild = true;
@Override
public void execute() throws MojoExecutionException {
File pom = project.getFile();
lastPomFileModification = pom.lastModified();
MavenProject newProject = null;
try {
final ProjectBuildingResult result = loadMavenProject();
newProject = result.getProject();
} catch (ProjectBuildingException exception) {
getLog().error("Error(s) detected in the pom file: " + exception.getMessage());
if (initialBuild) {
throw new MojoExecutionException("Invalid pom file, check log", exception);
}
if (pomFileMonitoring) {
waitForModification();
execute();
}
}
// newProject is necessarily set here and valid.
MavenExecutionRequest execRequest = getMavenExecutionRequest();
MavenSession newSession = getMavenSession(newProject, execRequest); //NOSONAR
// The session is going to be cleared, write the watcher list in the container.
// container.getContext().put(Watchers.WATCHERS_KEY, Watchers.all(session));
initialBuild = false;
try {
lifecycleExecutor.execute(newSession);
} catch (RuntimeException e) {
// Maven may throw internal error, they are fatal, stop everything.
getLog().info("Maven has thrown a fatal error, stopping the watch mode: " + e.getMessage());
return;
}
if (newSession.getResult().hasExceptions()) {
getLog().error("Exception(s) detected while launching Maven : " + newSession.getResult().getExceptions());
if (initialBuild) {
throw new MojoExecutionException("Exception(s) detected while launching Maven, check log",
newSession.getResult().getExceptions().get(0));
}
if (pomFileMonitoring) {
waitForModification();
execute();
}
return;
}
if (pomFileMonitoring && pomFileModified()) {
execute();
}
}
/**
* Waits for pom file modification. This method is used when a pom file has problems,
* to reload the project when they are fixed.
*/
private void waitForModification() {
while( ! pomFileModified()) {
try {
Thread.sleep(Integer.getInteger("watch.period", 2) * 1000);
} catch (InterruptedException e) {
// Ignore it.
}
}
}
private MavenSession getMavenSession(final MavenProject project, MavenExecutionRequest request) {
MavenSession newSession = new MavenSession(container,
session.getRepositorySession(),
request,
session.getResult());
newSession.setAllProjects(session.getAllProjects());
newSession.setCurrentProject(project);
newSession.setParallel(session.isParallel());
// Update project map to update the current project
Map projectMaps = new LinkedHashMap<>(session.getProjectMap());
projectMaps.put(ArtifactUtils.key(project.getGroupId(), project.getArtifactId(),
project.getVersion()), project);
newSession.setProjectMap(projectMaps);
/**
* Fake implementation of the project dependency graph, as we don't support reactor.
*/
ProjectDependencyGraph graph = new ProjectDependencyGraph() {
@Override
public List getSortedProjects() {
return ImmutableList.of(project);
}
@Override
public List getDownstreamProjects(MavenProject project, boolean transitive) {
return Collections.emptyList();
}
@Override
public List getUpstreamProjects(MavenProject project, boolean transitive) {
return Collections.emptyList();
}
};
newSession.setProjectDependencyGraph(graph);
newSession.setProjects(ImmutableList.of(project));
return newSession;
}
private MavenExecutionRequest getMavenExecutionRequest() {
MavenExecutionRequest request = DefaultMavenExecutionRequest.copy(session.getRequest());
request.setStartTime(session.getStartTime());
request.setExecutionListener(null);
if (! initialBuild && session.getGoals().contains("clean")) {
// Here the package phase is required to restore the runtime environment
request.setGoals(ImmutableList.of("clean", "package", "wisdom:internal-run"));
} else {
// It is safer to re-execute the package phase to have the new classes...
request.setGoals(ImmutableList.of("package", "wisdom:internal-run"));
}
return request;
}
private ProjectBuildingResult loadMavenProject() throws ProjectBuildingException {
DefaultProjectBuildingRequest request = new DefaultProjectBuildingRequest();
request.setRepositorySession(repoSession);
request.setUserProperties(session.getUserProperties());
request.setSystemProperties(session.getSystemProperties());
request.setProfiles(session.getRequest().getProfiles());
request.setActiveProfileIds(session.getRequest().getActiveProfiles());
request.setRemoteRepositories(session.getRequest().getRemoteRepositories());
request.setBuildStartTime(session.getRequest().getStartTime());
request.setInactiveProfileIds(session.getRequest().getInactiveProfiles());
request.setPluginArtifactRepositories(session.getRequest().getPluginArtifactRepositories());
request.setLocalRepository(session.getRequest().getLocalRepository());
return projectBuilder.build(project.getFile(), request);
}
/**
* On windows we can't play with the exit code, so check for the pom file modification dates.
*
* @return {@code true} if the pom file was modified. {@code false} otherwise.
*/
private boolean pomFileModified() {
File pom = project.getFile();
return pom.lastModified() > lastPomFileModification;
}
/**
* Retrieves the Plexus container.
* @param context the context
* @throws ContextException if the container cannot be retrieved.
*/
@Override
public void contextualize(Context context) throws ContextException {
container = (PlexusContainer) context.get(PlexusConstants.PLEXUS_KEY);
}
}