com.theoryinpractise.coffeescript.CoffeeScriptCompilerMojo.java Source code

Java tutorial

Introduction

Here is the source code for com.theoryinpractise.coffeescript.CoffeeScriptCompilerMojo.java

Source

package com.theoryinpractise.coffeescript;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.io.Files;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;

import javax.annotation.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.List;

/**
 * Copyright 2011 Mark Derricutt.
 * <p/>
 * Contributing authors:
 * Daniel Bower
 * <p/>
 * 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
 * <p/>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p/>
 * 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.
 * <p/>
 * <p/>
 * Compile CoffeeScript with Maven
 *
 * @goal coffee
 * @phase compile
 */
public class CoffeeScriptCompilerMojo extends AbstractMojo {

    /**
     * Default location of .coffee source files.
     *
     * @parameter expression="${basedir}/src/main/coffee"
     * @required
     */
    private File coffeeDir;

    /**
     * Location of the output files from the Coffee Compiler.  Defaults to ${build.directory}/coffee
     *
     * @parameter expression="${project.build.directory}/coffee"
     * @required
     */
    private File coffeeOutputDirectory;

    /**
     * Should we compile as bare?  A compiler option for the Coffee Compiler.
     *
     * @parameter default-value="false"
     */
    private Boolean bare;

    /**
     * Should we generate source maps when compiling?
     *
     * @parameter default-value="false"
     */
    private Boolean map;

    /**
     * Should we generate source maps when compiling?
     *
     * @parameter default-value="true"
     */
    private Boolean header;

    /**
     * What version of Coffee-Script should we compile with?
     *
     * @parameter default-value="1.6.1"
     */
    private String version;

    /**
     * Should the files be compiled individually or as a whole.
     * <p/>
     * This can help when trying to diagnose a compilation error
     *
     * @parameter default-value="false"
     */
    private Boolean compileIndividualFiles;

    /**
     * JoinSet definitions to join groups of coffee files into a single .js file
     * Individual Joinsets contain an id element to name the file that will be output and a maven
     * FileSet to define what files are included.
     *
     * @parameter
     */
    private List<JoinSet> coffeeJoinSets;

    @VisibleForTesting
    List<String> acceptableVersions = ImmutableList.of("1.2.0", "1.3.1", "1.3.3", "1.4.0", "1.5.0", "1.6.1");

    public void execute() throws MojoExecutionException {

        if (compileIndividualFiles && map) {
            throw new MojoExecutionException("Unable to generate source maps when compiling joinsets individually");
        }

        if (map && !version.equals("1.6.1")) {
            throw new MojoExecutionException("CoffeeScript 1.6.1 is required for using source maps");
        }

        if (!acceptableVersions.contains(version)) {

            String error = String.format(
                    "Unsupported version of coffee-script specified (%s) - supported versions: %s", version,
                    Joiner.on(", ").join(acceptableVersions));

            throw new MojoExecutionException(error);
        }

        getLog().info(String.format("coffee-maven-plugin using coffee script version %s", version));
        CoffeeScriptCompiler coffeeScriptCompiler = new CoffeeScriptCompiler(version);

        try {
            if (compileIndividualFiles) {
                getLog().info("Starting individual compilations of files");

                for (JoinSet joinSet : findJoinSets()) {
                    StringBuilder compiled = new StringBuilder();
                    for (File file : joinSet.getFiles()) {
                        getLog().info("Compiling File " + file.getName() + " in JoinSet:" + joinSet.getId());
                        compiled.append(
                                coffeeScriptCompiler
                                        .compile(Files.toString(file, Charsets.UTF_8), file.getName(), bare,
                                                getSourceMapType(), header, file.getName().endsWith(".litcoffee"))
                                        .getJs())
                                .append("\n");
                    }
                    write(joinSet.getCoffeeOutputDirectory(), joinSet.getId(),
                            new CompileResult(compiled.toString(), null));
                }
            } else {
                for (JoinSet joinSet : findJoinSets()) {
                    getLog().info(
                            "Compiling JoinSet: " + joinSet.getId() + " with files:  " + joinSet.getFileNames());

                    String sourceName = joinSet.getId() + (joinSet.isLiterate() ? ".litcoffee" : ".coffee");
                    CompileResult compiled = coffeeScriptCompiler.compile(joinSet.getConcatenatedStringOfFiles(),
                            sourceName, bare, getSourceMapType(), header, joinSet.isLiterate());

                    write(joinSet.getCoffeeOutputDirectory(), joinSet.getId(), compiled);
                }
            }

        } catch (Exception e) {
            throw new MojoExecutionException(e.getMessage(), e);
        }
    }

    public CoffeeScriptCompiler.SourceMap getSourceMapType() {
        if (map) {
            return CoffeeScriptCompiler.SourceMap.V3;
        } else {
            return CoffeeScriptCompiler.SourceMap.NONE;
        }
    }

    private List<JoinSet> findJoinSets() {
        if (coffeeJoinSets != null && !coffeeJoinSets.isEmpty()) {
            return coffeeJoinSets;
        } else {
            // Generate a joinset for each .coffee file
            return ImmutableList.<JoinSet>builder().addAll(findJoinSetsInDirectory(coffeeDir, ".coffee", false))
                    .addAll(findJoinSetsInDirectory(coffeeDir, ".litcoffee", true))
                    .addAll(findJoinSetsInDirectory(coffeeDir, ".coffee.md", true)).build();

        }
    }

    private List<JoinSet> findJoinSetsInDirectory(final File coffeeDir, final String suffix,
            final boolean literate) {
        return Lists.transform(findCoffeeFilesInDirectory(coffeeDir, suffix), new Function<File, JoinSet>() {
            public JoinSet apply(@Nullable File file) {
                return new StaticJoinSet(file, literate);
            }
        });
    }

    private static class StaticJoinSet extends JoinSet {
        private File file;

        private StaticJoinSet(File file, boolean literate) {
            this.file = file;
            String name = file.getPath().substring(file.getParent().length() + 1);
            name = name.substring(0, name.lastIndexOf("."));
            if (name.endsWith("coffee")) {
                name = name.substring(0, name.lastIndexOf("."));
            }
            setId(name);
            setLiterate(literate);
        }

        @Override
        public List<File> getFiles() throws IOException {
            return ImmutableList.of(file);
        }
    }

    private List<File> findCoffeeFilesInDirectory(File coffeeDir, final String suffix) {

        List<File> coffeeFiles = Lists.newArrayList();

        File[] files = coffeeDir.listFiles();

        for (File file : files) {
            if (file.isDirectory()) {
                coffeeFiles.addAll(findCoffeeFilesInDirectory(file, suffix));
            } else {
                if (file.getPath().endsWith(suffix)) {
                    coffeeFiles.add(file);
                }
            }
        }

        return coffeeFiles;
    }

    private void write(final File joinSetOutputDirectory, final String fileName, final CompileResult contents)
            throws IOException {
        //Create the new Javascript file path
        File outputDirectory = coffeeOutputDirectory;
        if (joinSetOutputDirectory != null) {
            outputDirectory = joinSetOutputDirectory;
        }
        File jsFile = new File(outputDirectory, fileName + ".js");
        if (!jsFile.getParentFile().exists()) {
            jsFile.getParentFile().mkdirs();
        }

        Files.write(contents.getJs(), jsFile, Charsets.UTF_8);
        if (contents.getMap() != null) {
            File mapFile = new File(outputDirectory, fileName + ".js.map");
            Files.write(contents.getMap(), mapFile, Charsets.UTF_8);
        }
    }

}