You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Checklics.java 20KB

21 years ago
21 years ago
21 years ago
21 years ago
15 years ago
21 years ago
15 years ago
21 years ago
15 years ago
15 years ago
15 years ago
21 years ago
15 years ago
21 years ago
21 years ago
15 years ago
21 years ago
15 years ago
21 years ago
15 years ago
15 years ago
21 years ago
21 years ago
15 years ago
21 years ago
15 years ago
21 years ago
15 years ago
21 years ago
15 years ago
21 years ago
6 years ago
21 years ago
15 years ago
21 years ago
15 years ago
6 years ago
15 years ago
6 years ago
15 years ago
6 years ago
15 years ago
6 years ago
21 years ago
15 years ago
21 years ago
15 years ago
21 years ago
21 years ago
21 years ago
15 years ago
21 years ago
6 years ago
21 years ago
15 years ago
21 years ago
15 years ago
21 years ago
15 years ago
21 years ago
15 years ago
21 years ago
6 years ago
21 years ago
15 years ago
21 years ago
15 years ago
21 years ago
15 years ago
21 years ago
15 years ago
15 years ago
15 years ago
6 years ago
15 years ago
21 years ago
15 years ago
15 years ago
15 years ago
21 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/epl-v10.html
  8. *
  9. * Contributors:
  10. * Xerox/PARC initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.internal.tools.ant.taskdefs;
  13. import java.io.BufferedReader;
  14. import java.io.File;
  15. import java.io.FileReader;
  16. import java.io.FileWriter;
  17. import java.io.IOException;
  18. import java.io.PrintStream;
  19. import java.io.PrintWriter;
  20. import java.util.ArrayList;
  21. import java.util.Collections;
  22. import java.util.Hashtable;
  23. import java.util.Iterator;
  24. import java.util.List;
  25. import java.util.Map;
  26. import org.apache.tools.ant.BuildException;
  27. import org.apache.tools.ant.Project;
  28. import org.apache.tools.ant.taskdefs.MatchingTask;
  29. import org.apache.tools.ant.types.Path;
  30. import org.apache.tools.ant.types.Reference;
  31. /**
  32. * Check that included .java files contain license and copyright strings for MPL 1.0 (default), Apache, or CPL. Use list="true" to
  33. * get a list of known license variants {license}-{copyrightHolder} todo reimplement with regexp and jdiff FileLine utilities
  34. */
  35. public class Checklics extends MatchingTask {
  36. /*
  37. * This does not enforce that copyrights are correct/current, only that they exist. E.g., the default behavior requires MPL but
  38. * permits either Xerox or PARC copyright holders and any valid year.
  39. */
  40. public static final String MPL_TAG = "mpl";
  41. public static final String APACHE_TAG = "apache";
  42. public static final String CPL_IBM_PARC_TAG = "cpl-ibm|parc";
  43. public static final String CPL_IBM_TAG = "cpl-ibm";
  44. public static final String MPL_XEROX_PARC_TAG = "mpl-parc|xerox";
  45. public static final String MPL_ONLY_TAG = "mpl-only";
  46. public static final String MPL_PARC_TAG = "mpl-parc";
  47. public static final String PARC_COPYRIGHT_TAG = "parc-copy";
  48. public static final String CPL_IBM_PARC_XEROX_TAG = "cpl-ibm|parc|xerox";
  49. public static final String CPL_IBM_PARC_XEROX_OTHERS_TAG = "cpl-ibm|parc|xerox|others";
  50. public static final String EPL_CPL_IBM_PARC_XEROX_OTHERS_TAG = "epl-cpl-ibm|parc|xerox|vmware|others";
  51. public static final String DEFAULT = EPL_CPL_IBM_PARC_XEROX_OTHERS_TAG;
  52. static final Map<String,License> LICENSES; // unmodifiable Map
  53. static {
  54. final String CONTRIBUTORS = "Contributors";
  55. final String XEROX = "Xerox";
  56. final String PARC = "Palo Alto Research Center";
  57. final String APACHE = "The Apache Software Foundation";
  58. final String IBM = "IBM";
  59. final String VMWARE = "VMware";
  60. final String IBM_LONG = "International Business Machines";
  61. final String LIC_APL = "Apache Software Foundation (http://www.apache.org/)";
  62. final String LIC_MPL = "http://aspectj.org/MPL/";
  63. final String LIC_CPL = "Eclipse Public License";
  64. final String LIC_ECPL = " Public License";
  65. License APL = new License(APACHE_TAG, LIC_APL, APACHE);
  66. License MPL = new License(MPL_TAG, LIC_MPL, XEROX);
  67. License MPL_XEROX_PARC = new License(DEFAULT, LIC_MPL, XEROX, PARC);
  68. License CPL_IBM_PARC = new License(CPL_IBM_PARC_TAG, LIC_CPL, new String[] { IBM_LONG, IBM, PARC });
  69. License CPL_IBM_PARC_XEROX = new License(CPL_IBM_PARC_XEROX_TAG, LIC_CPL, new String[] { IBM_LONG, IBM, PARC, XEROX });
  70. License CPL_IBM_PARC_XEROX_OTHERS = new License(CPL_IBM_PARC_XEROX_OTHERS_TAG, LIC_CPL, new String[] { IBM_LONG, IBM, PARC,
  71. XEROX, CONTRIBUTORS });
  72. License EPL_CPL_IBM_PARC_XEROX_OTHERS = new License(EPL_CPL_IBM_PARC_XEROX_OTHERS_TAG, LIC_ECPL, new String[] { IBM_LONG,
  73. IBM, PARC, XEROX, VMWARE, CONTRIBUTORS });
  74. License CPL_IBM = new License(CPL_IBM_TAG, LIC_CPL, IBM, IBM_LONG);
  75. License MPL_ONLY = new License(MPL_ONLY_TAG, LIC_MPL);
  76. License MPL_PARC = new License(MPL_PARC_TAG, LIC_MPL, PARC);
  77. License PARC_COPYRIGHT = new License(PARC_COPYRIGHT_TAG, null, PARC);
  78. LICENSES = new Hashtable<String,License>();
  79. LICENSES.put(APL.tag, APL);
  80. LICENSES.put(MPL.tag, MPL);
  81. LICENSES.put(MPL_PARC.tag, MPL_PARC);
  82. LICENSES.put(MPL_XEROX_PARC.tag, MPL_XEROX_PARC);
  83. LICENSES.put(CPL_IBM_PARC.tag, CPL_IBM_PARC);
  84. LICENSES.put(MPL_ONLY.tag, MPL_ONLY);
  85. LICENSES.put(CPL_IBM.tag, CPL_IBM);
  86. LICENSES.put(PARC_COPYRIGHT.tag, PARC_COPYRIGHT);
  87. LICENSES.put(CPL_IBM_PARC_XEROX.tag, CPL_IBM_PARC_XEROX);
  88. LICENSES.put(CPL_IBM_PARC_XEROX_OTHERS.tag, CPL_IBM_PARC_XEROX_OTHERS);
  89. LICENSES.put(EPL_CPL_IBM_PARC_XEROX_OTHERS.tag, EPL_CPL_IBM_PARC_XEROX_OTHERS);
  90. }
  91. /** @param args String[] { &lt; sourcepath &gt; {, &lt; licenseTag &gt; } } */
  92. public static void main(String[] args) {
  93. switch (args.length) {
  94. case 1:
  95. runDirect(args[0], null, false);
  96. break;
  97. case 2:
  98. runDirect(args[0], args[1], false);
  99. break;
  100. default:
  101. String options = "{replace-headers|get-years|list|{licenseTag}}";
  102. System.err.println("java {me} sourcepath " + options);
  103. break;
  104. }
  105. }
  106. /**
  107. * Run the license check directly
  108. *
  109. * @param sourcepaths String[] of paths to source directories
  110. * @param license the String tag for the license, if any
  111. * @param failonerror boolean flag to pass to Checklics
  112. * @throws IllegalArgumentException if sourcepaths is empty
  113. * @return total number of failed licenses
  114. */
  115. public static int runDirect(String sourcepath, String license, boolean failonerror) {
  116. if ((null == sourcepath) || (1 > sourcepath.length())) {
  117. throw new IllegalArgumentException("bad sourcepath: " + sourcepath);
  118. }
  119. Checklics me = new Checklics();
  120. Project p = new Project();
  121. p.setName("direct interface to Checklics");
  122. p.setBasedir(".");
  123. me.setProject(p);
  124. me.setFailOnError(failonerror);
  125. me.setSourcepath(new Path(p, sourcepath));
  126. if (null != license) {
  127. if ("replace-headers".equals(license)) {
  128. me.setReplaceheaders(true);
  129. } else if ("get-years".equals(license)) {
  130. me.setGetYears(true);
  131. } else if ("list".equals(license)) {
  132. me.setList(true);
  133. } else {
  134. me.setLicense(license);
  135. }
  136. }
  137. me.execute();
  138. return me.failed;
  139. }
  140. private Path sourcepath;
  141. private License license;
  142. private boolean list;
  143. private String streamTag;
  144. private boolean failOnError;
  145. private boolean getYears;
  146. private boolean replaceHeaders;
  147. private int failed;
  148. private int passed;
  149. private boolean printDirectories;
  150. /** @param list if true, don't run but list known license tags */
  151. public void setList(boolean list) {
  152. this.list = list;
  153. }
  154. public void setPrintDirectories(boolean print) {
  155. printDirectories = print;
  156. }
  157. /**
  158. * When failOnError is true, if any file failed, throw BuildException listing number of files that file failed to pass license
  159. * check
  160. *
  161. * @param fail if true, report errors by throwing BuildException
  162. */
  163. public void setFailOnError(boolean fail) {
  164. this.failOnError = fail;
  165. }
  166. /** @param tl mpl | apache | cpl */
  167. public void setLicense(String tl) {
  168. License input = LICENSES.get(tl);
  169. if (null == input) {
  170. throw new BuildException("no license known for " + tl);
  171. }
  172. license = input;
  173. }
  174. public void setSourcepath(Path path) {
  175. if (sourcepath == null) {
  176. sourcepath = path;
  177. } else {
  178. sourcepath.append(path);
  179. }
  180. }
  181. public Path createSourcepath() {
  182. return sourcepath == null ? (sourcepath = new Path(project)) : sourcepath.createPath();
  183. }
  184. public void setSourcepathRef(Reference id) {
  185. createSourcepath().setRefid(id);
  186. }
  187. /** @param out "out" or "err" */
  188. public void setOutputStream(String out) {
  189. this.streamTag = out;
  190. }
  191. public void setReplaceheaders(boolean replaceHeaders) {
  192. this.replaceHeaders = replaceHeaders;
  193. }
  194. public void setGetYears(boolean getYears) {
  195. this.getYears = getYears;
  196. }
  197. /** list known licenses or check source tree */
  198. @Override
  199. public void execute() throws BuildException {
  200. if (list) {
  201. list();
  202. } else if (replaceHeaders) {
  203. replaceHeaders();
  204. } else if (getYears) {
  205. getYears();
  206. } else {
  207. checkLicenses();
  208. }
  209. }
  210. private PrintStream getOut() {
  211. return ("err".equals(streamTag) ? System.err : System.out);
  212. }
  213. interface FileVisitor {
  214. void visit(File file);
  215. }
  216. /** visit all .java files in all directories... */
  217. private void visitAll(FileVisitor visitor) {
  218. // List filelist = new ArrayList();
  219. String[] dirs = sourcepath.list();
  220. for (int i = 0; i < dirs.length; i++) {
  221. File dir = project.resolveFile(dirs[i]);
  222. String[] files = getDirectoryScanner(dir).getIncludedFiles();
  223. for (int j = 0; j < files.length; j++) {
  224. File file = new File(dir, files[j]);
  225. String path = file.getPath();
  226. if (path.endsWith(".java")) {
  227. visitor.visit(file);
  228. }
  229. }
  230. }
  231. }
  232. private void replaceHeaders() {
  233. class YearVisitor implements FileVisitor {
  234. @Override
  235. public void visit(File file) {
  236. HeaderInfo info = Header.checkFile(file);
  237. if (!Header.replaceHeader(file, info)) {
  238. throw new BuildException("failed to replace header for " + file + " using " + info);
  239. }
  240. }
  241. }
  242. visitAll(new YearVisitor());
  243. }
  244. private void getYears() {
  245. final PrintStream out = getOut();
  246. class YearVisitor implements FileVisitor {
  247. @Override
  248. public void visit(File file) {
  249. HeaderInfo info = Header.checkFile(file);
  250. out.println(info.toString());
  251. }
  252. }
  253. visitAll(new YearVisitor());
  254. }
  255. private void checkLicenses() throws BuildException {
  256. if (null == license) {
  257. setLicense(DEFAULT);
  258. }
  259. final License license = this.license; // being paranoid...
  260. if (null == license) {
  261. throw new BuildException("no license");
  262. }
  263. final PrintStream out = getOut();
  264. class Visitor implements FileVisitor {
  265. int failed = 0;
  266. int passed = 0;
  267. @Override
  268. public void visit(File file) {
  269. if (license.checkFile(file)) {
  270. passed++;
  271. } else {
  272. failed++;
  273. String path = file.getPath();
  274. if (!license.foundLicense()) {
  275. out.println(license.tag + " LICENSE FAIL: " + path);
  276. }
  277. if (!license.foundCopyright()) {
  278. out.println(license.tag + " COPYRIGHT FAIL: " + path);
  279. }
  280. }
  281. }
  282. }
  283. Visitor visitor = new Visitor();
  284. visitAll(visitor);
  285. this.failed = visitor.failed;
  286. this.passed = visitor.passed;
  287. if (0 < visitor.failed) {
  288. getOut().println("Total passed: " + visitor.passed + (visitor.failed == 0 ? "" : " failed: " + visitor.failed));
  289. if (failOnError) {
  290. throw new BuildException(failed + " files failed license check");
  291. }
  292. }
  293. }
  294. private void list() {
  295. Iterator enu = LICENSES.keySet().iterator();
  296. StringBuffer sb = new StringBuffer();
  297. sb.append("known license keys:");
  298. boolean first = true;
  299. while (enu.hasNext()) {
  300. sb.append((first ? " " : ", ") + enu.next());
  301. if (first) {
  302. first = false;
  303. }
  304. }
  305. getOut().println(sb.toString());
  306. }
  307. /**
  308. * Encapsulate license and copyright specifications to check files use hokey string matching.
  309. */
  310. public static class License {
  311. /** acceptable years for copyright prefix to company - append " " */
  312. static final String[] YEARS = // remove older after license xfer?
  313. new String[] { "2002 ", "2003 ", "2004 ", "2005", "2006", "2007", "2008",
  314. "2009", "2010", "2011", "2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019", "2001 ", "2000 ",
  315. "1999 " };
  316. public final String tag;
  317. public final String license;
  318. private final String[] copyright;
  319. private boolean gotLicense;
  320. private boolean gotCopyright;
  321. License(String tag, String license) {
  322. this(tag, license, (String[]) null);
  323. }
  324. License(String tag, String license, String copyright) {
  325. this(tag, license, new String[] { copyright });
  326. }
  327. License(String tag, String license, String copyright, String altCopyright) {
  328. this(tag, license, new String[] { copyright, altCopyright });
  329. }
  330. License(String tag, String license, String[] copyright) {
  331. this.tag = tag;
  332. if ((null == tag) || (0 == tag.length())) {
  333. throw new IllegalArgumentException("null tag");
  334. }
  335. this.license = license;
  336. this.copyright = copyright;
  337. }
  338. public final boolean gotValidFile() {
  339. return foundLicense() && foundCopyright();
  340. }
  341. /** @return true if no license sought or if some license found */
  342. public final boolean foundLicense() {
  343. return ((null == license) || gotLicense);
  344. }
  345. /** @return true if no copyright sought or if some copyright found */
  346. public final boolean foundCopyright() {
  347. return ((null == copyright) || gotCopyright);
  348. }
  349. public boolean checkFile(final File file) {
  350. clear();
  351. // boolean result = false;
  352. BufferedReader input = null;
  353. int lineNum = 0;
  354. try {
  355. input = new BufferedReader(new FileReader(file));
  356. String line;
  357. while (!gotValidFile() && (line = input.readLine()) != null) {
  358. lineNum++;
  359. checkLine(line);
  360. }
  361. } catch (IOException e) {
  362. System.err.println("reading line " + lineNum + " of " + file);
  363. e.printStackTrace(System.err);
  364. } finally {
  365. if (null != input) {
  366. try {
  367. input.close();
  368. } catch (IOException e) {
  369. } // ignore
  370. }
  371. }
  372. return gotValidFile();
  373. }
  374. @Override
  375. public String toString() {
  376. return tag;
  377. }
  378. private void checkLine(String line) {
  379. if ((null == line) || (0 == line.length())) {
  380. return;
  381. }
  382. if (!gotLicense && (null != license) && (-1 != line.indexOf(license))) {
  383. gotLicense = true;
  384. }
  385. if (!gotCopyright && (null != copyright)) {
  386. int loc;
  387. for (int j = 0; !gotCopyright && (j < YEARS.length); j++) {
  388. if (-1 != (loc = line.indexOf(YEARS[j]))) {
  389. loc += YEARS[j].length();
  390. String afterLoc = line.substring(loc).trim();
  391. for (int i = 0; !gotCopyright && (i < copyright.length); i++) {
  392. if (0 == afterLoc.indexOf(copyright[i])) {
  393. gotCopyright = true;
  394. }
  395. }
  396. }
  397. }
  398. }
  399. }
  400. private void clear() {
  401. if (gotLicense) {
  402. gotLicense = false;
  403. }
  404. if (gotCopyright) {
  405. gotCopyright = false;
  406. }
  407. }
  408. } // class License
  409. }
  410. class HeaderInfo {
  411. /** File for which this is the info */
  412. public final File file;
  413. /** unmodifiable List of String years */
  414. public final List years;
  415. /** last line of license */
  416. public final int lastLine;
  417. /** last line of license */
  418. public final boolean hasLicense;
  419. public HeaderInfo(File file, int lastLine, List<String> years, boolean hasLicense) {
  420. this.lastLine = lastLine;
  421. this.file = file;
  422. this.hasLicense = hasLicense;
  423. List<String> newYears = new ArrayList<String>();
  424. newYears.addAll(years);
  425. Collections.sort(newYears);
  426. this.years = Collections.unmodifiableList(newYears);
  427. if ((null == file) || !file.canWrite()) {
  428. throw new IllegalArgumentException("bad file: " + this);
  429. }
  430. if (!hasLicense) {
  431. if ((0 > lastLine) || (65 < lastLine)) {
  432. throw new IllegalArgumentException("bad last line: " + this);
  433. }
  434. } else {
  435. if ((null == years) || (1 > years.size())) {
  436. throw new IllegalArgumentException("no years: " + this);
  437. }
  438. if ((20 > lastLine) || (65 < lastLine)) {
  439. throw new IllegalArgumentException("bad last line: " + this);
  440. }
  441. }
  442. }
  443. @Override
  444. public String toString() {
  445. return file.getPath() + ":" + lastLine + " " + years;
  446. }
  447. public void writeHeader(PrintWriter writer) {
  448. if (!hasLicense) {
  449. writer.println(TOP);
  450. writer.println(PARC_ONLY);
  451. writeRest(writer);
  452. } else {
  453. final int size = years.size();
  454. if (1 > size) {
  455. throw new Error("no years found in " + toString());
  456. }
  457. String first = (String) years.get(0);
  458. String last = (String) years.get(size - 1);
  459. boolean lastIs2002 = "2002".equals(last);
  460. String xlast = last;
  461. if (lastIs2002) { // 2002 was PARC
  462. xlast = (String) (size > 1 ? years.get(size - 2) : null);
  463. // 1999-2002 Xerox implies 1999-2001 Xerox
  464. if (first.equals(xlast) && !"2001".equals(xlast)) {
  465. xlast = "2001";
  466. }
  467. }
  468. String xyears = first + "-" + xlast;
  469. if (first.equals(last)) {
  470. xyears = first;
  471. }
  472. writer.println(TOP);
  473. if (!lastIs2002) { // Xerox only
  474. writer.println(XEROX_PREFIX + xyears + XEROX_SUFFIX + ". ");
  475. } else if (size == 1) { // PARC only
  476. writer.println(PARC_ONLY);
  477. } else { // XEROX plus PARC
  478. writer.println(XEROX_PREFIX + xyears + XEROX_SUFFIX + ", ");
  479. writer.println(PARC);
  480. }
  481. writeRest(writer);
  482. }
  483. }
  484. void writeRest(PrintWriter writer) {
  485. writer.println(" * All rights reserved. ");
  486. writer.println(" * This program and the accompanying materials are made available ");
  487. writer.println(" * under the terms of the Eclipse Public License v1.0 ");
  488. writer.println(" * which accompanies this distribution and is available at ");
  489. writer.println(" * http://www.eclipse.org/legal/epl-v10.html ");
  490. writer.println(" * ");
  491. writer.println(" * Contributors: ");
  492. writer.println(" * Xerox/PARC initial implementation ");
  493. writer.println(" * ******************************************************************/");
  494. writer.println("");
  495. }
  496. public static final String TOP = "/* *******************************************************************";
  497. public static final String PARC = " * 2002 Palo Alto Research Center, Incorporated (PARC).";
  498. public static final String PARC_ONLY = " * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).";
  499. public static final String XEROX_PREFIX = " * Copyright (c) ";
  500. public static final String XEROX_SUFFIX = " Xerox Corporation";
  501. /*
  502. * /* ******************************************************************* Copyright (c) 1998-2001 Xerox Corporation, 2002 Palo
  503. * Alto Research Center, Incorporated (PARC). All rights reserved. This program and the accompanying materials are made
  504. * available under the terms of the Eclipse Public License v1.0 which accompanies this distribution and is available at
  505. * http://www.eclipse.org/legal/epl-v10.html
  506. *
  507. * Contributors: Xerox/PARC initial implementation ******************************************************************
  508. */
  509. }
  510. /**
  511. * header search/replace using hokey string matching
  512. */
  513. class Header {
  514. /** replace the header in file */
  515. public static boolean replaceHeader(File file, HeaderInfo info) {
  516. // ArrayList years = new ArrayList();
  517. // int endLine = 0;
  518. BufferedReader input = null;
  519. PrintWriter output = null;
  520. FileWriter outWriter = null;
  521. int lineNum = 0;
  522. boolean result = false;
  523. final File inFile = new File(file.getPath() + ".tmp");
  524. try {
  525. File outFile = new File(file.getPath());
  526. if (!file.renameTo(inFile) || !inFile.canRead()) {
  527. throw new Error("unable to rename " + file + " to " + inFile);
  528. }
  529. outWriter = new FileWriter(outFile);
  530. input = new BufferedReader(new FileReader(inFile));
  531. output = new PrintWriter(outWriter, true);
  532. info.writeHeader(output);
  533. String line;
  534. while (null != (line = input.readLine())) {
  535. lineNum++;
  536. if (lineNum > info.lastLine) {
  537. output.println(line);
  538. }
  539. }
  540. } catch (IOException e) {
  541. System.err.println("writing line " + lineNum + " of " + file);
  542. e.printStackTrace(System.err);
  543. result = false;
  544. } finally {
  545. if (null != input) {
  546. try {
  547. input.close();
  548. } catch (IOException e) {
  549. result = false;
  550. }
  551. }
  552. if (null != outWriter) {
  553. try {
  554. outWriter.close();
  555. } catch (IOException e) {
  556. result = false;
  557. }
  558. }
  559. result = inFile.delete();
  560. }
  561. return result;
  562. }
  563. public static HeaderInfo checkFile(final File file) {
  564. ArrayList<String> years = new ArrayList<String>();
  565. int endLine = 0;
  566. BufferedReader input = null;
  567. int lineNum = 0;
  568. try {
  569. input = new BufferedReader(new FileReader(file));
  570. String line;
  571. while (null != (line = input.readLine())) {
  572. lineNum++;
  573. String ll = line.trim();
  574. if (ll.startsWith("package ") || ll.startsWith("import ")) {
  575. break; // ignore default package w/o imports
  576. }
  577. if (checkLine(line, years)) {
  578. endLine = lineNum;
  579. break;
  580. }
  581. }
  582. } catch (IOException e) {
  583. System.err.println("reading line " + lineNum + " of " + file);
  584. e.printStackTrace(System.err);
  585. } finally {
  586. if (null != input) {
  587. try {
  588. input.close();
  589. } catch (IOException e) {
  590. } // ignore
  591. }
  592. }
  593. return new HeaderInfo(file, endLine, years, endLine > 0);
  594. }
  595. /**
  596. * Add any years found (as String) to years, and return true at the first end-of-comment
  597. *
  598. * @return true if this line has end-of-comment
  599. */
  600. private static boolean checkLine(String line, ArrayList<String> years) {
  601. if ((null == line) || (0 == line.length())) {
  602. return false;
  603. }
  604. int loc;
  605. int start = 0;
  606. while ((-1 != (loc = line.indexOf("199", start)) || (-1 != (loc = line.indexOf("200", start))))) {
  607. char c = line.charAt(loc + 3);
  608. if ((c <= '9') && (c >= '0')) {
  609. years.add(line.substring(loc, loc + 4));
  610. }
  611. start = loc + 4;
  612. }
  613. return (-1 != line.indexOf("*/"));
  614. }
  615. } // class Header