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;
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() );
}
} );
}
}