/* * 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. * * Contributions from 2013-2017 where performed either by US government * employees, or under US Veterans Health Administration contracts. * * US Veterans Health Administration contributions by government employees * are work of the U.S. Government and are not subject to copyright * protection in the United States. Portions contributed by government * employees are USGovWork (17USC ยง105). Not subject to copyright. * * Contribution by contractors to the US Veterans Health Administration * during this period are contractually contributed under the * Apache License, Version 2.0. * * See: https://www.usa.gov/government-works * * Contributions prior to 2013: * * Copyright (C) International Health Terminology Standards Development Organisation. * Licensed under the Apache License, Version 2.0. * */ package sh.isaac.mojo.external; //~--- JDK imports ------------------------------------------------------------ import java.io.File; import java.lang.reflect.Field; import java.util.Iterator; import java.util.Map; //~--- non-JDK imports -------------------------------------------------------- import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import sh.isaac.api.LookupService; import sh.isaac.api.util.FortifyFun; //~--- classes ---------------------------------------------------------------- /** * Goal which executes mojo-like things that can't be run as mojos directly, due to class loading issues in maven. * * Basically, the short of it, is that a DB lifecycle can't span multiple plugins in maven. because of classloader * isolation among the plugins. This class allows us to run any code, even code not in this plugin module - so * long as it extends the {@link QuasiMojo} class. * * @see QuasiMojo */ @Mojo( defaultPhase = LifecyclePhase.PROCESS_RESOURCES, name = "quasi-mojo-executor" ) public class ExternalCodeExecutor extends AbstractMojo { /** The skip execution. */ @Parameter( required = false, defaultValue = "false" ) protected boolean skipExecution = false;; /** The project version. */ @Parameter( required = true, defaultValue = "${project.version}" ) protected String projectVersion; /** The output directory. */ @Parameter( required = true, defaultValue = "${project.build.directory}" ) protected File outputDirectory; /** The quasi mojo name. */ @Parameter(required = true) protected String quasiMojoName; /** The parameters. */ @Parameter(required = false) protected Map<String, String> parameters; //~--- methods ------------------------------------------------------------- /** * Execute. * * @throws MojoExecutionException the mojo execution exception * @see org.apache.maven.plugin.Mojo#execute() */ @Override public void execute() throws MojoExecutionException { try { if (this.skipExecution) { getLog().info("Skipping execution of " + this.quasiMojoName); return; } else { getLog().info("Executing " + this.quasiMojoName); } final long start = System.currentTimeMillis(); final QuasiMojo quasiMojo = LookupService.getService(QuasiMojo.class, this.quasiMojoName); if (quasiMojo == null) { throw new MojoExecutionException("Could not locate a QuasiMojo implementation with the name '" + this.quasiMojoName + "'."); } quasiMojo.outputDirectory = this.outputDirectory; quasiMojo.projectVersion = this.projectVersion; quasiMojo.log = getLog(); if ((this.parameters != null) && (this.parameters.size() > 0)) { final Class<?> myClass = quasiMojo.getClass(); final Iterator<String> params = this.parameters.keySet() .iterator(); while (params.hasNext()) { final String name = params.next(); final String value = this.parameters.get(name); params.remove(); Field myField = null; try { myField = myClass.getDeclaredField(name); } catch (final NoSuchFieldException e) { // recurse up the parent classes, looking for the field Class<?> parent = myClass; while ((myField == null) && (parent.getSuperclass() != null)) { parent = parent.getSuperclass(); try { myField = parent.getDeclaredField(name); } catch (final NoSuchFieldException e1) { // ignore } } } if (myField == null) { throw new MojoExecutionException("No field in " + quasiMojo + " to place the parameter " + name + " : " + value); } FortifyFun.fixAccessible(myField); // myField.setAccessible(true); if (myField.getType() .equals(String.class)) { myField.set(quasiMojo, value); } else if (myField.getType() .equals(File.class)) { myField.set(quasiMojo, new File(value)); } else if (myField.getType() .equals(Integer.class)) { myField.set(quasiMojo, Integer.parseInt(value)); } else if (myField.getType() .equals(Long.class)) { myField.set(quasiMojo, Long.parseLong(value)); } else if (myField.getType() .equals(Boolean.class)) { myField.set(quasiMojo, Boolean.parseBoolean(value)); } else { throw new MojoExecutionException("Can't handle field datatype " + myField.getType()); } } if (this.parameters.size() > 0) { for (final String s: this.parameters.keySet()) { getLog().warn("Mojo specified a parameter '" + s + "' that couldn't be placed into the execution class!"); } } } quasiMojo.execute(); getLog().info(this.quasiMojoName + " execution completed in " + (System.currentTimeMillis() - start) + "ms"); } catch (final Exception e) { throw new MojoExecutionException("QuasiMojo Execution Failure", e); } } }