org.tahomarobotics.maven.plugin.SimulationMojo Maven / Gradle / Ivy
/**
* Copyright 2018 Tahoma Robotics - http://tahomarobotics.org - Bear Metal 2046 FRC Team
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without
* limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*/
package org.tahomarobotics.maven.plugin;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.apache.commons.io.IOUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import org.apache.maven.repository.RepositorySystem;
/**
* This plugin goal simply determines the arguments for running the simulation. The simulation
* runs as a java agent since it will modify the loaded class prior to running the Robot.
*
*/
@Mojo(name = "exec-simulation", requiresDependencyResolution=ResolutionScope.COMPILE_PLUS_RUNTIME)
public class SimulationMojo extends AbstractMojo {
@Component
private MavenProject project;
@Component
private MavenSession session;
@Component
private RepositorySystem repo;
// java executable path used for running simulation
@Parameter(defaultValue = "${java.home}\\bin\\java.exe" )
private String jrePath;
// simulation artifact used for initiating the java-agent
@Parameter(defaultValue = "bear-simulation")
private String simulationArtifactId;
// simulation class main
@Parameter(defaultValue = "org.tahomarobotics.sim.lib.Simulation")
private String javaMainClass;
@Parameter(defaultValue = "windowsx86-64")
private String nativeClassifier;
@Parameter(defaultValue = "target/natives")
private String nativeUnpackTarget;
@Parameter(defaultValue = "target/natives/windows/x86-64")
private String libraryPath;
@Parameter
private String debugString;
@Parameter(required=true)
private List models;
private final Set allArtifacts = new LinkedHashSet<>();
private String getSimulationJarPath() {
for (Artifact dependency : allArtifacts) {
if (dependency.getArtifactId().equals(simulationArtifactId)) {
return dependency.getFile().getAbsolutePath();
}
}
return "not found";
}
/**
* Execute robot with simulation
*/
public void execute() throws MojoExecutionException, MojoFailureException {
// generate class path for all dependencies
String javaClasspath = getDependencyPath();
// get the path to the simulation jar path used for the java agent argument
// be sure to quote the path as there might be spaces in path
String javaVMArgs = "-javaagent:\"" + getSimulationJarPath() + "\"";
// create execution command line
StringBuffer sb = new StringBuffer();
sb.append(jrePath).append(" ");
sb.append(javaVMArgs).append(" ");
if (debugString != null) {
sb.append(debugString).append(" ");
}
// be sure to quote the path as there might be spaces in path
sb.append("-Djava.library.path=\"").append(libraryPath).append("\" ");
// add simulation models to command line from plugin configuration
sb.append("-Dsimulation.models=");
for(String model : models) {
sb.append(model).append(':');
}
// be sure to quote the path as there might be spaces in path
sb.append(" -classpath \"").append(javaClasspath).append("\" ");
sb.append(' ').append(javaMainClass);
String cmd = sb.toString();
// log out the command line
getLog().info(cmd);
ProcessBuilder builder = new ProcessBuilder().inheritIO();
builder.command(cmd.split(" "));
try {
Process process = builder.start();
int exitCode = process.waitFor();
if (exitCode != 0) {
throw new MojoExecutionException("Failed to start simulated robot with a exit code: " + exitCode);
}
} catch (IOException | InterruptedException e) {
throw new MojoExecutionException("Failed to start simulated robot", e);
}
}
/**
* Create class-path. This will unpack native archive.
*
* @return class-path
* @throws MojoExecutionException
*/
private String getDependencyPath() throws MojoExecutionException {
StringBuffer sb = new StringBuffer();
boolean first = true;
allArtifacts.add(project.getArtifact());
allArtifacts.addAll(project.getArtifacts());
for (Artifact dependency : allArtifacts) {
String classifier = dependency.getClassifier();
File file = dependency.getFile();
if (classifier == null) {
if (!first) {
sb.append(";");
}
first = false;
sb.append(dependency.getFile().getAbsolutePath());
} else if (classifier.equals(nativeClassifier)) {
try {
unpackNatives(file);
} catch (IOException e) {
throw new MojoExecutionException("UnpackNatives", e);
}
}
}
return sb.toString();
}
// unpack any native libraries into a unpack area
private void unpackNatives(File jarPath) throws IOException {
try (JarFile jar = new JarFile(jarPath)) {
Enumeration entries = jar.entries();
while (entries.hasMoreElements()) {
JarEntry file = entries.nextElement();
File f = new File(nativeUnpackTarget, file.getName());
getLog().info("Copying native - " + file.getName());
f.getParentFile().mkdirs();
if (file.isDirectory()) { // if its a directory, create it
f.mkdir();
continue;
}
try (InputStream is = jar.getInputStream(file); FileOutputStream fos = new FileOutputStream(f)) {
IOUtils.copy(is, fos);
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy