1 /**
2  * The utillib library.
3  * More information is available at http://www.jinchess.com/.
4  * Copyright (C) 2002 Alexander Maryanovsky.
5  * All rights reserved.
6  *
7  * The utillib library is free software; you can redistribute
8  * it and/or modify it under the terms of the GNU Lesser General Public License
9  * as published by the Free Software Foundation; either version 2 of the
10  * License, or (at your option) any later version.
11  *
12  * The utillib library is distributed in the hope that it will
13  * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with utillib library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21 
22 package free.util;
23 
24 import java.io.*;
25 
26 
27 /**
28  * A commandline utility application which adds text taken from a given file,
29  * and adds it to the beginning of all files with the given extension in a given
30  * directory. This is useful for adding license text to source code files.
31  * The modifying process of a single file includes renaming it to a file with
32  * the name of the original file, ".tmp" added to it, then creating a new file
33  * with the name of the original file, writing license information into the new
34  * file, writing the contents of the ".tmp" file into the new file and only then
35  * deleting the ".tmp" file. If at any point an I/O error occurrs, the utility
36  * terminates immediately. This ensures that at all times, either the original
37  * file or the ".tmp" file exist, preventing possible data loss.
38  */
39 
40 public class ApplyLicense{
41 
42 
43   /**
44    * The main method, duh.
45    */
46 
main(String [] args)47   public static void main(String [] args){
48     if (args.length<3){
49       if (args.length!=0)
50         System.out.println("Not enough arguments.");
51       printUsage();
52       System.exit(0);
53     }
54 
55     boolean recurse = false;
56     boolean undo = false;
57     String backupDirName = null;
58 
59     int argIndex = 0;
60     while (argIndex<args.length-3){
61       String arg = args[argIndex];
62       if (arg.equals("-r"))
63         recurse = true;
64       else if (arg.equals("-b"))
65         backupDirName = args[++argIndex];
66       else if (arg.equals("-u"))
67         undo = true;
68 
69       argIndex++;
70     }
71 
72     if (argIndex>args.length-3){
73       System.out.println("Not enough arguments");
74       printUsage();
75       System.exit(0);
76     }
77 
78     String licenseFilename = args[args.length-3];
79     String extension = args[args.length-2];
80     String dirName = args[args.length-1];
81 
82     File backupDir = (backupDirName==null ? null : new File(backupDirName));
83     File licenseFile = new File(licenseFilename);
84     File dir = new File(dirName);
85 
86     if (!licenseFile.exists()){
87       System.out.println("No such file: "+licenseFilename);
88       System.exit(0);
89     }
90 
91     if (!dir.exists()){
92       System.out.println("No such directory: "+dirName);
93       System.exit(0);
94     }
95 
96     if (!dir.isDirectory()){
97       System.out.println(dirName+" is a file, not a directory");
98       System.exit(0);
99     }
100 
101     if (backupDir != null){
102       if (!backupDir.exists()){
103         System.out.print("Creating backup directory "+backupDirName+" ");
104         if (!backupDir.mkdirs()){
105           System.out.println("Unable to create backup directory "+backupDirName);
106           System.exit(0);
107         }
108         System.out.println("done");
109       }
110       try{
111         System.out.print("Backing up files in "+backupDir.getCanonicalPath()+" ");
112         IOUtilities.copyDir(dir, backupDir, recurse);
113         System.out.println("done");
114       } catch (IOException e){
115           System.out.println("Unable to backup files into "+backupDirName);
116           e.printStackTrace();
117           System.exit(0);
118         }
119     }
120 
121     try{
122       String license = IOUtilities.loadTextFile(licenseFile);
123       if (undo)
124         removeLicense(license, new ExtensionFilenameFilter("."+extension), dir, recurse);
125       else
126         applyLicense(license, new ExtensionFilenameFilter("."+extension), dir, recurse);
127     } catch (IOException e){
128         e.printStackTrace();
129         System.exit(0);
130       }
131   }
132 
133 
134 
135 
136   /**
137    * Prints usage information to the standard output stream.
138    * Here is what this method prints:
139    * <PRE>
140    *
141    * ApplyLicense Utility
142    * Copyright (C) 2001 Alexander Maryanovsky
143    *
144    * Use: java free.util.ApplyLicense [-r][-b backupDir] licenseFile extension dir
145    *
146    * -r apply recursively into subdirectories
147    * -b backupDir    Backup files into the given directory before applying license
148    *
149    * Version 1.00 - 05 Oct. 2001
150    * </PRE>
151    */
152 
printUsage()153   private static void printUsage(){
154     System.out.println();
155     System.out.println("ApplyLicense Utility");
156     System.out.println("Copyright (C) 2001 Alexander Maryanovsky");
157     System.out.println();
158     System.out.println("Use: java free.util.ApplyLicense [-r][-b backupDir] licenseFile extension dir");
159     System.out.println();
160     System.out.println("-r              Apply recursively into subdirectories");
161     System.out.println("-u              Undo applying the license");
162     System.out.println("-b backupDir    Backup files into the given directory before applying license");
163     System.out.println();
164     System.out.println("Version 1.00 - 05 Oct. 2001");
165   }
166 
167 
168 
169 
170   /**
171    * Adds the given license string to the beginning of every file in the given
172    * directory, optionally recursing into subdirectories, which passes the given
173    * FilenameFilter.
174    *
175    * @throws IOException If an I/O error occurs during the processing of the
176    * file(s).
177    */
178 
applyLicense(String license, FilenameFilter filter, File dir, boolean recurse)179   public static void applyLicense(String license, FilenameFilter filter, File dir, boolean recurse) throws IOException{
180     if (!dir.exists())
181       throw new IllegalArgumentException("The directory "+dir+" does not exist");
182 
183     if (!dir.isDirectory())
184       throw new IllegalArgumentException(dir.toString()+" is a file, not a directory");
185 
186     String [] filenames = dir.list();
187     for (int i = 0; i < filenames.length; i++){
188       String filename = filenames[i];
189       File file = new File(dir, filename);
190       if (file.isDirectory()){
191         if (recurse)
192           applyLicense(license, filter, file, true);
193       }
194       else if (filter.accept(dir, filename)){
195         System.out.print("Prepending license text to: "+file);
196         prependLicense(license, file);
197         System.out.println(" done");
198       }
199     }
200   }
201 
202 
203 
204 
205   /**
206    * Prepends the given text to the given file.
207    */
208 
prependLicense(String license, File file)209   private static void prependLicense(String license, File file) throws IOException{
210     File tmpFile = new File(file.getAbsolutePath()+".tmp");
211     if (!file.renameTo(tmpFile))
212       throw new IOException("Unable to rename "+file+" into "+tmpFile);
213 
214     OutputStream out = null;
215     InputStream in = null;
216 
217     try{
218       out = new FileOutputStream(file);
219       Writer writer = new BufferedWriter(new OutputStreamWriter(out));
220       writer.write(license);
221       writer.flush();
222       in = new FileInputStream(tmpFile);
223       IOUtilities.pump(in, out);
224     } finally{
225         if (in != null)
226           in.close();
227         if (out != null)
228           out.close();
229       }
230     if (!tmpFile.delete())
231       throw new IOException("Unable to delete "+tmpFile);
232   }
233 
234 
235 
236 
237 
238   /**
239    * Removes the given license string from the beginning of every file in the
240    * given directory, optionally recursing into subdirectories, which passes
241    * the given FilenameFilter.
242    *
243    * @throws IOException If an I/O error occurs during the processing of the
244    * file(s).
245    */
246 
removeLicense(String license, FilenameFilter filter, File dir, boolean recurse)247   public static void removeLicense(String license, FilenameFilter filter, File dir, boolean recurse) throws IOException{
248     if (!dir.exists())
249       throw new IllegalArgumentException("The directory "+dir+" does not exist");
250 
251     if (!dir.isDirectory())
252       throw new IllegalArgumentException(dir.toString()+" is a file, not a directory");
253 
254     String [] filenames = dir.list();
255     for (int i = 0; i < filenames.length; i++){
256       String filename = filenames[i];
257       File file = new File(dir, filename);
258       if (file.isDirectory()){
259         if (recurse)
260           removeLicense(license, filter, file, true);
261       }
262       else if (filter.accept(dir, filename)){
263         System.out.print("Removing license text from: "+file);
264         deleteLicense(license, file);
265         System.out.println(" done");
266       }
267     }
268   }
269 
270 
271 
272 
273   /**
274    * Prepends the specified text from the beginning of the given file. Returns
275    * <code>true</code> if the file indeed started with the specified text,
276    * false otherwise.
277    */
278 
deleteLicense(String license, File file)279   private static boolean deleteLicense(String license, File file) throws IOException{
280     File tmpFile = new File(file.getAbsolutePath()+".tmp");
281     if (!file.renameTo(tmpFile))
282       throw new IOException("Unable to rename "+file+" into "+tmpFile);
283 
284     OutputStream out = null;
285     InputStream in = null;
286 
287     try{
288       in = new FileInputStream(tmpFile);
289       int i = 0, b;
290       while (i < license.length()){
291         b = in.read();
292         if ((b==-1) || ((byte)b != license.charAt(i++))){
293           in.close();
294           in = null;
295           if (!tmpFile.renameTo(file))
296             throw new IOException("Unable to rename "+tmpFile+" into "+file);
297           return false;
298         }
299       }
300       out = new FileOutputStream(file);
301       IOUtilities.pump(in, out);
302     } finally{
303         if (in != null)
304           in.close();
305         if (out != null)
306           out.close();
307       }
308     if (!tmpFile.delete())
309       throw new IOException("Unable to delete "+tmpFile);
310 
311     return true;
312   }
313 
314 
315 
316 }
317