org.codehaus.mojo.latex.LaTeXMojo.java Source code

Java tutorial

Introduction

Here is the source code for org.codehaus.mojo.latex.LaTeXMojo.java

Source

package org.codehaus.mojo.latex;

/*
 * Copyright 2010 INRIA / CITI Laboratory / Amazones Research Team.
 *
 * 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.
 *
 */

import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.io.FileUtils;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;

import static org.apache.commons.exec.CommandLine.parse;
import static org.apache.commons.io.FileUtils.copyDirectory;
import static org.apache.commons.io.FileUtils.copyFile;
import static org.apache.commons.io.FileUtils.iterateFiles;

/**
 * LaTeX documents building goal.
 *
 * @author Julien Ponge
 * @goal latex
 * @phase compile
 */
public class LaTeXMojo extends AbstractMojo {

    /**
     * The documents root.
     *
     * @parameter expression="${latex.docsRoot}" default-value="src/main/latex"
     * @required
     */
    private File docsRoot;

    /**
     * Common files directory inside the documents root (the only directory to be skipped).
     *
     * @parameter expression="${latex.commonsDirName}" default-value="common"
     * @required
     */
    private String commonsDirName;

    /**
     * The Maven build directory.
     *
     * @parameter expression="${project.build.directory}"
     * @required
     * @readonly
     */
    private File buildDir;

    /**
     * The LaTeX builds directory.
     *
     * @parameter expression="${project.latex.build.directory}" default-value="${project.build.directory}/latex"
     * @required
     */
    private File latexBuildDir;

    /**
     * Path to the LaTeX binaries installation.
     *
     * @parameter expression="${latex.binariesPath}" default-value=""
     */
    private String binariesPath;

    /**
     * Name of bibtex executable. Use this to invoke bibtex8 or biber instead of bibtex.
     *
     * @parameter expression="${latex.bibtex}" default-value="bibtex"
     */
    private String bibtex;

    public void execute() throws MojoExecutionException, MojoFailureException {
        try {
            final File[] docDirs = getDocDirs();
            final File[] buildDirs = prepareLaTeXBuildDirectories(docDirs);
            buildDocuments(buildDirs);
        } catch (IOException e) {
            getLog().error(e);
            throw new MojoFailureException(e.getMessage());
        }
    }

    private void buildDocuments(File[] buildDirs) throws IOException, MojoFailureException {
        for (File dir : buildDirs) {
            final File texFile = new File(dir, dir.getName() + ".tex");
            final File pdfFile = new File(dir, dir.getName() + ".pdf");
            final File bibFile = new File(dir, dir.getName() + ".bib");

            if (requiresBuilding(dir, pdfFile)) {

                final CommandLine pdfLaTeX = parse(executablePath("pdflatex")).addArgument("-shell-escape")
                        .addArgument("--halt-on-error").addArgument(texFile.getAbsolutePath());
                if (getLog().isDebugEnabled()) {
                    getLog().debug("pdflatex: " + pdfLaTeX);
                }

                final CommandLine bibTeX = parse(executablePath(bibtex)).addArgument(dir.getName());
                if (getLog().isDebugEnabled()) {
                    getLog().debug("bibtex: " + bibTeX);
                }

                execute(pdfLaTeX, dir);
                if (bibFile.exists()) {
                    execute(bibTeX, dir);
                    execute(pdfLaTeX, dir);
                }
                execute(pdfLaTeX, dir);

                copyFile(pdfFile, new File(buildDir, pdfFile.getName()));
            }
        }
    }

    private boolean requiresBuilding(File dir, File pdfFile) throws IOException {
        Collection texFiles = FileUtils.listFiles(dir, new String[] { "tex", "bib" }, true);
        getLog().info(texFiles.toString());
        if (pdfFile.exists()) {
            boolean upToDate = true;
            Iterator it = texFiles.iterator();
            while (it.hasNext() && upToDate) {
                File file = (File) it.next();
                if (FileUtils.isFileNewer(file, pdfFile)) {
                    if (getLog().isInfoEnabled()) {
                        getLog().info("Changes detected on " + file.getAbsolutePath());
                    }
                    return true;
                }
                if (getLog().isInfoEnabled()) {
                    getLog().info("No change detected on " + file.getAbsolutePath());
                }
            }
            if (getLog().isInfoEnabled()) {
                getLog().info("Skipping: no LaTeX changes detected in " + dir.getCanonicalPath());
            }
            return false;
        } else {
            return true;
        }
    }

    private String executablePath(String executable) {
        if (binariesPath == null) {
            return executable;
        } else {
            return new StringBuilder().append(binariesPath).append(File.separator).append(executable).toString();
        }
    }

    private void execute(CommandLine commandLine, File dir) throws IOException, MojoFailureException {
        final DefaultExecutor executor = new DefaultExecutor();
        executor.setWorkingDirectory(dir);
        if (executor.execute(commandLine) != 0) {
            throw new MojoFailureException("Error code returned for: " + commandLine.toString());
        }
    }

    private File[] prepareLaTeXBuildDirectories(File[] docDirs) throws IOException {
        final File[] buildDirs = new File[docDirs.length];
        final File commonsDir = new File(docsRoot, commonsDirName);

        for (int i = 0; i < docDirs.length; i++) {
            final File dir = docDirs[i];
            final File target = new File(latexBuildDir, docDirs[i].getName());
            buildDirs[i] = target;

            copyDirectory(dir, target);
            if (commonsDir.exists()) {
                copyDirectory(commonsDir, target);
            }

            final Iterator iterator = iterateFiles(target, new String[] { ".svn" }, true);
            while (iterator.hasNext()) {
                FileUtils.deleteDirectory((File) iterator.next());
            }

        }

        return buildDirs;
    }

    private File[] getDocDirs() {
        return docsRoot.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return pathname.isDirectory() && !(pathname.getName().equals(commonsDirName))
                        && !(pathname.isHidden());
            }
        });
    }

}