All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.scalaxb.maven.ScalaxbMojo Maven / Gradle / Ivy

There is a newer version: 1.12.1
Show newest version
package org.scalaxb.maven;

/*
 * Copyright (c) 2011-2012 Martin Ellis
 *
 * 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.
 */

import static java.util.Collections.emptyList;
import static java.util.Collections.sort;
import static org.apache.maven.plugins.annotations.LifecyclePhase.GENERATE_SOURCES;
import static scala.collection.JavaConversions.asScalaBuffer;
import static scala.collection.JavaConversions.seqAsJavaList;
import static scalaxb.compiler.Module$.MODULE$;

import java.io.File;
import java.text.ChoiceFormat;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
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.project.MavenProject;
import org.codehaus.plexus.util.Scanner;
import org.sonatype.plexus.build.incremental.BuildContext;

import scala.Option;
import scalaxb.compiler.Arguments;
import scalaxb.compiler.CaseClassTooLong;
import scalaxb.compiler.Module;
import scalaxb.compiler.ReferenceNotFound;

/**
 * Generates Scala code from XSD and WSDL.
 */
@Mojo(name = "generate", defaultPhase = GENERATE_SOURCES)
public class ScalaxbMojo extends AbstractScalaxbMojo {

    @Parameter(property = "project", required = true, readonly = true)
    private MavenProject project;

    @Component
    private BuildContext context;

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        getOutputDirectory().mkdirs();
        String outputPath = getOutputDirectory().getAbsolutePath();
        getLog().debug("Adding source root: " + outputPath);
        project.addCompileSourceRoot(outputPath);

        List inputFiles = inputFiles();
        if (!inputFiles.isEmpty() && buildRequired(inputFiles)) {
            generateBindings(inputFiles);
        }
    }

    public List inputFiles() {
        List schemaFiles = inputFiles(getXsdDirectory(), "xsd");
        List wsdlFiles = inputFiles(getWsdlDirectory(), "wsdl");
        if (schemaFiles.isEmpty() && wsdlFiles.isEmpty()) {
            if (!context.isIncremental()) {
                getLog().warn("No XSD or WSDL files found: not running scalaxb");
            }
            return emptyList();
        }

        List inputFiles = new ArrayList();
        inputFiles.addAll(wsdlFiles);
        inputFiles.addAll(schemaFiles);
        return inputFiles;
    }

    /**
     * Returns true if scalaxb should be run. This method returns true for CLI
     * builds, or full builds in the IDE. It also returns true for IDE builds
     * where any of the input files are outside the project directory.
     * This method returns false if this is an incremental build, and none of
     * the input files have changed.
     * 

* @param inputFiles The XSD and WSDL files. * @return True if a build is required, and false otherwise. */ public boolean buildRequired(List inputFiles) { if (!context.isIncremental()) { return true; } String basedir = project.getBasedir().toString() + File.separatorChar; boolean changes = false; for (String file : inputFiles) { if (file.startsWith(basedir)) { String relPath = file.substring(basedir.length()); if (context.hasDelta(relPath)) { changes = true; break; } } } return changes; } /** * Build up ('command line') arguments for scalaxb, and invoke the scalaxb * compiler. * @param schemaFiles The WSDL and XSD input files. */ private void generateBindings(List schemaFiles) throws MojoExecutionException, MojoFailureException { List arguments = new ArrayList(); arguments.addAll(arguments()); arguments.addAll(schemaFiles); Option option = Arguments.apply(asScalaBuffer(arguments)); String args = argumentsToString(arguments); if (!option.isDefined()) { throw new MojoExecutionException("Error parsing arguments " + args); } if (getLog().isDebugEnabled()) { getLog().debug("Running: scalaxb " + args); } invokeCompiler(option.get()); } /** * Runs scalaxb using the specified arguments, wrapping any exceptions * thrown with appropriate Maven exceptions. */ private void invokeCompiler(Arguments args) throws MojoExecutionException, MojoFailureException { try { List generated = generateSources(args); if (getLog().isInfoEnabled()) { getLog().info(generatedFilesMessage(generated)); } context.refresh(getOutputDirectory()); } catch (ReferenceNotFound ex) { throw new MojoFailureException(ex.getMessage(), ex); } catch (CaseClassTooLong ex) { throw new MojoFailureException(ex.getMessage(), ex); } catch (Exception ex) { throw new MojoExecutionException("Error running scalaxb", ex); } } /** * Returns a message indicating the number of files generated, for logging. */ private String generatedFilesMessage(List generated) { double[] limits = {0, 1, 2}; String[] files = {"No files", "1 file", "{0,number} files"}; ChoiceFormat choice = new ChoiceFormat(limits, files); MessageFormat format = new MessageFormat("{0} generated."); format.setFormatByArgumentIndex(0, choice); return format.format(new Object[]{generated.size()}); } /** * Runs scalaxb using the specified arguments. */ private List generateSources(Arguments args) { File file = args.files().head(); boolean verbose = args.verbose(); Module module = MODULE$.moduleByFileName(file); configureLogging(verbose); List generated = seqAsJavaList( module.processFiles(args.files(), args.config())); return generated; } /** * Reconfigures logging so that logging goes through Maven Log. * @param verbose True if verbose logging is required. */ private void configureLogging(boolean verbose) { LogAppender appender = new LogAppender(getLog()); Logger rootLogger = Logger.getRootLogger(); rootLogger.removeAllAppenders(); rootLogger.addAppender(appender); if (!verbose) { rootLogger.setLevel(Level.WARN); } } /** * Formats arguments into a form that can be copied and pasted into the command line. */ static String argumentsToString(List arguments) { Pattern safe = Pattern.compile("[\\p{Alnum}:/=\\.-]*"); StringBuilder str = new StringBuilder(); for (String arg : arguments) { if (safe.matcher(arg).matches()) { str.append(arg); } else { String escapedArg = arg.replaceAll("'", "'\\\\''"); str.append('\'').append(escapedArg).append('\''); } str.append(' '); } str.deleteCharAt(str.length() - 1); return str.toString(); } /** * Returns the path of all files in a directory (or its subdirectories) with * a given extension. The returned File objects are prefixed with the given * directory. *

* @param directory The directory in which to search. * @param type The required file extension. * @return A list of all files contained in the directory with the specified * extension. */ List inputFiles(File directory, String type) { if (!directory.exists()) { return emptyList(); } Scanner ds = context.newScanner(directory, true); String[] includes = {"**\\*." + type}; ds.setIncludes(includes); ds.scan(); List result = new ArrayList(); for (String file : ds.getIncludedFiles()) { result.add(new File(directory, file).getPath()); } sort(result); return result; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy