concatenate : concatenates multiple files into one destination.

Download concatenate.zip

Synopsis:

ConcatenateFiles.java


ConcatenateFiles.java

Synopsis
package com.arrizza.ant.taskdefs;

/**
 * com.optiron.ant.ConcatenateFiles
 * Copyright (c) 2001 Optiron, Inc. All Rights Reserved.
 *
 * This software is licenced under the Apache Software License. See:
 *
 *     http://www.apache.org/LICENSE.txt
 *
 *  for the license contents.
 */

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.tools.ant.*;
import org.apache.tools.ant.types.*;

/**
 * This class implements a new task for Ant: ConcatenateFiles. As the name
 * states, the purpose of this task is to concatenate two or more files into a
 * single file with a new name. You can also subsitute a message for one or
 * both of the 'begin' and 'end' files.
 *
 * Note that this will automatically overwrite the destFile until we create
 * some forceOverride methods.
 *
 * <p>Arguments for this task:</p>
 * <ul>
 *  <li>file: new filename
 *  <li>fileset: set of files that are concatenated for the new file
 * </ul>
 *
 * <p>The next two arguments are mutually exclusive:</p>
 * <ul>
 *  <li>beginfile: file that begins the new file
 *  <li>beginmessage: message that begins the new file
 * </ul>
 *
 * <p>The next two arguments are mutually exclusive:</p>
 * <ul>
 *  <li>endfile: file that ends the new file
 *  <li>endmessage: message that ends the new file
 * </ul>
 *
 * <p>Usage:</p>
 * <p>First define the taskdef:</p>
 *   <pre>
 *   &lt;taskdef name="concatenate"
 *            classname="com.optiron.ant.ConcatenateFiles"/&gt;
 *   </pre>
 * <p>Now define some actions:</p>
 *
 * <p>Concatenate all the files beginning with 'Plumbing' in the base
 * directory to a file called <tt>concat.txt</tt>:</p>
 * <code>
 *  <concatenate file="concat.txt">
 *    <fileset dir="${basedir}" includes="Plumbing*.*"/>
 *  </concatenate>
 * </code>
 * <p>Concatenate all XML files in the <code>deployment</code> subdirectory into
 * a file called <code>main.xml</code>:
 * <code>
 *  <concatenate file="main.xml">
 *    <fileset dir="${basedir}/deployment" includes="**\/xml"/>
 *  </concatenate>
 * </code>
 *
 * <p>More about Ant:
 * <a href="http://jakarta.apache.org/ant/">http://jakarta.apache.org/ant/</a></p>
 *
 * @author Chris Winters <a href="mailto:cwinters@optiron.com">cwinters@optiron.com</a>
 * @version $Revision: 1.3 $
 */

public class ConcatenateFiles
      extends Task
  {
  protected File file = null;
  protected File destFile = null;
  protected File beginFile = null;
  protected File endFile = null;
  protected String beginMessage = null;
  protected String endMessage = null;
  protected List filesets = new ArrayList();
  protected int verbosity = Project.MSG_VERBOSE;
  protected boolean forceBuild = false;

  public void setFile( File _set )
    {
    file = _set;
    }
  public void setBeginfile( File _set )
    {
    beginFile = _set;
    }
  public void setEndfile( File _set )
    {
    endFile = _set;
    }
  public void setBeginmessage( String _set )
    {
    beginMessage = _set;
    }
  public void setEndmessage( String _set )
    {
    endMessage = _set;
    }
  public void addFileset( FileSet set )
    {
    filesets.add( set );
    }
  public void setVerbose( boolean _set )
    {
    if ( _set )
      {
      verbosity = Project.MSG_INFO;
      }
    else
      {
      verbosity = Project.MSG_VERBOSE;
      }
    }
  public void setDepends( boolean _set )
    {
    this.forceBuild = !_set;
    }


  /**
   * Perform the actual action. First validate the parameters passed
   * to the task to ensure everything is sane, then open up the
   * output file. Next do the beginning file/message, process the
   * fileset and then do the ending file/message.
   *
   * @exception BuildException for any IO problems (can't read file,
   * can't open file, can't write to file, etc.)
   */
  public void execute() //throws BuildException
    {
    // Ensure everything is set correctly
    validateAttributes();
    FileWriter out = null;
    try
      {
      destFile = new File( file.getAbsolutePath() );
      if (forceBuild || outOfDate())
        processAllFiles(out);
      else
        log("No files are out-of-date.", verbosity);
      }
    catch ( IOException ioe )
      {
      throw new BuildException( "Error with the filesystem: " + ioe.getMessage() );
      }
    finally
      {
      try
        {
        if ( out != null )
          {
          out.close();
          }
        }
      catch ( IOException ioe )
        {
        throw new BuildException( "Cannot close output buffer! Error: " + ioe.getMessage() );
        }
      }
    }

  //------------------------------------
  //-- private from here on
  //------------------------------------

  //------------------------------------
  private boolean outOfDate()
  throws IOException
    {
    long destTimeStamp = 0;
    if ( destFile.exists() )
      destTimeStamp = destFile.lastModified();

    if (destTimeStamp == 0)
      {
      log( "Destination file " + destFile.getCanonicalPath() + " does not exist. building...", verbosity );
      return true;
      }

    boolean doit = false;

    if ( beginFile != null )
      {
      if (beginFile.lastModified() > destTimeStamp)
        {
        log( "Beginning file " + beginFile.getCanonicalPath() + " is out-of-date. building...", verbosity );
        doit = true;
        }
      }

    if ( endFile != null )
      {
      if (endFile.lastModified() > destTimeStamp)
        {
        log( "Ending file " + endFile.getCanonicalPath() + " is out-of-date. building...", verbosity );
        doit = true;
        }
      }

    // Now do the filesets specified
    Iterator fsi = filesets.iterator();
    while ( fsi.hasNext() )
      {
      FileSet fs = (FileSet)fsi.next();
      DirectoryScanner ds = fs.getDirectoryScanner( getProject() );
      String[] srcFiles = ds.getIncludedFiles();
      File baseDir = ds.getBasedir().getAbsoluteFile();
      for ( int i = 0; i < srcFiles.length; i++ )
        {
        File readFile = new File( baseDir, srcFiles[i] );
        if (readFile.lastModified() > destTimeStamp)
          {
          doit = true;
          log( "Fileset file " + readFile.getCanonicalPath() + " is out-of-date. building...", verbosity );
          }
        }
      }
    return doit;
    }

  //------------------------------------------------
  private void processAllFiles(FileWriter out)
  throws IOException
    {
    // Open up the new file and a writer to it.
    if ( destFile.exists() )
      {
      log( "File " + destFile.getCanonicalPath() + " exists; removing.", verbosity );
      destFile.delete();
      destFile.createNewFile();
      }
    out = new FileWriter( destFile.getAbsolutePath() );

    // If the beginFile is defined, contatenate it
    if ( beginFile != null )
      {
      concatenate( out, beginFile );
      log( "Beginning file " + beginFile.getCanonicalPath() + " ok", verbosity );
      }

    if ( beginMessage != null )
      {
      concatenate( out, beginMessage );
      log( "Beginning message ok", verbosity );
      }

    Iterator fsi = filesets.iterator();
    while ( fsi.hasNext() )
      {
      FileSet fs = (FileSet)fsi.next();
      DirectoryScanner ds = fs.getDirectoryScanner( getProject() );
      String[] srcFiles = ds.getIncludedFiles();
      File baseDir = ds.getBasedir().getAbsoluteFile();
      for ( int i = 0; i < srcFiles.length; i++ )
        {
        File readFile = new File( baseDir, srcFiles[i] );
        concatenate( out, readFile );
        log( "Fileset file " + readFile.getCanonicalPath() + " ok", verbosity );
        }
      }

    // And if the endFile is defined, do it
    if ( endFile != null )
      {
      concatenate( out, endFile );
      log( "Ending file " + endFile.getCanonicalPath() + " ok", verbosity );
      }

    if ( endMessage != null )
      {
      concatenate( out, endMessage );
      log( "Ending message ok", verbosity );
      }

    log( "Created new file (" + destFile.getCanonicalPath() + ") successfully" );
    out.close();
    }

  /**
   * Ensure we have the right attributes. Failure conditions are:
   *
   * <ul>
   *   <li>destination file is not specified</li>
   *   <li>both 'beginmessage' and 'beginfile' are specified</li>
   *   <li>both 'endmessage' and 'endfile' are specified</li>
   *   <li>no messages or files are specified at all</li>
   * </ul>
   *
   * @throws BuildException if one of the specifications is not met.
   */
  protected void validateAttributes() //throws BuildException
    {
    if ( file == null )
      {
      throw new BuildException("You must specify a destfile." );
      }
    if ( beginMessage != null && beginFile != null )
      {
      throw new BuildException( "You cannot specify both 'beginmessage' and 'beginfile'" );
      }
    if ( endMessage != null && endFile != null )
      {
      throw new BuildException( "You cannot specify both 'endmessage' and 'endfile'" );
      }
    boolean hasMessage = ( beginMessage != null || endMessage != null );
    boolean hasFile = ( beginFile != null || endFile != null || filesets.size() > 0 );
    if ( ! hasMessage && ! hasFile )
      {
      throw new BuildException( "You must specify one or more messages or files." );
      }
    }

  /**
   * Concatenate two text files
   *
   * @param to file object appending to
   * @param from file whose contents we're appending
   * @throws IOException if we can't read the file or if the actual
   * write fails
   */
  private static void concatenate( FileWriter to, File from )
  throws IOException
    {
    BufferedReader in = new BufferedReader( new FileReader( from ) );
    String inBuf = new String();
    StringBuffer contents = new StringBuffer();
    while ( ( inBuf = in.readLine() ) != null )
      {
      contents.append( inBuf + "\r\n" );
      }
    in.close();
    concatenate( to, contents.toString() );
    }

  /**
   * Concatenate a string to a text file
   *
   * @param to file object appending to
   * @param from string we're appending
   * @throws IOException if the write fails
   */
  private static void concatenate( FileWriter to, String from )
  throws IOException
    {
    to.write( from );
    }
  }






Contact me about content on this page using john_web-at-arrizza-dot-com
For Web Master or site problems contact: webadmin-at-arrizza-dot-com
Copyright John Arrizza (c) 2001-2010