View Javadoc

1   package com.imcode.ant.tasks;
2   
3   import java.io.*;
4   import java.util.*;
5   
6   import org.apache.tools.ant.*;
7   import org.apache.tools.ant.types.*;
8   
9   public class Cat extends Task {
10  
11      private File destFile = null; // the destination file
12      private String orderBy = null;
13      private boolean filtering = false;
14      private boolean append = false;
15      private int verbosity = Project.MSG_VERBOSE;
16      private boolean forceOverwrite = false;
17  
18      private Vector filesets = new Vector();
19      private Vector filterSets = new Vector();
20  
21      private String ORDER_BY_PATH = "path";
22  
23      private final static int BUFFER_SIZE = 32768;
24  
25      /***
26       * Set the value of append.
27       * 
28       * @param v Value to assign to append.
29       */
30      public void setAppend( boolean v ) {
31          this.append = v;
32      }
33  
34      /***
35       * Sets the value of destFile
36       * 
37       * @param argDestFile Value to assign to this.destFile
38       */
39      public void setDestFile( File argDestFile ) {
40          this.destFile = argDestFile;
41      }
42  
43      /***
44       * Sets the value of orderBy
45       * 
46       * @param argOrderBy Value to assign to this.orderBy
47       */
48      public void setOrderBy( String argOrderBy ) {
49          this.orderBy = argOrderBy;
50      }
51  
52      /***
53       * Adds a set of files (nested fileset attribute).
54       */
55      public void addFileset( FileSet set ) {
56          filesets.addElement( set );
57      }
58  
59      /***
60       * Used to force listing of all names of copied files.
61       */
62      public void setVerbose( boolean verbose ) {
63          if ( verbose ) {
64              this.verbosity = Project.MSG_INFO;
65          } else {
66              this.verbosity = Project.MSG_VERBOSE;
67          }
68      }
69  
70      /***
71       * Sets filtering.
72       */
73      public void setFiltering( boolean filtering ) {
74          this.filtering = filtering;
75      }
76  
77      /***
78       * Overwrite any existing destination file(s).
79       */
80      public void setOverwrite( boolean overwrite ) {
81          this.forceOverwrite = overwrite;
82      }
83  
84      /***
85       * Create a nested filterset
86       */
87      public FilterSet createFilterSet() {
88          FilterSet filterSet = new FilterSet();
89          filterSets.addElement( filterSet );
90          return filterSet;
91      }
92  
93      public void execute() throws BuildException {
94          validateAttributes();
95          doFileOperations();
96      }
97  
98      /***
99       * Make sure all attributes are correct. *
100      */
101     private void validateAttributes() {
102         if ( filesets.size() == 0 ) {
103             throw new BuildException( "Specify at least one fileset." );
104         }
105 
106         if ( destFile == null ) {
107             throw new BuildException( "Specify a destfile." );
108         }
109 
110         if ( orderBy != null && !ORDER_BY_PATH.equalsIgnoreCase( orderBy ) ) {
111             throw new BuildException( "Specify a valid orderby ('path'), or none." );
112         }
113     }
114 
115     /***
116      * Do whatever is necessary to open the destination file. *
117      */
118     private OutputStream openOutputStream() throws IOException {
119         File parent = new File( destFile.getParent() );
120         if ( !parent.exists() ) {
121             if ( !parent.mkdirs() ) {
122                 log( "Unable to create directory " + parent.getAbsolutePath(), Project.MSG_ERR );
123             } else {
124                 log( "Created directory " + parent.getAbsolutePath(), verbosity );
125             }
126         }
127 
128         return new FileOutputStream( destFile.getPath(), append );
129 
130     }
131 
132     /***
133      * Do all fileoperations. *
134      */
135     private void doFileOperations() {
136         try {
137 
138             List srcFiles = handleFileSets();
139 
140             if ( srcFiles == null ) {
141                 return;
142             }
143 
144             FilterSetCollection filters = handleFilterSets();
145 
146             log( "Concatenating " + srcFiles.size() + ( srcFiles.size() == 1
147                                                         ? " file to "
148                                                         : " files to " ) + destFile.getAbsolutePath() );
149 
150             catFiles( srcFiles, filters );
151 
152         } catch ( IOException ex ) {
153             throw new BuildException( ex );
154         }
155     }
156 
157     /***
158      * Deal with the filesets *
159      */
160     private List handleFileSets() {
161         List srcFiles = new Vector();
162         boolean foundNewer = false;
163 
164         for ( Iterator filesetsIterator = filesets.iterator(); filesetsIterator.hasNext(); ) {  // for each fileset
165             FileSet fs = (FileSet)filesetsIterator.next();
166             DirectoryScanner ds = fs.getDirectoryScanner( project );
167             File baseDir = fs.getDir( project );
168 
169             // get all files in this fileset
170             String[] srcFilesArray = ds.getIncludedFiles();
171 
172             // sort by path if requested
173             if ( ORDER_BY_PATH.equalsIgnoreCase( orderBy ) ) {
174                 Arrays.sort( srcFilesArray );
175             }
176 
177             long destModified = destFile.lastModified();
178 
179             // add all source files to vector
180             for ( int j = 0; j < srcFilesArray.length; ++j ) {
181                 File srcFile = new File( baseDir, srcFilesArray[j] );
182                 if ( srcFile.equals( destFile ) ) {
183                     log( "Skipping self-concatenation of " + srcFile, verbosity );
184                 } else {
185                     // See if we can find a sourcefile that is newer than the destination
186                     if ( !foundNewer && srcFile.lastModified() > destModified ) {
187                         foundNewer = true;
188                     }
189                     srcFiles.add( srcFile );
190                 }
191             }
192         }
193 
194         // If we didn't find any newer sourcefiles, then forget it.
195         if ( !forceOverwrite && !foundNewer ) {
196             srcFiles = null;
197         }
198 
199         return srcFiles;
200     }
201 
202     /***
203      * Handle the filtersets. *
204      */
205     private FilterSetCollection handleFilterSets() {
206         // handle filters
207         FilterSetCollection executionFilters = new FilterSetCollection();
208         if ( filtering ) {
209             executionFilters.addFilterSet( project.getGlobalFilterSet() );
210         }
211         for ( Enumeration filterEnum = filterSets.elements(); filterEnum.hasMoreElements(); ) {
212             executionFilters.addFilterSet( (FilterSet)filterEnum.nextElement() );
213         }
214         return executionFilters;
215     }
216 
217     /***
218      * Cat through all files  *
219      */
220     private void catFiles( List srcFiles, FilterSetCollection filters ) throws IOException {
221         OutputStream out = openOutputStream();
222 
223         // do actual concatenation
224         for ( Iterator srcFilesIterator = srcFiles.iterator(); srcFilesIterator.hasNext(); ) {
225 
226             File srcFile = (File)srcFilesIterator.next();
227             log( "Concatenating " + srcFile + " to " + destFile, verbosity );
228 
229             FileInputStream in = new FileInputStream( srcFile );
230             catStream( in, out, filters );
231             in.close();
232         }
233         out.close();
234     }
235 
236     /***
237      * Cat one file/stream *
238      */
239     private void catStream( InputStream in, OutputStream out, FilterSetCollection filters ) throws IOException {
240         if ( filters != null && filters.hasFilters() ) {
241 
242             BufferedReader input = new BufferedReader( new InputStreamReader( in ) );
243             BufferedWriter output = new BufferedWriter( new OutputStreamWriter( out ) );
244 
245             for ( String newline, line = input.readLine(); line != null; line = input.readLine() ) {
246                 if ( line.length() == 0 ) {
247                     output.newLine();
248                 } else {
249                     newline = filters.replaceTokens( line );
250                     output.write( newline );
251                     output.newLine();
252                 }
253             }
254             output.flush();
255 
256         } else {
257 
258             int read;
259             byte[] buffer = new byte[BUFFER_SIZE];
260             while ( -1 != ( read = in.read( buffer, 0, BUFFER_SIZE ) ) ) {
261                 out.write( buffer, 0, read );
262             }
263 
264         }
265     }
266 }