View Javadoc
1   /*
2    * The Kuali Financial System, a comprehensive financial management system for higher education.
3    *
4    * Copyright 2005-2014 The Kuali Foundation
5    *
6    * This program is free software: you can redistribute it and/or modify
7    * it under the terms of the GNU Affero General Public License as
8    * published by the Free Software Foundation, either version 3 of the
9    * License, or (at your option) any later version.
10   *
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU Affero General Public License for more details.
15   *
16   * You should have received a copy of the GNU Affero General Public License
17   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18   */
19  import java.io.BufferedReader;
20  import java.io.BufferedWriter;
21  import java.io.File;
22  import java.io.FileReader;
23  import java.io.FileWriter;
24  import java.io.IOException;
25  import java.io.StringReader;
26  import java.util.ArrayList;
27  import java.util.Collection;
28  import java.util.List;
29  
30  import org.apache.commons.io.DirectoryWalker;
31  import org.apache.commons.io.FileUtils;
32  import org.apache.commons.io.filefilter.FileFilterUtils;
33  import org.apache.commons.io.filefilter.HiddenFileFilter;
34  import org.apache.commons.io.filefilter.IOFileFilter;
35  
36  public class LicenseHeaderUpdate {
37  
38      public static final String AGPL_LICENSE_TEXT = "The Kuali Financial System, a comprehensive financial management system for higher education.\n" +
39              "\n" +
40              "Copyright 2005-2014 The Kuali Foundation\n" +
41              "\n" +
42              "This program is free software: you can redistribute it and/or modify\n" +
43              "it under the terms of the GNU Affero General Public License as\n" +
44              "published by the Free Software Foundation, either version 3 of the\n" +
45              "License, or (at your option) any later version.\n" +
46              "\n" +
47              "This program is distributed in the hope that it will be useful,\n" +
48              "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" +
49              "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" +
50              "GNU Affero General Public License for more details.\n" +
51              "\n" +
52              "You should have received a copy of the GNU Affero General Public License\n" +
53              "along with this program.  If not, see <http://www.gnu.org/licenses/>.";
54  
55      static final String LINE_SEPARATOR = System.getProperty("line.separator");
56  
57      private static final List<String> blacklistedFiles = new ArrayList<String>();
58  
59      /**
60       *
61       * @param args
62       */
63      public static void main(String[] args) throws Exception {
64          setupBlackList();
65          handleJavaStyleComments( args[0] );
66          handleJSPStyleComments( args[0] );
67          handleXMLStyleComments( args[0] );
68          handlePropertyStyleComments( args[0] );
69          handleSQLStyleComments( args[0] );
70      }
71  
72      public static void setupBlackList() {
73          blacklistedFiles.add("build"+File.separator+"project"+File.separator+"OJB-logging.properties");
74          blacklistedFiles.add("build"+File.separator+"project"+File.separator+"OJB.properties");
75          blacklistedFiles.add("work"+File.separator+"db"+File.separator+"kfs-db"+File.separator+"db-impex"+File.separator+"impex"+File.separator+"src"+File.separator+"org"+File.separator+"kuali"+File.separator+"core"+File.separator+"db"+File.separator+"torque"+File.separator+"KualiDatabase.java");
76          blacklistedFiles.add("work"+File.separator+"src"+File.separator+"org"+File.separator+"springframework"+File.separator+"beans"+File.separator+"factory"+File.separator+"support"+File.separator+"DefaultListableBeanFactory.java");
77      }
78  
79      public static void handleJavaStyleComments( String baseDir ) throws Exception {
80          IOFileFilter sourceFileFilter = FileFilterUtils.orFileFilter(
81                  FileFilterUtils.suffixFileFilter("java"),
82                  FileFilterUtils.suffixFileFilter("js") );
83          sourceFileFilter = FileFilterUtils.orFileFilter(
84                  sourceFileFilter,
85                  FileFilterUtils.suffixFileFilter("css") );
86          sourceFileFilter = FileFilterUtils.orFileFilter(
87                  sourceFileFilter,
88                  FileFilterUtils.suffixFileFilter("groovy") );
89          sourceFileFilter = FileFilterUtils.makeSVNAware(sourceFileFilter);
90          sourceFileFilter = FileFilterUtils.makeFileOnly(sourceFileFilter);
91  
92          LicensableFileDirectoryWalker dw = new LicensableFileDirectoryWalker(sourceFileFilter, "/*", " * ", " */");
93          Collection<String> results = dw.run( baseDir );
94          System.out.println( results );
95      }
96  
97      public static void handleJSPStyleComments( String baseDir ) throws Exception {
98          IOFileFilter sourceFileFilter = FileFilterUtils.orFileFilter(
99                  FileFilterUtils.suffixFileFilter("jsp"),
100                 FileFilterUtils.suffixFileFilter("tag") );
101         sourceFileFilter = FileFilterUtils.orFileFilter(
102                 sourceFileFilter,
103                 FileFilterUtils.suffixFileFilter("inc") );
104         sourceFileFilter = FileFilterUtils.makeSVNAware(sourceFileFilter);
105         sourceFileFilter = FileFilterUtils.makeFileOnly(sourceFileFilter);
106 
107         LicensableFileDirectoryWalker dw = new LicensableFileDirectoryWalker(sourceFileFilter, "<%--", "   - ", "--%>");
108         Collection<String> results = dw.run( baseDir );
109         System.out.println( results );
110     }
111 
112     public static void handlePropertyStyleComments( String baseDir ) throws Exception {
113         IOFileFilter sourceFileFilter = FileFilterUtils.orFileFilter(
114                 FileFilterUtils.suffixFileFilter("properties"),
115                 FileFilterUtils.suffixFileFilter("cmd") );
116         sourceFileFilter = FileFilterUtils.orFileFilter(
117                 sourceFileFilter,
118                 FileFilterUtils.suffixFileFilter("sh") );
119         sourceFileFilter = FileFilterUtils.makeSVNAware(sourceFileFilter);
120         sourceFileFilter = FileFilterUtils.makeFileOnly(sourceFileFilter);
121 
122         LicensableFileDirectoryWalker dw = new LicensableFileDirectoryWalker(sourceFileFilter, "########################################", "# ", "########################################");
123         Collection<String> results = dw.run( baseDir );
124         System.out.println( results );
125     }
126 
127     public static void handleSQLStyleComments( String baseDir ) throws Exception {
128         IOFileFilter sourceFileFilter = FileFilterUtils.suffixFileFilter("sql");
129         sourceFileFilter = FileFilterUtils.makeSVNAware(sourceFileFilter);
130         sourceFileFilter = FileFilterUtils.makeFileOnly(sourceFileFilter);
131 
132         LicensableFileDirectoryWalker dw = new LicensableFileDirectoryWalker(sourceFileFilter, "--", "-- ", LINE_SEPARATOR);
133         Collection<String> results = dw.run( baseDir );
134         System.out.println( results );
135     }
136 
137     public static void handleXMLStyleComments( String baseDir ) throws Exception {
138         IOFileFilter sourceFileFilter = FileFilterUtils.orFileFilter(
139                 FileFilterUtils.suffixFileFilter("xml"),
140                 FileFilterUtils.suffixFileFilter("jrxml") );
141         sourceFileFilter = FileFilterUtils.orFileFilter(
142                 sourceFileFilter,
143                 FileFilterUtils.suffixFileFilter("html") );
144         sourceFileFilter = FileFilterUtils.orFileFilter(
145                 sourceFileFilter,
146                 FileFilterUtils.suffixFileFilter("htm") );
147         sourceFileFilter = FileFilterUtils.orFileFilter(
148                 sourceFileFilter,
149                 FileFilterUtils.suffixFileFilter("xsd") );
150         sourceFileFilter = FileFilterUtils.orFileFilter(
151                 sourceFileFilter,
152                 FileFilterUtils.suffixFileFilter("tld") );
153         sourceFileFilter = FileFilterUtils.makeSVNAware(sourceFileFilter);
154         sourceFileFilter = FileFilterUtils.makeFileOnly(sourceFileFilter);
155 
156         LicensableFileDirectoryWalker dw = new LicensableFileDirectoryWalker(sourceFileFilter, "<!--", "   - ", " -->");
157         Collection<String> results = dw.run( baseDir );
158         System.out.println( results );
159     }
160 
161     public static class LicensableFileDirectoryWalker extends DirectoryWalker {
162 
163         String firstLine;
164         String lastLine;
165         String linePrefix;
166 
167         public LicensableFileDirectoryWalker( IOFileFilter fileFilter, String firstLine, String linePrefix, String lastLine ) {
168             super(HiddenFileFilter.VISIBLE,fileFilter,100);
169             this.firstLine = firstLine;
170             this.linePrefix = linePrefix;
171             this.lastLine = lastLine;
172         }
173         @Override
174         protected void handleDirectoryStart(File directory, int depth, @SuppressWarnings("rawtypes") Collection results) throws IOException {
175             System.out.println( "Directory: " + directory.getAbsolutePath() );
176         }
177         @Override
178         protected boolean handleDirectory(File directory, int depth, Collection results) throws IOException {
179             if ( directory.getAbsolutePath().endsWith("WEB-INF"+File.separator+"classes") ) {
180                 return false;
181             }
182             if ( directory.getAbsolutePath().endsWith("test"+File.separator+"classes") ) {
183                 return false;
184             }
185             if ( directory.getAbsolutePath().endsWith("build"+File.separator+"tomcat") ) {
186                 return false;
187             }
188             if ( directory.getAbsolutePath().endsWith("build"+File.separator+"rice-datadictionary") ) {
189                 return false;
190             }
191             if ( directory.getAbsolutePath().endsWith("kr"+File.separator+"static"+File.separator+"help") ) {
192                 return false;
193             }
194             if ( directory.getName().equals("META-INF") ) {
195                 return false;
196             }
197             return true;
198         }
199         @Override
200         protected void handleFile(File file, int depth, @SuppressWarnings("rawtypes") Collection results) throws IOException {
201             if (isBlacklisted(file.getAbsolutePath())) {
202                 System.err.println( "Found blacklisted file, skipping file: " + file.getAbsolutePath() );
203                 results.add("FILE SKIPPED - BLACKLISTED: " + file.getAbsolutePath() );
204                 return;
205             }
206             System.out.println( "Handing File: " + file.getAbsolutePath() );
207             BufferedReader r = new BufferedReader(new FileReader( file ) );
208             String currentLine = null;
209             String savedFirstLine = null;
210             // check the initial line of the file
211             String line1 = r.readLine();
212             // if the file is empty, just skip
213             if ( line1 == null ) {
214                 results.add("FILE SKIPPED - EMPTY: " + file.getAbsolutePath() );
215                 return;
216             }
217             if ( line1.startsWith("<?") ) { // special hack for XML files
218                 savedFirstLine = line1;
219                 line1 = r.readLine();
220             }
221             if ( line1.trim().equals(firstLine.trim()) ) {
222                 // if found, skip until find a line containing the lastLine
223                 while ( (currentLine = r.readLine()) != null ) {
224                     // throw away the lines
225                     if ( currentLine.trim().equals(lastLine.trim()) ) {
226                         break;
227                     }
228                 }
229                 if ( currentLine == null ) {
230                     // we reached the end of the file before finding the end of the comment, ABORT!
231                     System.err.println( "Unable to find end of existing header section, skipping file: " + file.getAbsolutePath() );
232                     results.add("FILE SKIPPED - UNABLE TO FIND END OF HEADER: " + file.getAbsolutePath() );
233                     return;
234                 }
235             }
236             File outputFile = new File( file.getAbsolutePath() + "-out" );
237             BufferedWriter w = new BufferedWriter( new FileWriter( outputFile ) );
238             if ( savedFirstLine != null ) {
239                 w.write( savedFirstLine );
240                 w.write( LINE_SEPARATOR );
241             }
242             // now, write the new header file
243             w.write( firstLine );
244             w.write( LINE_SEPARATOR );
245             BufferedReader headerReader = new BufferedReader( new StringReader( AGPL_LICENSE_TEXT ) );
246             while ( (currentLine = headerReader.readLine()) != null ) {
247                 w.write( linePrefix );
248                 w.write( currentLine );
249                 w.write( LINE_SEPARATOR );
250             }
251             if ( lastLine.equals(LINE_SEPARATOR) ) { // special hack for SQL files
252                 w.write("--" + LINE_SEPARATOR);
253                 w.write( LINE_SEPARATOR );
254             } else {
255                 w.write( lastLine );
256                 w.write( LINE_SEPARATOR );
257             }
258             headerReader.close();
259             if ( !line1.trim().equals(firstLine.trim()) ) {
260                 w.write( line1 );
261                 w.write( LINE_SEPARATOR );
262             }
263 
264             while ( (currentLine = r.readLine()) != null ) {
265                 w.write(currentLine);
266                 w.write(LINE_SEPARATOR);
267             }
268             // delete the original file and replace with the completed output file
269             w.close();
270             r.close();
271             FileUtils.deleteQuietly(file);
272             FileUtils.moveFile(outputFile, file);
273         }
274         public Collection<String> run( String projectDir ) throws IOException {
275             Collection<String> results = new ArrayList<String>();
276             walk( new File( projectDir ), results );
277             return results;
278         }
279         protected boolean isBlacklisted(String file) {
280             for (String str : blacklistedFiles) {
281                 if (file.endsWith(str)) {
282                     return true;
283                 }
284             }
285             return false;
286         }
287     }
288 }