/******************************************************************************* * Copyright (c) 2006-2010 eBay Inc. All Rights Reserved. * 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 *******************************************************************************/ package org.ebayopensource.turmeric.plugins.maven; import java.io.File; import java.net.MalformedURLException; import java.util.List; import org.apache.maven.artifact.Artifact; import org.apache.maven.model.Resource; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.ebayopensource.turmeric.plugins.maven.resources.ResourceLocator.Location; import org.ebayopensource.turmeric.plugins.maven.utils.CodegenCommands; import org.ebayopensource.turmeric.plugins.maven.utils.LegacyProperties; import org.ebayopensource.turmeric.tools.codegen.NonInteractiveCodeGen; import org.ebayopensource.turmeric.tools.codegen.ServiceGeneratorFacade; /** * Abstract Mojo for the ServiceGeneratorFacade from codegen-tools to generate the various project level sources. */ public abstract class AbstractTurmericCodegenMojo extends AbstractTurmericMojo { /** * Location of generated java code * * @parameter expression="${codegen.output.directory}" * default-value="${project.build.directory}/generated-sources/codegen" * @required */ protected File outputDirectory = new File("${project.build.directory}/generated-sources/codegen"); /** * Location of generated resources (not java code) * * @parameter expression="${codegen.resources.output.directory}" * default-value="${project.build.directory}/generated-resources/codegen" * @required */ protected File resourcesOutputDirectory = new File("${project.build.directory}/generated-resources/codegen"); /** * Optional raw command line arguments that can be passed to the Service Code Generation tooling found in codegen-tools. * * @parameter * @optional */ protected String[] args; /** * Optional flag to ignore any sort of CodeGen error. * * @parameter expression="${codegen.ignore.error}" default-value="false" */ private boolean ignoreCodeGenError = false; /** * Optional flag to indicate if the mojo should operate in legacy mode * or not, usually this is an indicator of the specific kind of codegen * to utilize information found in various project stored files, such * as service_intf_project.properties, service_metadata.properties, * service WSDL, service_impl_project.properties, ServiceConfig.xml * and ClientConfig.xml, to name a few. * * @parameter expression="${codegen.legacy}" default-value="false" * * @see TURMERIC-155 */ private boolean legacy = false; @Override public boolean executeSkip() throws MojoExecutionException, MojoFailureException { if(isMojoRunningInEclipse() && isTurmericEclipsePluginEnabled() && isLegacyMode()) { getLog().warn("No need to generate. " + "Running in legacy mode in eclipse with turmeric eclipse plugin enabled."); return true; // SKIP EXECUTION } return false; } /** * Tests on various aspects to know if generation is needed. * * @return true if need to generate, false otherwise. * @throws MojoExecutionException */ @Override public boolean needsGeneration() throws MojoExecutionException { if (this.project == null) { throw new MojoExecutionException("Cannot execute with null project"); } // Both interface and impl use an output directory if (outputDirectory.exists() == false) { getLog().info( "Must Generate: No output directory present: " + outputDirectory); return true; } // Both interface and impl use a resources output directory if (resourcesOutputDirectory.exists() == false) { getLog().info( "Must Generate: No resources output directory present: " + resourcesOutputDirectory); return true; } return false; } @Override protected void onValidateParameters() throws MojoExecutionException, MojoFailureException { super.onValidateParameters(); outputDirectory = expandFile(outputDirectory); resourcesOutputDirectory = expandFile(resourcesOutputDirectory); } public String[] getArgs() { return args; } /** * Get the Gen Type as defined by the specific service gen process. * * @return the Generate Type */ public abstract String getGenType(); public File getOutputDirectory() { return outputDirectory; } public File getResourcesOutputDirectory() { return resourcesOutputDirectory; } public boolean isLegacyMode() { return legacy; } public boolean isStandardsMode() { return !legacy; } @Override protected void onRunSetup() throws MojoExecutionException, MojoFailureException { super.onRunSetup(); ensureDirectoryExists("Output Directory", outputDirectory); ensureDirectoryExists("Resources Output Directory", resourcesOutputDirectory); if (isLegacyMode()) { getLog().warn("Operating in LEGACY Mode"); } } /** * Primary execution point of the plugin */ @Override public final void onRun() throws MojoExecutionException, MojoFailureException { super.onRun(); CodegenCommands commands = new CodegenCommands(); commands.setLog(getLog()); // Add Standard CodeGen arguments. @SuppressWarnings("unchecked") List<Resource> resources = project.getBuild().getResources(); commands.addGenType(getGenType()); commands.addSourceDir(project.getBuild().getSourceDirectory()); if ((resources != null) && (resources.size() >= 1)) { commands.addResourceDir(resources.get(0).getDirectory()); } commands.addGeneratedJavaOutputDir(outputDirectory); commands.addGeneratedResourcesOutputDir(resourcesOutputDirectory); commands.addClassesOutputDir(project.getBuild().getOutputDirectory()); // Add the optional args from the mojo parameters commands.addFreeformArgs(args); // Add mojo specific args addCodegenCommands(commands); // Run the codegen runCodegen(commands); } private void runCodegen(CodegenCommands commands) throws MojoExecutionException { NonInteractiveCodeGen codegen = new NonInteractiveCodeGen(); // Collect all of the project compile artifacts to add to a // URL ClassLoader later @SuppressWarnings("unchecked") List<Artifact> arts = project.getCompileArtifacts(); if (arts != null) { for (Artifact arti : arts) { try { codegen.addExtraClassPath(arti.getFile()); } catch (MalformedURLException e) { throw new MojoExecutionException("Unable to get URL for: " + arti.getId()); } } } File classesDir = new File(project.getBuild().getOutputDirectory()); // Some JVM's will not add the directory to the classpath if it doesn't exist. // Make sure that the project.build.outputDirectory exists prior to wrapping // the Codegen with an active, valid, classloader. ensureDirectoryExists("project.build.outputDirectory", classesDir); try { codegen.addExtraClassPath(classesDir); } catch (MalformedURLException e1) { throw new MojoExecutionException("Unable to get URL for: " + classesDir); } try { codegen.execute(commands.getCommandArray()); } catch (Exception e) { String err = "Exception executing service generator facade"; if (ignoreCodeGenError) { getLog().error(err, e); } else { throw new MojoExecutionException(err, e); } } } /** * Add more Codegen Commands. * * @param commands * the CodegenCommands to set to, which will eventually be used to execute the * {@link ServiceGeneratorFacade} * @throws MojoExecutionException * when wrapping other exceptions. Will cause build to go into error, resulting in a "BUILD ERROR" * message. The build will stop. * @throws MojoFailureException * to throw new exceptions. Will cause build to go into error, resulting in a "BUILD FAILURE" message. * The build will stop. */ protected abstract void addCodegenCommands(CodegenCommands commands) throws MojoExecutionException, MojoFailureException; /** * Attach {@link #outputDirectory} (and {@link #resourcesOutputDirectory} * if being used) to the project. */ @Override protected void onAttachGeneratedDirectories() { // Attach the generated source directory to the maven project project.addCompileSourceRoot(outputDirectory.getAbsolutePath()); // Attach the generated resources directory to the maven project if ((resourcesOutputDirectory != null) && (resourcesOutputDirectory.exists())) { Resource resource = new Resource(); resource.setDirectory(resourcesOutputDirectory.getAbsolutePath()); resource.addInclude("**/*"); project.addResource(resource); } } /** * Create a {@link LegacyProperties} object representing the legacy properties from the project and the named file. * * @param pathref * the reference to the file required. Can include expressions. * @return the properties that were loaded. * @throws MojoFailureException * if unable to find the required legacy properties file. * @throws MojoExecutionException * if unable to expand pathref */ protected LegacyProperties getLegacyProperties(String pathref) throws MojoExecutionException, MojoFailureException { File file = new File(expandParameter(pathref)); return new LegacyProperties(getLog(), getProject(), file); } /** * Create a {@link LegacyProperties} object representing the legacy properties from the project and location. * * @param location * the location to the file required. * @return the properties that were loaded. * @throws MojoFailureException * if unable to find the required legacy properties file. */ protected LegacyProperties getLegacyProperties(Location location) throws MojoFailureException { if(location == null) { throw new NullPointerException("Null location"); } return new LegacyProperties(getLog(), getProject(), location.getFile()); } }