001: // This file is part of KeY - Integrated Deductive Software Design
002: // Copyright (C) 2001-2007 Universitaet Karlsruhe, Germany
003: // Universitaet Koblenz-Landau, Germany
004: // Chalmers University of Technology, Sweden
005: //
006: // The KeY system is protected by the GNU General Public License.
007: // See LICENSE.TXT for details.
008: //
009: //
010: //
011: //
012:
013: package de.uka.ilkd.key.util;
014:
015: /**
016: * Manages code of the KeY project, i.e. adds headers to the files and
017: * removes an old one, but should be useable in other projects.
018: *
019: */
020: import java.io.*;
021: import java.util.Vector;
022:
023: public class AddAHead {
024:
025: private static String[] endings = new String[] { "java", "gjava",
026: "", "html", "g", "jj", "prj", "key" };
027: private String[] commentsstart = new String[] { "//", "#", "#",
028: "<!--", "//", "//", ";;", "//" };
029: private String[] noendingFiles = new String[] { "Makefile" };
030: private String[] commentsend = new String[] { "", "", "", "-->",
031: "", "", "", "" };
032: private String[] notToRemove = new String[] { "#!/bin/sh",
033: "<!DOCTYPE HTML", ";; -*- Prcs -*-" };
034: private String[] header;
035:
036: private String[] oldHeader = null;
037:
038: private String copyright = "Copyright";
039: private int copyrightWithin = 10;
040: private File tmpFile = new File("TMP");
041:
042: private int[] countCode = initCounter();
043: private int[] countComment = initCounter();
044: private int[] countEmpty = initCounter();
045: private int[] countFile = initCounter();
046: private int[] countAddFile = initCounter();
047: private int[] countRemoveFile = initCounter();
048:
049: public AddAHead() {
050:
051: }
052:
053: public BufferedReader getBufferedReader(File file) {
054: try {
055: return new BufferedReader(new FileReader(file));
056: } catch (IOException e) {
057: return null;
058: }
059: }
060:
061: public static int[] initCounter() {
062: int[] result = new int[endings.length];
063: for (int i = 0; i < endings.length; i++) {
064: result[i] = 0;
065: }
066: return result;
067: }
068:
069: public String ending(String fn) {
070: int l = fn.lastIndexOf(".");
071: return (l >= 0) ? fn.substring(l + 1) : "";
072: }
073:
074: public boolean startsWithOne(String s0, String[] s) {
075: for (int i = 0; i < s.length; i++) {
076: if (s0.startsWith(s[i]))
077: return true;
078: }
079: return false;
080: }
081:
082: public int containsHeader(File f, int type) {
083: BufferedReader b = getBufferedReader(f);
084: int i = 0;
085: int hStart = -1;
086: int ohStart = -1;
087: boolean h = false;
088: boolean oh = false;
089: boolean readComment = false;
090: try {
091: while (true) {
092: String line = b.readLine();
093: if (line == null)
094: break;
095: if (commentsstart[type].equals("//")
096: && line.indexOf("/*") >= 0) {
097: readComment = true;
098: }
099: if ((line.indexOf(commentsstart[type]) >= 0 && line
100: .indexOf(commentsstart[type]) <= 5)
101: || readComment)
102: countComment[type]++;
103: else if (line.equals(""))
104: countEmpty[type]++;
105: else
106: countCode[type]++;
107: if (commentsstart[type].equals("//")
108: && line.indexOf("*/") >= 0) {
109: readComment = false;
110: }
111: if (h)
112: continue;
113: if (oh)
114: continue;
115: if (hStart > -1) {
116: if (line.equals(commentsstart[type]
117: + header[i - hStart] + commentsend[type])) {
118: if (i - hStart == header.length - 1)
119: h = true;
120: } else {
121: if (hStart > -1)
122: hStart = -1;
123: }
124: }
125: if (line.equals(commentsstart[type] + header[0]
126: + commentsend[type])
127: && hStart == -1)
128: hStart = i;
129: if (ohStart > -1) {
130: if (line.equals(commentsstart[type]
131: + oldHeader[i - ohStart]
132: + commentsend[type])) {
133: if (i - ohStart == oldHeader.length - 1)
134: oh = true;
135: } else {
136: if (ohStart > -1)
137: ohStart = -1;
138: }
139: }
140: if (oldHeader != null
141: && line.equals(commentsstart[type]
142: + oldHeader[0] + commentsend[type])
143: && ohStart == -1)
144: ohStart = i;
145:
146: i++;
147: }
148: b.close();
149: } catch (IOException e) {
150: Debug.out("Exception thrown by class AddAhead at IO");
151: }
152: if (h)
153: return 2;
154: if (oh)
155: return 1;
156: return 0;
157:
158: }
159:
160: public void addHeader(File f, int type) {
161: BufferedReader b = getBufferedReader(f);
162: try {
163: PrintWriter w = new PrintWriter(new BufferedWriter(
164: new FileWriter(tmpFile)));
165: String line = b.readLine();
166: if (line == null)
167: return;
168: while (startsWithOne(line, notToRemove)) {
169: w.println(line);
170: line = b.readLine();
171: }
172: for (int i = 0; i < header.length; i++) {
173: w.println(commentsstart[type] + header[i]
174: + commentsend[type]);
175: }
176: while (line != null) {
177: w.println(line);
178: line = b.readLine();
179: }
180: w.close();
181: b.close();
182: } catch (IOException e) {
183: Debug.out("Exception thrown by class AddAhead at IO");
184: }
185: tmpFile.renameTo(f);
186: }
187:
188: public void removeOldHeader(File f, int type) {
189: BufferedReader b = getBufferedReader(f);
190: try {
191: PrintWriter w = new PrintWriter(new BufferedWriter(
192: new FileWriter(tmpFile)));
193: String line;
194: int i = 0;
195: while ((line = b.readLine()) != null) {
196: if (line.equals(commentsstart[type] + oldHeader[0]
197: + commentsend[type])) {
198: String fline = line;
199: int hstart = i;
200: b.mark(80 * 10);
201: boolean oh = false;
202: while (!oh
203: && line != null
204: && line.equals(commentsstart[type]
205: + oldHeader[i - hstart]
206: + commentsend[type])) {
207: if (i - hstart == oldHeader.length - 1)
208: oh = true;
209: line = b.readLine();
210: i++;
211: }
212: if (!oh) {
213: b.reset();
214: line = fline;
215: }
216: }
217: if (line != null)
218: w.println(line);
219: i++;
220: }
221: w.close();
222: b.close();
223: } catch (IOException e) {
224: Debug.out("Exception thrown by class AddAhead at IO");
225: }
226: tmpFile.renameTo(f);
227: }
228:
229: public void handleFile(File f) {
230: for (int i = 0; i < endings.length; i++) {
231: if (ending(f.getName()).equals(endings[i])) {
232: if (endings[i].equals("")) {
233: boolean ok = false;
234: for (int j = 0; j < noendingFiles.length; j++) {
235: if (noendingFiles[j].equals(f.getName()))
236: ok = true;
237: }
238: if (!ok)
239: return;
240: }
241: countFile[i]++;
242: int ch = containsHeader(f, i);
243: if (ch == 0) {
244: addHeader(f, i);
245: countAddFile[i]++;
246: } else if (ch == 1) {
247: removeOldHeader(f, i);
248: addHeader(f, i);
249: countAddFile[i]++;
250: countRemoveFile[i]++;
251: }
252: }
253: }
254: }
255:
256: public void visitFile(File currentFile) {
257:
258: if (currentFile.isDirectory()) {
259: String[] fileList = currentFile.list();
260: for (int i = 0; i < fileList.length; i++) {
261: visitFile(new File(currentFile.getPath()
262: + File.separator + fileList[i]));
263: }
264: } else {
265: if (currentFile.isFile())
266: handleFile(currentFile);
267: }
268: }
269:
270: public String summary(String ending, int countFile,
271: int countRemoveFile, int countAddFile, int countCode,
272: int countComment, int countEmpty) {
273: int total = countCode + countComment + countEmpty;
274: return "*** " + countFile + " " + ending
275: + " *** \n The old header was removed in "
276: + countRemoveFile
277: + " files.\n The new header was added to "
278: + countAddFile + " files.\n The files contained "
279: + countCode + " lines of code, " + countComment
280: + " lines of comments, and " + countEmpty
281: + " empty lines.\n Sum of lines: " + total + ".\n";
282: }
283:
284: private static int sum(int[] is) {
285: int result = 0;
286: for (int i = 0; i < is.length; i++) {
287: result = result + is[i];
288: }
289: return result;
290: }
291:
292: public String statistics() {
293: String s = "";
294: for (int i = 0; i < endings.length; i++) {
295: s = s
296: + summary("files ending with ." + endings[i],
297: countFile[i], countRemoveFile[i],
298: countAddFile[i], countCode[i],
299: countComment[i], countEmpty[i]);
300: }
301: s = s
302: + summary("files altogether", sum(countFile),
303: sum(countRemoveFile), sum(countAddFile),
304: sum(countCode), sum(countComment),
305: sum(countEmpty));
306: return s;
307: }
308:
309: public void readHeader(String f) {
310: header = readLines(f);
311: }
312:
313: public String[] readLines(String f) {
314: File file = new File(f);
315: BufferedReader b = getBufferedReader(file);
316: Vector v = new Vector();
317: String l;
318: try {
319: while ((l = b.readLine()) != null) {
320: v.add(l);
321: }
322: b.close();
323: } catch (IOException e) {
324: System.out.println(e);
325: }
326: String[] result = new String[v.size()];
327: for (int i = 0; i < result.length; i++) {
328: result[i] = (String) v.elementAt(i);
329: }
330: return result;
331: }
332:
333: public void readOldHeader(String f) {
334: oldHeader = readLines(f);
335: }
336:
337: /**
338: * searches files for old and new headers. If an old header is found,
339: * the new one is inserted instead. If a new one is found, nothing
340: * happens. Some statistics is finally printed. Comments signs are
341: * used as in the commentsstart, commentsend arrays. Lines in
342: * notToRemove are skipped and the header is inserted after them.
343: *
344: * @param args First parameter contains the file to start from. If it
345: * is a directory all files below that directory are
346: * considered. Second parameter is a String describing the file where
347: * the new header can be found. This file should be text without any
348: * comment characters. The Third parameter is the filename of the old
349: * header that is to be replaced by the new header. The third one is
350: * optional.
351: *
352: */
353: public static void main(String args[]) {
354: AddAHead cm = (new AddAHead());
355: System.out
356: .println("AddAHead - adding headers to files in KeY.");
357: System.out.println("ABSOLUTELY NO WARRANTY.\n");
358: if (args.length < 2) {
359: System.out
360: .println("Usage: java AddAHead start header [oldheader]");
361: System.out
362: .println(" adds headers (license text) to files or "
363: + "all files in directory.\n");
364: System.out
365: .println("where start is directory or file to look at "
366: + "license;");
367: System.out
368: .println(" header is text to use as header;");
369: System.out
370: .println(" oldheader is header that is to be"
371: + " replaced.");
372: return;
373: }
374: cm.readHeader(args[1]);
375: if (args.length > 2)
376: cm.readOldHeader(args[2]);
377: cm.visitFile(new File(args[0]));
378: System.out.println(cm.statistics());
379: }
380: }
|