Return-Path: Delivered-To: apmail-jakarta-ant-dev-archive@apache.org Received: (qmail 92937 invoked from network); 30 Dec 2001 09:58:54 -0000 Received: from unknown (HELO nagoya.betaversion.org) (192.18.49.131) by daedalus.apache.org with SMTP; 30 Dec 2001 09:58:54 -0000 Received: (qmail 21302 invoked by uid 97); 30 Dec 2001 09:58:41 -0000 Delivered-To: qmlist-jakarta-archive-ant-dev@jakarta.apache.org Received: (qmail 21245 invoked by uid 97); 30 Dec 2001 09:58:40 -0000 Mailing-List: contact ant-dev-help@jakarta.apache.org; run by ezmlm Precedence: bulk List-Unsubscribe: List-Subscribe: List-Help: List-Post: List-Id: "Ant Developers List" Reply-To: "Ant Developers List" Delivered-To: mailing list ant-dev@jakarta.apache.org Received: (qmail 21234 invoked by uid 97); 30 Dec 2001 09:58:40 -0000 Date: 30 Dec 2001 09:58:25 -0000 Message-ID: <20011230095825.7950.qmail@icarus.apache.org> From: donaldp@apache.org To: jakarta-ant-cvs@apache.org Subject: cvs commit: jakarta-ant/proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/text FixCRLF.java NestedString.java Replace.java Replacefilter.java X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N donaldp 01/12/30 01:58:25 Modified: proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs Filter.java proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/optional/ide VAJWorkspaceScanner.java proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/optional/net FTP.java Added: proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/text FixCRLF.java NestedString.java Replace.java Replacefilter.java Removed: proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs FixCRLF.java NestedString.java Replace.java Replacefilter.java Log: Move text manipulation tasks into new package Revision Changes Path 1.7 +2 -1 jakarta-ant/proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/Filter.java Index: Filter.java =================================================================== RCS file: /home/cvs/jakarta-ant/proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/Filter.java,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- Filter.java 23 Dec 2001 14:21:50 -0000 1.6 +++ Filter.java 30 Dec 2001 09:58:25 -0000 1.7 @@ -21,7 +21,8 @@ * @author Gero Vermaas gero@xs4all.nl * @author Michael McCallum */ -public class Filter extends Task +public class Filter + extends Task { private File filtersFile; 1.6 +10 -10 jakarta-ant/proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/optional/ide/VAJWorkspaceScanner.java Index: VAJWorkspaceScanner.java =================================================================== RCS file: /home/cvs/jakarta-ant/proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/optional/ide/VAJWorkspaceScanner.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- VAJWorkspaceScanner.java 23 Dec 2001 06:31:57 -0000 1.5 +++ VAJWorkspaceScanner.java 30 Dec 2001 09:58:25 -0000 1.6 @@ -94,12 +94,12 @@ */ public void addDefaultExcludes() { - int excludesLength = excludes == null ? 0 : excludes.length; + int excludesLength = getExcludes() == null ? 0 : getExcludes().length; String[] newExcludes; newExcludes = new String[ excludesLength + DEFAULTEXCLUDES.length ]; if( excludesLength > 0 ) { - System.arraycopy( excludes, 0, newExcludes, 0, excludesLength ); + System.arraycopy( getExcludes(), 0, newExcludes, 0, excludesLength ); } for( int i = 0; i < DEFAULTEXCLUDES.length; i++ ) { @@ -107,7 +107,7 @@ replace( '/', File.separatorChar ). replace( '\\', File.separatorChar ); } - excludes = newExcludes; + setExcludes( newExcludes ); } /** @@ -125,10 +125,10 @@ for( int i = 0; i < projects.length; i++ ) { Project project = projects[ i ]; - for( int j = 0; j < includes.length && !allProjectsMatch; j++ ) + for( int j = 0; j < getIncludes().length && !allProjectsMatch; j++ ) { StringTokenizer tok = - new StringTokenizer( includes[ j ], File.separator ); + new StringTokenizer( getIncludes()[ j ], File.separator ); String projectNamePattern = tok.nextToken(); if( projectNamePattern.equals( "**" ) ) { @@ -162,15 +162,15 @@ */ public void scan() { - if( includes == null ) + if( getIncludes() == null ) { // No includes supplied, so set it to 'matches all' - includes = new String[ 1 ]; - includes[ 0 ] = "**"; + setIncludes( new String[ 1 ] ); + getIncludes()[ 0 ] = "**"; } - if( excludes == null ) + if( getExcludes() == null ) { - excludes = new String[ 0 ]; + setExcludes( new String[ 0 ] ); } // only scan projects which are included in at least one include pattern 1.10 +17 -17 jakarta-ant/proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/optional/net/FTP.java Index: FTP.java =================================================================== RCS file: /home/cvs/jakarta-ant/proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/optional/net/FTP.java,v retrieving revision 1.9 retrieving revision 1.10 diff -u -r1.9 -r1.10 --- FTP.java 23 Dec 2001 14:22:47 -0000 1.9 +++ FTP.java 30 Dec 2001 09:58:25 -0000 1.10 @@ -962,23 +962,23 @@ public void scan() { - if( includes == null ) + if( getIncludes() == null ) { // No includes supplied, so set it to 'matches all' - includes = new String[ 1 ]; - includes[ 0 ] = "**"; + setIncludes( new String[ 1 ] ); + getIncludes()[ 0 ] = "**"; } - if( excludes == null ) + if( getExcludes() == null ) { - excludes = new String[ 0 ]; + setExcludes( new String[ 0 ] ); } - filesIncluded = new ArrayList(); - filesNotIncluded = new ArrayList(); - filesExcluded = new ArrayList(); - dirsIncluded = new ArrayList(); - dirsNotIncluded = new ArrayList(); - dirsExcluded = new ArrayList(); + setFilesIncluded( new ArrayList() ); + setFilesNotIncluded( new ArrayList() ); + setFilesExcluded( new ArrayList() ); + setDirsIncluded( new ArrayList() ); + setDirsNotIncluded( new ArrayList() ); + setDirsExcluded( new ArrayList() ); try { @@ -1020,7 +1020,7 @@ { if( !isExcluded( name ) ) { - dirsIncluded.add( name ); + getDirsIncluded().add( name ); if( fast ) { scandir( name, vpath + name + File.separator, fast ); @@ -1028,12 +1028,12 @@ } else { - dirsExcluded.add( name ); + getDirsExcluded().add( name ); } } else { - dirsNotIncluded.add( name ); + getDirsNotIncluded().add( name ); if( fast && couldHoldIncluded( name ) ) { scandir( name, vpath + name + File.separator, fast ); @@ -1053,16 +1053,16 @@ { if( !isExcluded( name ) ) { - filesIncluded.add( name ); + getFilesIncluded().add( name ); } else { - filesExcluded.add( name ); + getFilesExcluded().add( name ); } } else { - filesNotIncluded.add( name ); + getFilesNotIncluded().add( name ); } } } 1.1 jakarta-ant/proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/text/FixCRLF.java Index: FixCRLF.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE.txt file. */ package org.apache.tools.ant.taskdefs.text; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; import java.io.InputStream; import java.io.BufferedInputStream; import java.util.Iterator; import java.util.NoSuchElementException; import org.apache.myrmidon.api.TaskException; import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.taskdefs.MatchingTask; import org.apache.tools.ant.types.EnumeratedAttribute; import org.apache.tools.ant.util.FileUtils; /** * Task to convert text source files to local OS formatting conventions, as well * as repair text files damaged by misconfigured or misguided editors or file * transfer programs.

* * This task can take the following arguments: *

    *
  • srcdir *
  • destdir *
  • include *
  • exclude *
  • cr *
  • eol *
  • tab *
  • eof *
  • encoding *
* Of these arguments, only sourcedir is required.

* * When this task executes, it will scan the srcdir based on the include and * exclude properties.

* * This version generalises the handling of EOL characters, and allows for * CR-only line endings (which I suspect is the standard on Macs.) Tab handling * has also been generalised to accommodate any tabwidth from 2 to 80, * inclusive. Importantly, it will leave untouched any literal TAB characters * embedded within string or character constants.

* * Warning: do not run on binary files. Caution: run with care * on carefully formatted files. This may sound obvious, but if you don't * specify asis, presume that your files are going to be modified. If "tabs" is * "add" or "remove", whitespace characters may be added or removed as * necessary. Similarly, for CR's - in fact "eol"="crlf" or cr="add" can result * in cr characters being removed in one special case accommodated, i.e., CRCRLF * is regarded as a single EOL to handle cases where other programs have * converted CRLF into CRCRLF. * * @author Sam Ruby rubys@us.ibm.com * @author Peter B. West * @version $Revision: 1.1 $ $Name: $ */ public class FixCRLF extends MatchingTask { private final static int UNDEF = -1; private final static int NOTJAVA = 0; private final static int LOOKING = 1; private final static int IN_CHAR_CONST = 2; private final static int IN_STR_CONST = 3; private final static int IN_SINGLE_COMMENT = 4; private final static int IN_MULTI_COMMENT = 5; private final static int ASIS = 0; private final static int CR = 1; private final static int LF = 2; private final static int CRLF = 3; private final static int ADD = 1; private final static int REMOVE = -1; private final static int SPACES = -1; private final static int TABS = 1; private final static int INBUFLEN = 8192; private final static int LINEBUFLEN = 200; private final static char CTRLZ = '\u001A'; private int tablength = 8; private String spaces = " "; private StringBuffer linebuf = new StringBuffer( 1024 ); private StringBuffer linebuf2 = new StringBuffer( 1024 ); private boolean javafiles = false; private File destDir = null; /** * Encoding to assume for the files */ private String encoding = null; private int ctrlz; private int eol; private String eolstr; private File srcDir; private int tabs; /** * Defaults the properties based on the system type. *

    *
  • Unix: eol="LF" tab="asis" eof="remove" *
  • Mac: eol="CR" tab="asis" eof="remove" *
  • DOS: eol="CRLF" tab="asis" eof="asis" *
* */ public FixCRLF() { tabs = ASIS; if( File.pathSeparator.equals( ":" ) ) { ctrlz = REMOVE; if( System.getProperty( "os.name" ).indexOf( "Mac" ) > -1 ) { eol = CR; eolstr = "\r"; } else { eol = LF; eolstr = "\n"; } } else { ctrlz = ASIS; eol = CRLF; eolstr = "\r\n"; } } /** * Set the destination where the fixed files should be placed. Default is to * replace the original file. * * @param destDir The new Destdir value */ public void setDestdir( File destDir ) { this.destDir = destDir; } /** * Specifies the encoding Ant expects the files to be in - defaults to the * platforms default encoding. * * @param encoding The new Encoding value */ public void setEncoding( String encoding ) { this.encoding = encoding; } /** * Specify how DOS EOF (control-z) charaters are to be handled * * @param attr The new Eof value */ public void setEof( AddAsisRemove attr ) { String option = attr.getValue(); if( option.equals( "remove" ) ) { ctrlz = REMOVE; } else if( option.equals( "asis" ) ) { ctrlz = ASIS; } else { // must be "add" ctrlz = ADD; } } /** * Specify how EndOfLine characters are to be handled * * @param attr The new Eol value */ public void setEol( CrLf attr ) { String option = attr.getValue(); if( option.equals( "asis" ) ) { eol = ASIS; } else if( option.equals( "cr" ) ) { eol = CR; eolstr = "\r"; } else if( option.equals( "lf" ) ) { eol = LF; eolstr = "\n"; } else { // Must be "crlf" eol = CRLF; eolstr = "\r\n"; } } /** * Fixing Java source files? * * @param javafiles The new Javafiles value */ public void setJavafiles( boolean javafiles ) { this.javafiles = javafiles; } /** * Set the source dir to find the source text files. * * @param srcDir The new Srcdir value */ public void setSrcdir( File srcDir ) { this.srcDir = srcDir; } /** * Specify how tab characters are to be handled * * @param attr The new Tab value */ public void setTab( AddAsisRemove attr ) { String option = attr.getValue(); if( option.equals( "remove" ) ) { tabs = SPACES; } else if( option.equals( "asis" ) ) { tabs = ASIS; } else { // must be "add" tabs = TABS; } } /** * Specify tab length in characters * * @param tlength specify the length of tab in spaces, * @exception TaskException Description of Exception */ public void setTablength( int tlength ) throws TaskException { if( tlength < 2 || tlength > 80 ) { throw new TaskException( "tablength must be between 2 and 80" ); } tablength = tlength; StringBuffer sp = new StringBuffer(); for( int i = 0; i < tablength; i++ ) { sp.append( ' ' ); } spaces = sp.toString(); } /** * Executes the task. * * @exception TaskException Description of Exception */ public void execute() throws TaskException { // first off, make sure that we've got a srcdir and destdir if( srcDir == null ) { throw new TaskException( "srcdir attribute must be set!" ); } if( !srcDir.exists() ) { throw new TaskException( "srcdir does not exist!" ); } if( !srcDir.isDirectory() ) { throw new TaskException( "srcdir is not a directory!" ); } if( destDir != null ) { if( !destDir.exists() ) { throw new TaskException( "destdir does not exist!" ); } if( !destDir.isDirectory() ) { throw new TaskException( "destdir is not a directory!" ); } } // log options used getLogger().debug( "options:" + " eol=" + ( eol == ASIS ? "asis" : eol == CR ? "cr" : eol == LF ? "lf" : "crlf" ) + " tab=" + ( tabs == TABS ? "add" : tabs == ASIS ? "asis" : "remove" ) + " eof=" + ( ctrlz == ADD ? "add" : ctrlz == ASIS ? "asis" : "remove" ) + " tablength=" + tablength + " encoding=" + ( encoding == null ? "default" : encoding ) ); DirectoryScanner ds = super.getDirectoryScanner( srcDir ); String[] files = ds.getIncludedFiles(); for( int i = 0; i < files.length; i++ ) { processFile( files[ i ] ); } } /** * Creates a Reader reading from a given file an taking the user defined * encoding into account. * * @param f Description of Parameter * @return The Reader value * @exception IOException Description of Exception */ private Reader getReader( File f ) throws IOException { return ( encoding == null ) ? new FileReader( f ) : new InputStreamReader( new FileInputStream( f ), encoding ); } /** * Scan a BufferLine forward from the 'next' pointer for the end of a * character constant. Set 'lookahead' pointer to the character following * the terminating quote. * * @param bufline Description of Parameter * @param terminator Description of Parameter * @exception TaskException Description of Exception */ private void endOfCharConst( OneLiner.BufferLine bufline, char terminator ) throws TaskException { int ptr = bufline.getNext(); int eol = bufline.length(); char c; ptr++;// skip past initial quote while( ptr < eol ) { if( ( c = bufline.getChar( ptr++ ) ) == '\\' ) { ptr++; } else { if( c == terminator ) { bufline.setLookahead( ptr ); return; } } }// end of while (ptr < eol) // Must have fallen through to the end of the line throw new TaskException( "endOfCharConst: unterminated char constant" ); } /** * Scan a BufferLine for the next state changing token: the beginning of a * single or multi-line comment, a character or a string constant. As a * side-effect, sets the buffer state to the next state, and sets field * lookahead to the first character of the state-changing token, or to the * next eol character. * * @param bufline Description of Parameter * @exception TaskException Description of Exception */ private void nextStateChange( OneLiner.BufferLine bufline ) throws TaskException { int eol = bufline.length(); int ptr = bufline.getNext(); // Look for next single or double quote, double slash or slash star while( ptr < eol ) { switch( bufline.getChar( ptr++ ) ) { case '\'': bufline.setState( IN_CHAR_CONST ); bufline.setLookahead( --ptr ); return; case '\"': bufline.setState( IN_STR_CONST ); bufline.setLookahead( --ptr ); return; case '/': if( ptr < eol ) { if( bufline.getChar( ptr ) == '*' ) { bufline.setState( IN_MULTI_COMMENT ); bufline.setLookahead( --ptr ); return; } else if( bufline.getChar( ptr ) == '/' ) { bufline.setState( IN_SINGLE_COMMENT ); bufline.setLookahead( --ptr ); return; } } break; }// end of switch (bufline.getChar(ptr++)) }// end of while (ptr < eol) // Eol is the next token bufline.setLookahead( ptr ); } /** * Process a BufferLine string which is not part of of a string constant. * The start position of the string is given by the 'next' field. Sets the * 'next' and 'column' fields in the BufferLine. * * @param bufline Description of Parameter * @param end Description of Parameter * @param outWriter Description of Parameter */ private void notInConstant( OneLiner.BufferLine bufline, int end, BufferedWriter outWriter ) throws TaskException { // N.B. both column and string index are zero-based // Process a string not part of a constant; // i.e. convert tabs<->spaces as required // This is NOT called for ASIS tab handling int nextTab; int nextStop; int tabspaces; String line = bufline.substring( bufline.getNext(), end ); int place = 0;// Zero-based int col = bufline.getColumn();// Zero-based // process sequences of white space // first convert all tabs to spaces linebuf.setLength( 0 ); while( ( nextTab = line.indexOf( (int)'\t', place ) ) >= 0 ) { linebuf.append( line.substring( place, nextTab ) );// copy to the TAB col += nextTab - place; tabspaces = tablength - ( col % tablength ); linebuf.append( spaces.substring( 0, tabspaces ) ); col += tabspaces; place = nextTab + 1; }// end of while linebuf.append( line.substring( place, line.length() ) ); // if converting to spaces, all finished String linestring = new String( linebuf.toString() ); if( tabs == REMOVE ) { try { outWriter.write( linestring ); } catch( IOException e ) { throw new TaskException( "Error", e ); }// end of try-catch } else {// tabs == ADD int tabCol; linebuf2.setLength( 0 ); place = 0; col = bufline.getColumn(); int placediff = col - 0; // for the length of the string, cycle through the tab stop // positions, checking for a space preceded by at least one // other space at the tab stop. if so replace the longest possible // preceding sequence of spaces with a tab. nextStop = col + ( tablength - col % tablength ); if( nextStop - col < 2 ) { linebuf2.append( linestring.substring( place, nextStop - placediff ) ); place = nextStop - placediff; nextStop += tablength; } for( ; nextStop - placediff <= linestring.length() ; nextStop += tablength ) { for( tabCol = nextStop; --tabCol - placediff >= place && linestring.charAt( tabCol - placediff ) == ' ' ; ) { ;// Loop for the side-effects } // tabCol is column index of the last non-space character // before the next tab stop if( nextStop - tabCol > 2 ) { linebuf2.append( linestring.substring( place, ++tabCol - placediff ) ); linebuf2.append( '\t' ); } else { linebuf2.append( linestring.substring( place, nextStop - placediff ) ); }// end of else place = nextStop - placediff; }// end of for (nextStop ... ) // pick up that last bit, if any linebuf2.append( linestring.substring( place, linestring.length() ) ); try { outWriter.write( linebuf2.toString() ); } catch( IOException e ) { throw new TaskException( "Error", e ); }// end of try-catch }// end of else tabs == ADD // Set column position as modified by this method bufline.setColumn( bufline.getColumn() + linestring.length() ); bufline.setNext( end ); } private void processFile( String file ) throws TaskException { File srcFile = new File( srcDir, file ); File destD = destDir == null ? srcDir : destDir; File tmpFile = null; BufferedWriter outWriter; OneLiner.BufferLine line; // read the contents of the file OneLiner lines = new OneLiner( srcFile ); try { // Set up the output Writer try { tmpFile = File.createTempFile( "fixcrlf", "", destD ); Writer writer = ( encoding == null ) ? new FileWriter( tmpFile ) : new OutputStreamWriter( new FileOutputStream( tmpFile ), encoding ); outWriter = new BufferedWriter( writer ); } catch( IOException e ) { throw new TaskException( "Error", e ); } while( lines.hasNext() ) { // In-line states int endComment; try { line = (OneLiner.BufferLine)lines.next(); } catch( NoSuchElementException e ) { throw new TaskException( "Error", e ); } String lineString = line.getLineString(); int linelen = line.length(); // Note - all of the following processing NOT done for // tabs ASIS if( tabs == ASIS ) { // Just copy the body of the line across try { outWriter.write( lineString ); } catch( IOException e ) { throw new TaskException( "Error", e ); }// end of try-catch } else {// (tabs != ASIS) int ptr; while( ( ptr = line.getNext() ) < linelen ) { switch( lines.getState() ) { case NOTJAVA: notInConstant( line, line.length(), outWriter ); break; case IN_MULTI_COMMENT: if( ( endComment = lineString.indexOf( "*/", line.getNext() ) ) >= 0 ) { // End of multiLineComment on this line endComment += 2;// Include the end token lines.setState( LOOKING ); } else { endComment = linelen; } notInConstant( line, endComment, outWriter ); break; case IN_SINGLE_COMMENT: notInConstant( line, line.length(), outWriter ); lines.setState( LOOKING ); break; case IN_CHAR_CONST: case IN_STR_CONST: // Got here from LOOKING by finding an opening "\'" // next points to that quote character. // Find the end of the constant. Watch out for // backslashes. Literal tabs are left unchanged, and // the column is adjusted accordingly. int begin = line.getNext(); char terminator = ( lines.getState() == IN_STR_CONST ? '\"' : '\'' ); endOfCharConst( line, terminator ); while( line.getNext() < line.getLookahead() ) { if( line.getNextCharInc() == '\t' ) { line.setColumn( line.getColumn() + tablength - line.getColumn() % tablength ); } else { line.incColumn(); } } // Now output the substring try { outWriter.write( line.substring( begin, line.getNext() ) ); } catch( IOException e ) { throw new TaskException( "Error", e ); } lines.setState( LOOKING ); break; case LOOKING: nextStateChange( line ); notInConstant( line, line.getLookahead(), outWriter ); break; }// end of switch (state) }// end of while (line.getNext() < linelen) }// end of else (tabs != ASIS) try { outWriter.write( eolstr ); } catch( IOException e ) { throw new TaskException( "Error", e ); }// end of try-catch }// end of while (lines.hasNext()) try { // Handle CTRLZ if( ctrlz == ASIS ) { outWriter.write( lines.getEofStr() ); } else if( ctrlz == ADD ) { outWriter.write( CTRLZ ); } } catch( IOException e ) { throw new TaskException( "Error", e ); } finally { try { outWriter.close(); } catch( IOException e ) { throw new TaskException( "Error", e ); } } File destFile = new File( destD, file ); try { lines.close(); lines = null; } catch( IOException e ) { throw new TaskException( "Unable to close source file " + srcFile ); } if( destFile.exists() ) { // Compare the destination with the temp file getLogger().debug( "destFile exists" ); if( !contentEquals( destFile, tmpFile ) ) { getLogger().debug( destFile + " is being written" ); if( !destFile.delete() ) { throw new TaskException( "Unable to delete " + destFile ); } if( !tmpFile.renameTo( destFile ) ) { throw new TaskException( "Failed to transform " + srcFile + " to " + destFile + ". Couldn't rename temporary file: " + tmpFile ); } } else {// destination is equal to temp file getLogger().debug( destFile + " is not written, as the contents are identical" ); if( !tmpFile.delete() ) { throw new TaskException( "Unable to delete " + tmpFile ); } } } else {// destFile does not exist - write the temp file ///XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX getLogger().debug( "destFile does not exist" ); if( !tmpFile.renameTo( destFile ) ) { throw new TaskException( "Failed to transform " + srcFile + " to " + destFile + ". Couldn't rename temporary file: " + tmpFile ); } } tmpFile = null; } catch( IOException e ) { throw new TaskException( "Error", e ); } finally { try { if( lines != null ) { lines.close(); } } catch( IOException io ) { getLogger().error( "Error closing " + srcFile ); }// end of catch if( tmpFile != null ) { tmpFile.delete(); } }// end of finally } private boolean contentEquals( File f1, File f2 ) throws IOException { if( f1.exists() != f2.exists() ) { return false; } if( !f1.exists() ) { // two not existing files are equal return true; } if( f1.isDirectory() || f2.isDirectory() ) { // don't want to compare directory contents for now return false; } InputStream in1 = null; InputStream in2 = null; try { in1 = new BufferedInputStream( new FileInputStream( f1 ) ); in2 = new BufferedInputStream( new FileInputStream( f2 ) ); int expectedByte = in1.read(); while( expectedByte != -1 ) { if( expectedByte != in2.read() ) { return false; } expectedByte = in1.read(); } if( in2.read() != -1 ) { return false; } return true; } finally { if( in1 != null ) { try { in1.close(); } catch( IOException e ) { } } if( in2 != null ) { try { in2.close(); } catch( IOException e ) { } } } } /** * Enumerated attribute with the values "asis", "add" and "remove". * * @author RT */ public static class AddAsisRemove extends EnumeratedAttribute { public String[] getValues() { return new String[]{"add", "asis", "remove"}; } } /** * Enumerated attribute with the values "asis", "cr", "lf" and "crlf". * * @author RT */ public static class CrLf extends EnumeratedAttribute { public String[] getValues() { return new String[]{"asis", "cr", "lf", "crlf"}; } } class OneLiner implements Iterator { private int state = javafiles ? LOOKING : NOTJAVA; private StringBuffer eolStr = new StringBuffer( LINEBUFLEN ); private StringBuffer eofStr = new StringBuffer(); private StringBuffer line = new StringBuffer(); private boolean reachedEof = false; private BufferedReader reader; public OneLiner( File srcFile ) throws TaskException { try { reader = new BufferedReader ( getReader( srcFile ), INBUFLEN ); nextLine(); } catch( IOException e ) { throw new TaskException( "Error", e ); } } public void remove() { throw new UnsupportedOperationException(); } public void setState( int state ) { this.state = state; } public String getEofStr() { return eofStr.toString(); } public int getState() { return state; } public void close() throws IOException { if( reader != null ) { reader.close(); } } public boolean hasNext() { return !reachedEof; } public Object next() throws NoSuchElementException { if( !hasNext() ) { throw new NoSuchElementException( "OneLiner" ); } try { BufferLine tmpLine = new BufferLine( line.toString(), eolStr.toString() ); nextLine(); return tmpLine; } catch( TaskException e ) { throw new NoSuchElementException(); } } protected void nextLine() throws TaskException { int ch = -1; int eolcount = 0; eolStr.setLength( 0 ); line.setLength( 0 ); try { ch = reader.read(); while( ch != -1 && ch != '\r' && ch != '\n' ) { line.append( (char)ch ); ch = reader.read(); } if( ch == -1 && line.length() == 0 ) { // Eof has been reached reachedEof = true; return; } switch( (char)ch ) { case '\r': // Check for \r, \r\n and \r\r\n // Regard \r\r not followed by \n as two lines ++eolcount; eolStr.append( '\r' ); switch( (char)( ch = reader.read() ) ) { case '\r': if( (char)( ch = reader.read() ) == '\n' ) { eolcount += 2; eolStr.append( "\r\n" ); } break; case '\n': ++eolcount; eolStr.append( '\n' ); break; }// end of switch ((char)(ch = reader.read())) break; case '\n': ++eolcount; eolStr.append( '\n' ); break; }// end of switch ((char) ch) // if at eolcount == 0 and trailing characters of string // are CTRL-Zs, set eofStr if( eolcount == 0 ) { int i = line.length(); while( --i >= 0 && line.charAt( i ) == CTRLZ ) { // keep searching for the first ^Z } if( i < line.length() - 1 ) { // Trailing characters are ^Zs // Construct new line and eofStr eofStr.append( line.toString().substring( i + 1 ) ); if( i < 0 ) { line.setLength( 0 ); reachedEof = true; } else { line.setLength( i + 1 ); } } }// end of if (eolcount == 0) } catch( IOException e ) { throw new TaskException( "Error", e ); } } class BufferLine { private int next = 0; private int column = 0; private int lookahead = UNDEF; private String eolStr; private String line; public BufferLine( String line, String eolStr ) throws TaskException { next = 0; column = 0; this.line = line; this.eolStr = eolStr; } public void setColumn( int col ) { column = col; } public void setLookahead( int lookahead ) { this.lookahead = lookahead; } public void setNext( int next ) { this.next = next; } public void setState( int state ) { OneLiner.this.setState( state ); } public char getChar( int i ) { return line.charAt( i ); } public int getColumn() { return column; } public String getEol() { return eolStr; } public int getEolLength() { return eolStr.length(); } public String getLineString() { return line; } public int getLookahead() { return lookahead; } public int getNext() { return next; } public char getNextChar() { return getChar( next ); } public char getNextCharInc() { return getChar( next++ ); } public int getState() { return OneLiner.this.getState(); } public int incColumn() { return column++; } public int length() { return line.length(); } public String substring( int begin ) { return line.substring( begin ); } public String substring( int begin, int end ) { return line.substring( begin, end ); } } } } 1.1 jakarta-ant/proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/text/NestedString.java Index: NestedString.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE.txt file. */ package org.apache.tools.ant.taskdefs.text; public class NestedString { private String m_text = ""; public String getText() { return m_text; } public void addContent( final String text ) { m_text = text; } } 1.1 jakarta-ant/proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/text/Replace.java Index: Replace.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE.txt file. */ package org.apache.tools.ant.taskdefs.text; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; import java.util.ArrayList; import java.util.Properties; import org.apache.myrmidon.api.TaskException; import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.taskdefs.MatchingTask; import org.apache.avalon.excalibur.util.StringUtil; /** * Replaces all occurrences of one or more string tokens with given values in * the indicated files. Each value can be either a string or the value of a * property available in a designated property file. * * @author Stefano Mazzocchi * stefano@apache.org * @author Erik Langenbach */ public class Replace extends MatchingTask { private File m_src; private NestedString m_token; private NestedString m_value = new NestedString(); private File m_propertyFile; private Properties m_properties; private ArrayList m_replacefilters = new ArrayList(); private File m_dir; private boolean m_summary; /** * The encoding used to read and write files - if null, uses default */ private String m_encoding; private int m_fileCount; private int m_replaceCount; /** * Set the source files path when using matching tasks. * * @param dir The new Dir value */ public void setDir( File dir ) { m_dir = dir; } /** * Set the file encoding to use on the files read and written by replace * * @param encoding the encoding to use on the files */ public void setEncoding( String encoding ) { m_encoding = encoding; } /** * Set the source file. * * @param file The new File value */ public void setFile( File file ) { m_src = file; } /** * Sets a file to be searched for property values. * * @param filename The new PropertyFile value */ public void setPropertyFile( File filename ) { m_propertyFile = filename; } /** * Request a summary * * @param summary true if you would like a summary logged of the replace * operation */ public void setSummary( boolean summary ) { m_summary = summary; } /** * Set the string token to replace. * * @param token The new Token value */ public void setToken( String token ) { createReplaceToken().addContent( token ); } /** * Set the string value to use as token replacement. * * @param value The new Value value */ public void setValue( String value ) { createReplaceValue().addContent( value ); } public Properties getProperties( File propertyFile ) throws TaskException { Properties properties = new Properties(); try { properties.load( new FileInputStream( propertyFile ) ); } catch( FileNotFoundException e ) { String message = "Property file (" + propertyFile.getPath() + ") not found."; throw new TaskException( message ); } catch( IOException e ) { String message = "Property file (" + propertyFile.getPath() + ") cannot be loaded."; throw new TaskException( message ); } return properties; } /** * Nested <replacetoken> element. * * @return Description of the Returned Value */ public NestedString createReplaceToken() { if( m_token == null ) { m_token = new NestedString(); } return m_token; } /** * Nested <replacevalue> element. * * @return Description of the Returned Value */ public NestedString createReplaceValue() { return m_value; } /** * Add nested <replacefilter> element. * * @return Description of the Returned Value */ public Replacefilter createReplacefilter() { Replacefilter filter = new Replacefilter( this ); m_replacefilters.add( filter ); return filter; } /** * Do the execution. * * @exception TaskException Description of Exception */ public void execute() throws TaskException { validateAttributes(); if( m_propertyFile != null ) { m_properties = getProperties( m_propertyFile ); } validateReplacefilters(); m_fileCount = 0; m_replaceCount = 0; if( m_src != null ) { processFile( m_src ); } if( m_dir != null ) { DirectoryScanner ds = super.getDirectoryScanner( m_dir ); String[] srcs = ds.getIncludedFiles(); for( int i = 0; i < srcs.length; i++ ) { File file = new File( m_dir, srcs[ i ] ); processFile( file ); } } if( m_summary ) { getLogger().info( "Replaced " + m_replaceCount + " occurrences in " + m_fileCount + " files." ); } } /** * Validate attributes provided for this task in .xml build file. * * @exception TaskException if any supplied attribute is invalid or any * mandatory attribute is missing */ public void validateAttributes() throws TaskException { if( m_src == null && m_dir == null ) { String message = "Either the file or the dir attribute " + "must be specified"; throw new TaskException( message ); } if( m_propertyFile != null && !m_propertyFile.exists() ) { String message = "Property file " + m_propertyFile.getPath() + " does not exist."; throw new TaskException( message ); } if( m_token == null && m_replacefilters.size() == 0 ) { String message = "Either token or a nested replacefilter " + "must be specified"; throw new TaskException( message ); } if( m_token != null && "".equals( m_token.getText() ) ) { String message = "The token attribute must not be an empty string."; throw new TaskException( message ); } } /** * Validate nested elements. * * @exception TaskException if any supplied attribute is invalid or any * mandatory attribute is missing */ public void validateReplacefilters() throws TaskException { for( int i = 0; i < m_replacefilters.size(); i++ ) { Replacefilter element = (Replacefilter)m_replacefilters.get( i ); element.validate(); } } /** * Perform the replacement on the given file. The replacement is performed * on a temporary file which then replaces the original file. * * @param src the source file * @exception TaskException Description of Exception */ private void processFile( File src ) throws TaskException { if( !src.exists() ) { throw new TaskException( "Replace: source file " + src.getPath() + " doesn't exist" ); } File temp = null; try { temp = File.createTempFile( "rep", ".tmp", src.getParentFile() ); } catch( IOException ioe ) { throw new TaskException( ioe.toString(), ioe ); } Reader reader = null; Writer writer = null; try { reader = m_encoding == null ? new FileReader( src ) : new InputStreamReader( new FileInputStream( src ), m_encoding ); writer = m_encoding == null ? new FileWriter( temp ) : new OutputStreamWriter( new FileOutputStream( temp ), m_encoding ); BufferedReader br = new BufferedReader( reader ); BufferedWriter bw = new BufferedWriter( writer ); // read the entire file into a StringBuffer // size of work buffer may be bigger than needed // when multibyte characters exist in the source file // but then again, it might be smaller than needed on // platforms like Windows where length can't be trusted int fileLengthInBytes = (int)( src.length() ); StringBuffer tmpBuf = new StringBuffer( fileLengthInBytes ); int readChar = 0; int totread = 0; while( true ) { readChar = br.read(); if( readChar < 0 ) { break; } tmpBuf.append( (char)readChar ); totread++; } // create a String so we can use indexOf String buf = tmpBuf.toString(); //Preserve original string (buf) so we can compare the result String newString = new String( buf ); if( m_token != null ) { // line separators in values and tokens are "\n" // in order to compare with the file contents, replace them // as needed final String val = stringReplace( m_value.getText(), "\n", StringUtil.LINE_SEPARATOR ); final String tok = stringReplace( m_token.getText(), "\n", StringUtil.LINE_SEPARATOR ); // for each found token, replace with value getLogger().debug( "Replacing in " + src.getPath() + ": " + m_token.getText() + " --> " + m_value.getText() ); newString = stringReplace( newString, tok, val ); } if( m_replacefilters.size() > 0 ) { newString = processReplacefilters( newString, src.getPath() ); } boolean changes = !newString.equals( buf ); if( changes ) { bw.write( newString, 0, newString.length() ); bw.flush(); } // cleanup bw.close(); writer = null; br.close(); reader = null; // If there were changes, move the new one to the old one; // otherwise, delete the new one if( changes ) { ++m_fileCount; src.delete(); temp.renameTo( src ); temp = null; } } catch( IOException ioe ) { throw new TaskException( "IOException in " + src + " - " + ioe.getClass().getName() + ":" + ioe.getMessage(), ioe ); } finally { if( reader != null ) { try { reader.close(); } catch( IOException e ) { } } if( writer != null ) { try { writer.close(); } catch( IOException e ) { } } if( temp != null ) { temp.delete(); } } } private String processReplacefilters( String buffer, String filename ) { String newString = new String( buffer ); for( int i = 0; i < m_replacefilters.size(); i++ ) { Replacefilter filter = (Replacefilter)m_replacefilters.get( i ); //for each found token, replace with value getLogger().debug( "Replacing in " + filename + ": " + filter.getToken() + " --> " + filter.getReplaceValue() ); newString = stringReplace( newString, filter.getToken(), filter.getReplaceValue() ); } return newString; } /** * Replace occurrences of str1 in string str with str2 * * @param str Description of Parameter * @param str1 Description of Parameter * @param str2 Description of Parameter * @return Description of the Returned Value */ private String stringReplace( String str, String str1, String str2 ) { StringBuffer ret = new StringBuffer(); int start = 0; int found = str.indexOf( str1 ); while( found >= 0 ) { // write everything up to the found str1 if( found > start ) { ret.append( str.substring( start, found ) ); } // write the replacement str2 if( str2 != null ) { ret.append( str2 ); } // search again start = found + str1.length(); found = str.indexOf( str1, start ); ++m_replaceCount; } // write the remaining characters if( str.length() > start ) { ret.append( str.substring( start, str.length() ) ); } return ret.toString(); } public NestedString getValue() { return m_value; } public File getPropertyFile() { return m_propertyFile; } public Properties getProperties() { return m_properties; } } 1.1 jakarta-ant/proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/text/Replacefilter.java Index: Replacefilter.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE.txt file. */ package org.apache.tools.ant.taskdefs.text; import org.apache.myrmidon.api.TaskException; public class Replacefilter { private String m_property; private String m_token; private String m_value; private Replace m_replace; public Replacefilter( Replace replace ) { m_replace = replace; } public void setProperty( final String property ) { this.m_property = property; } public void setToken( String token ) { this.m_token = token; } public void setValue( String value ) { this.m_value = value; } public String getProperty() { return m_property; } public String getReplaceValue() { if( m_property != null ) { return (String)m_replace.getProperties().getProperty( m_property ); } else if( m_value != null ) { return m_value; } else if( m_replace.getValue() != null ) { return m_replace.getValue().getText(); } else { //Default is empty string return ""; } } public String getToken() { return m_token; } public String getValue() { return m_value; } public void validate() throws TaskException { //Validate mandatory attributes if( m_token == null ) { String message = "token is a mandatory attribute " + "of replacefilter."; throw new TaskException( message ); } if( "".equals( m_token ) ) { String message = "The token attribute must not be an empty string."; throw new TaskException( message ); } //value and property are mutually exclusive attributes if( ( m_value != null ) && ( m_property != null ) ) { String message = "Either value or property " + "can be specified, but a replacefilter " + "element cannot have both."; throw new TaskException( message ); } if( ( m_property != null ) ) { //the property attribute must have access to a property file if( m_replace.getPropertyFile() == null ) { String message = "The replacefilter's property attribute " + "can only be used with the replacetask's propertyFile attribute."; throw new TaskException( message ); } //Make sure property exists in property file if( m_replace.getProperties() == null || m_replace.getProperties().getProperty( m_property ) == null ) { String message = "property \"" + m_property + "\" was not found in " + m_replace.getPropertyFile().getPath(); throw new TaskException( message ); } } } } -- To unsubscribe, e-mail: For additional commands, e-mail: