001/* 002 * The Kuali Financial System, a comprehensive financial management system for higher education. 003 * 004 * Copyright 2005-2014 The Kuali Foundation 005 * 006 * This program is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU Affero General Public License as 008 * published by the Free Software Foundation, either version 3 of the 009 * License, or (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU Affero General Public License for more details. 015 * 016 * You should have received a copy of the GNU Affero General Public License 017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 018 */ 019import java.io.BufferedReader; 020import java.io.BufferedWriter; 021import java.io.File; 022import java.io.FileReader; 023import java.io.FileWriter; 024import java.io.IOException; 025import java.io.StringReader; 026import java.util.ArrayList; 027import java.util.Collection; 028import java.util.List; 029 030import org.apache.commons.io.DirectoryWalker; 031import org.apache.commons.io.FileUtils; 032import org.apache.commons.io.filefilter.FileFilterUtils; 033import org.apache.commons.io.filefilter.HiddenFileFilter; 034import org.apache.commons.io.filefilter.IOFileFilter; 035 036public class LicenseHeaderUpdate { 037 038 public static final String AGPL_LICENSE_TEXT = "The Kuali Financial System, a comprehensive financial management system for higher education.\n" + 039 "\n" + 040 "Copyright 2005-2014 The Kuali Foundation\n" + 041 "\n" + 042 "This program is free software: you can redistribute it and/or modify\n" + 043 "it under the terms of the GNU Affero General Public License as\n" + 044 "published by the Free Software Foundation, either version 3 of the\n" + 045 "License, or (at your option) any later version.\n" + 046 "\n" + 047 "This program is distributed in the hope that it will be useful,\n" + 048 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + 049 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + 050 "GNU Affero General Public License for more details.\n" + 051 "\n" + 052 "You should have received a copy of the GNU Affero General Public License\n" + 053 "along with this program. If not, see <http://www.gnu.org/licenses/>."; 054 055 static final String LINE_SEPARATOR = System.getProperty("line.separator"); 056 057 private static final List<String> blacklistedFiles = new ArrayList<String>(); 058 059 /** 060 * 061 * @param args 062 */ 063 public static void main(String[] args) throws Exception { 064 setupBlackList(); 065 handleJavaStyleComments( args[0] ); 066 handleJSPStyleComments( args[0] ); 067 handleXMLStyleComments( args[0] ); 068 handlePropertyStyleComments( args[0] ); 069 handleSQLStyleComments( args[0] ); 070 } 071 072 public static void setupBlackList() { 073 blacklistedFiles.add("build"+File.separator+"project"+File.separator+"OJB-logging.properties"); 074 blacklistedFiles.add("build"+File.separator+"project"+File.separator+"OJB.properties"); 075 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"); 076 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"); 077 } 078 079 public static void handleJavaStyleComments( String baseDir ) throws Exception { 080 IOFileFilter sourceFileFilter = FileFilterUtils.orFileFilter( 081 FileFilterUtils.suffixFileFilter("java"), 082 FileFilterUtils.suffixFileFilter("js") ); 083 sourceFileFilter = FileFilterUtils.orFileFilter( 084 sourceFileFilter, 085 FileFilterUtils.suffixFileFilter("css") ); 086 sourceFileFilter = FileFilterUtils.orFileFilter( 087 sourceFileFilter, 088 FileFilterUtils.suffixFileFilter("groovy") ); 089 sourceFileFilter = FileFilterUtils.makeSVNAware(sourceFileFilter); 090 sourceFileFilter = FileFilterUtils.makeFileOnly(sourceFileFilter); 091 092 LicensableFileDirectoryWalker dw = new LicensableFileDirectoryWalker(sourceFileFilter, "/*", " * ", " */"); 093 Collection<String> results = dw.run( baseDir ); 094 System.out.println( results ); 095 } 096 097 public static void handleJSPStyleComments( String baseDir ) throws Exception { 098 IOFileFilter sourceFileFilter = FileFilterUtils.orFileFilter( 099 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}