001: /*
002: * Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
003: * (license2)
004: * Initial Developer: H2 Group
005: */
006: package org.h2.tools.code;
007:
008: import java.io.ByteArrayOutputStream;
009: import java.io.File;
010: import java.io.RandomAccessFile;
011:
012: import org.h2.util.ByteUtils;
013:
014: /**
015: * This tool checks that source code files only contain the allowed set of
016: * characters, and that the copyright license is included in each file. It also
017: * removes trailing spaces.
018: */
019: public class CheckTextFiles {
020: public static void main(String[] args) throws Exception {
021: new CheckTextFiles().run();
022: }
023:
024: String[] suffixCheck = new String[] { "html", "jsp", "js", "css",
025: "bat", "nsi", "java", "txt", "properties", "sql", "xml",
026: "csv", "Driver" };
027: String[] suffixIgnore = new String[] { "gif", "png", "odg", "ico",
028: "sxd", "layout", "res", "win", "jar", "task" };
029: boolean failOnError;
030: boolean allowTab, allowCR = true, allowTrailingSpaces = true;
031: int spacesPerTab = 4;
032: boolean autoFix = true;
033: boolean useCRLF = true;
034: // must contain "+" otherwise this here counts as well
035: String copyrightLicense = "Copyright 2004-2008 H2 Group. "
036: + "Licensed under the H2 License, Version 1.0";
037: String[] suffixIgnoreLicense = new String[] { "bat", "nsi", "txt",
038: "properties", "xml", "java.sql.Driver", "task" };
039: boolean hasError;
040:
041: void run() throws Exception {
042: System.out.println(getClass().getName());
043: String baseDir = "src";
044: check(new File(baseDir));
045: if (hasError) {
046: throw new Exception("Errors found");
047: }
048: }
049:
050: private void check(File file) throws Exception {
051: String name = file.getName();
052: if (file.isDirectory()) {
053: if (name.equals("CVS") || name.equals(".svn")) {
054: return;
055: }
056: File[] list = file.listFiles();
057: for (int i = 0; i < list.length; i++) {
058: check(list[i]);
059: }
060: } else {
061: String suffix = "";
062: int lastDot = name.lastIndexOf('.');
063: if (lastDot >= 0) {
064: suffix = name.substring(lastDot + 1);
065: }
066: boolean check = false, ignore = false;
067: for (int i = 0; i < suffixCheck.length; i++) {
068: if (suffix.equals(suffixCheck[i])) {
069: check = true;
070: }
071: }
072: // if (name.endsWith(".html") && name.indexOf("_ja") > 0) {
073: // int todoRemoveJapaneseFiles;
074: // // Japanese html files are UTF-8 at this time
075: // check = false;
076: // ignore = true;
077: // }
078: if (name.endsWith(".utf8.txt")) {
079: check = false;
080: ignore = true;
081: }
082: for (int i = 0; i < suffixIgnore.length; i++) {
083: if (suffix.equals(suffixIgnore[i])) {
084: ignore = true;
085: }
086: }
087: boolean checkLicense = true;
088: for (int i = 0; i < suffixIgnoreLicense.length; i++) {
089: String ig = suffixIgnoreLicense[i];
090: if (suffix.equals(ig) || name.endsWith(ig)) {
091: checkLicense = false;
092: break;
093: }
094: }
095: if (ignore == check) {
096: throw new Error("Unknown suffix: " + suffix
097: + " for file: " + name);
098: }
099: if (check) {
100: checkOrFixFile(file, autoFix, checkLicense);
101: }
102: }
103: }
104:
105: public void checkOrFixFile(File file, boolean fix,
106: boolean checkLicense) throws Exception {
107: RandomAccessFile in = new RandomAccessFile(file, "r");
108: byte[] data = new byte[(int) file.length()];
109: ByteArrayOutputStream out = fix ? new ByteArrayOutputStream()
110: : null;
111: in.readFully(data);
112: in.close();
113: if (checkLicense) {
114: if (data.length > copyrightLicense.length()) {
115: // don't check tiny files
116: String text = new String(data);
117: if (text.indexOf(copyrightLicense) < 0) {
118: fail(file, "license is missing", 0);
119: }
120: if (text.indexOf(" " + "//#") > 0) {
121: fail(file, "unexpected space,//#", 0);
122: }
123: if (text.indexOf(" " + "#ifdef") > 0) {
124: fail(file, "unexpected space,#if", 0);
125: }
126: if (text.indexOf(" " + "#endif") > 0) {
127: fail(file, "unexpected space,#endif", 0);
128: }
129: }
130: }
131: int line = 1;
132: boolean lastWasWhitespace = false;
133: for (int i = 0; i < data.length; i++) {
134: char ch = (char) (data[i] & 0xff);
135: if (ch > 127) {
136: fail(file, "contains character " + ch, line);
137: return;
138: } else if (ch < 32) {
139: if (ch == '\n') {
140: if (lastWasWhitespace && !allowTrailingSpaces) {
141: fail(file, "contains trailing white space",
142: line);
143: return;
144: }
145: if (fix) {
146: if (useCRLF) {
147: out.write('\r');
148: }
149: out.write(ch);
150: }
151: lastWasWhitespace = false;
152: line++;
153: } else if (ch == '\r') {
154: if (!allowCR) {
155: fail(file, "contains CR", line);
156: return;
157: }
158: if (lastWasWhitespace && !allowTrailingSpaces) {
159: fail(file, "contains trailing white space",
160: line);
161: return;
162: }
163: lastWasWhitespace = false;
164: // ok
165: } else if (ch == '\t') {
166: if (fix) {
167: for (int j = 0; j < spacesPerTab; j++) {
168: out.write(' ');
169: }
170: } else {
171: if (!allowTab) {
172: fail(file, "contains TAB", line);
173: return;
174: }
175: }
176: lastWasWhitespace = true;
177: // ok
178: } else {
179: fail(file, "contains character " + (int) ch, line);
180: return;
181: }
182: } else {
183: if (fix) {
184: out.write(ch);
185: }
186: lastWasWhitespace = Character.isWhitespace(ch);
187: }
188: }
189: if (lastWasWhitespace && !allowTrailingSpaces) {
190: fail(file, "contains trailing white space at the very end",
191: line);
192: return;
193: }
194: if (fix) {
195: byte[] changed = out.toByteArray();
196: if (ByteUtils.compareNotNull(data, changed) != 0) {
197: RandomAccessFile f = new RandomAccessFile(file, "rw");
198: f.write(changed);
199: f.setLength(changed.length);
200: f.close();
201: System.out.println("CHANGED: File " + file.getName());
202: }
203: }
204: }
205:
206: private void fail(File file, String error, int line) {
207: if (line <= 0) {
208: line = 1;
209: }
210: String name = file.getAbsolutePath();
211: int idx = name.lastIndexOf(File.separatorChar);
212: if (idx >= 0) {
213: name = name.replace(File.separatorChar, '.');
214: name = name + "(" + name.substring(idx + 1) + ":" + line
215: + ")";
216: idx = name.indexOf("org.");
217: if (idx > 0) {
218: name = name.substring(idx);
219: }
220: }
221: System.out.println("FAIL at " + name + " " + error + " "
222: + file.getAbsolutePath());
223: hasError = true;
224: if (failOnError) {
225: throw new Error("FAIL");
226: }
227: }
228:
229: }
|