Clover Coverage Report
Coverage timestamp: Fri May 24 2013 13:47:27 UTC
../../../../img/srcFileCovDistChart10.png 0% of files have more coverage
380   1,203   159   7.6
156   687   0.42   50
50     3.18  
1    
 
  IoUtility       Line # 58 380 159 91.5% 0.9146758
 
  (444)
 
1    /* This file is part of the project "Hilbert II" - http://www.qedeq.org
2    *
3    * Copyright 2000-2013, Michael Meyling <mime@qedeq.org>.
4    *
5    * "Hilbert II" is free software; you can redistribute
6    * it and/or modify it under the terms of the GNU General Public
7    * License as published by the Free Software Foundation; either
8    * version 2 of the License, or (at your option) any later version.
9    *
10    * This program is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13    * GNU General Public License for more details.
14    */
15   
16    package org.qedeq.base.io;
17   
18    import java.io.BufferedOutputStream;
19    import java.io.BufferedReader;
20    import java.io.BufferedWriter;
21    import java.io.ByteArrayInputStream;
22    import java.io.File;
23    import java.io.FileFilter;
24    import java.io.FileInputStream;
25    import java.io.FileOutputStream;
26    import java.io.FileReader;
27    import java.io.FileWriter;
28    import java.io.IOException;
29    import java.io.InputStream;
30    import java.io.InputStreamReader;
31    import java.io.OutputStream;
32    import java.io.OutputStreamWriter;
33    import java.io.Reader;
34    import java.io.UnsupportedEncodingException;
35    import java.io.Writer;
36    import java.net.URL;
37    import java.nio.charset.Charset;
38    import java.util.ArrayList;
39    import java.util.Arrays;
40    import java.util.Enumeration;
41    import java.util.Iterator;
42    import java.util.List;
43    import java.util.Map;
44    import java.util.Properties;
45    import java.util.StringTokenizer;
46    import java.util.TreeMap;
47   
48    import org.apache.commons.lang.SystemUtils;
49   
50   
51    /**
52    * A collection of useful static methods for input and output.
53    *
54    * LATER mime 20070101: use StringBuilder instead of StringBuffer if working under JDK 1.5
55    *
56    * @author Michael Meyling
57    */
 
58    public final class IoUtility {
59   
60    /**
61    * Constructor, should never be called.
62    */
 
63  0 toggle private IoUtility() {
64    // don't call me
65    }
66   
67    /**
68    * Get default encoding for this system.
69    *
70    * @return Default encoding for this system.
71    */
 
72  9 toggle public static String getDefaultEncoding() {
73  9 return SystemUtils.FILE_ENCODING;
74    // mime 20090630: under ubuntu the following gave the encoding ASCII:
75    // return new InputStreamReader(
76    // new ByteArrayInputStream(new byte[0])).getEncoding();
77    // but it was: file.encoding="ANSI_X3.41968"
78    }
79   
80    /**
81    * Get working Java encoding.
82    *
83    * @param encoding Try this encoding.
84    * @return This is <code>encoding</code> if it is supported. Or an other
85    * encoding that is supported by this system.
86    */
 
87  5 toggle public static String getWorkingEncoding(final String encoding) {
88  5 if (encoding != null) {
89  4 try {
90  4 if (Charset.isSupported(encoding)
91    && Charset.forName(encoding).canEncode()) {
92  3 return encoding;
93    }
94    } catch (RuntimeException e) {
95    // ignore
96    }
97    }
98    // we must inform someone, but using
99    // Trace within this class is not wise, because it is used
100    // before the Trace is initialized.
101  2 System.err.println("not supported encoding: " + encoding);
102  2 return "ISO-8859-1"; // every system must support this
103    }
104   
105    /**
106    * Reads a file and returns the contents as a <code>String</code>.
107    *
108    * @param filename Name of the file (could include path).
109    * @param encoding Take this encoding.
110    * @return Contents of file.
111    * @throws IOException File exception occurred.
112    */
 
113  4 toggle public static String loadFile(final String filename, final String encoding)
114    throws IOException {
115   
116  4 final StringBuffer buffer = new StringBuffer();
117  4 loadFile(filename, buffer, encoding);
118  4 return buffer.toString();
119    }
120   
121    /**
122    * Reads contents of a file into a string buffer.
123    *
124    * @param filename Name of the file (could include path).
125    * @param buffer Buffer to fill with file contents.
126    * @param encoding Take this encoding.
127    * @throws IOException File exception occurred.
128    */
 
129  4 toggle public static void loadFile(final String filename,
130    final StringBuffer buffer, final String encoding)
131    throws IOException {
132  4 loadFile(new File(filename), buffer, encoding);
133    }
134   
135    /**
136    * Reads contents of a stream into a string buffer. Stream is not closed.
137    *
138    * @param in This stream will be loaded.
139    * @param buffer Buffer to fill with file contents.
140    * @throws IOException File exception occurred.
141    *
142    * @deprecated Use {@link #loadReader(Reader, StringBuffer)}.
143    */
 
144  1 toggle public static void loadStream(final InputStream in, final StringBuffer buffer)
145    throws IOException {
146   
147  1 buffer.setLength(0);
148  1 int c;
149  ? while ((c = in.read()) >= 0) {
150  37 buffer.append((char) c);
151    }
152    }
153   
154    /**
155    * Returns contents of a stream into a string, respecting a maximum length.
156    * No exceptions are thrown. Stream is not closed.
157    *
158    * @param in This stream will be loaded.
159    * @param maxLength This length is not exceeded.
160    * @return readData Data read, is not <code>null</code>.
161    */
 
162  16 toggle public static String loadStreamWithoutException(final InputStream in, final int maxLength) {
163   
164  16 if (in == null) {
165  2 return "";
166    }
167  14 final StringBuffer buffer = new StringBuffer();
168  14 buffer.setLength(0);
169  14 try {
170  14 int counter = 0;
171  14 int c;
172  12190 while (counter++ < maxLength) {
173  12178 c = in.read();
174  12178 if (c < 0) {
175  2 break;
176    }
177  12176 buffer.append((char) c);
178    }
179    } catch (IOException e) {
180    // ignored
181    } catch (RuntimeException e) {
182    // ignored
183    }
184  14 return buffer.toString();
185    }
186   
187    /**
188    * Reads contents of a {@link Reader} into a string buffer. Reader is not closed.
189    *
190    * @param in This reader will be loaded.
191    * @param buffer Buffer to fill with file contents.
192    * @throws IOException File exception occurred.
193    */
 
194  3 toggle public static void loadReader(final Reader in, final StringBuffer buffer)
195    throws IOException {
196   
197  3 buffer.setLength(0);
198  3 int c;
199  ? while ((c = in.read()) >= 0) {
200  7392 buffer.append((char) c);
201    }
202    }
203   
204    /**
205    * Reads contents of a file into a string buffer. Uses default encoding.
206    *
207    * @param file This file will be loaded.
208    * @param buffer Buffer to fill with file contents.
209    * @throws IOException File exception occurred.
210    *
211    * @deprecated Use {@link #loadFile(File, StringBuffer, String)}.
212    */
 
213  1 toggle public static void loadFile(final File file,
214    final StringBuffer buffer)
215    throws IOException {
216   
217  1 final int size = (int) file.length();
218  1 final char[] data = new char[size];
219  1 buffer.setLength(0);
220  1 FileReader in = null;
221  1 try {
222  1 in = new FileReader(file);
223  1 int charsread = 0;
224  2 while (charsread < size) {
225  1 charsread += in.read(data, charsread, size - charsread);
226    }
227    } finally {
228  1 close(in);
229    }
230  1 buffer.insert(0, data);
231    }
232   
233    /**
234    * Reads contents of a file into a string buffer.
235    *
236    * @param file This file will be loaded.
237    * @param buffer Buffer to fill with file contents.
238    * @param encoding Take this encoding.
239    * @throws IOException File exception occurred.
240    */
 
241  10 toggle public static void loadFile(final File file,
242    final StringBuffer buffer, final String encoding)
243    throws IOException {
244   
245  10 buffer.setLength((int) file.length()); // ensure capacity
246  10 buffer.setLength(0);
247  10 final InputStreamReader in = new InputStreamReader(new FileInputStream(file), encoding);
248  10 final char[] data = new char[10 * 1024];
249   
250  10 try {
251  10 int charsread = 0;
252  ? while (0 < (charsread = in.read(data, 0, data.length))) {
253  10 buffer.append(data, 0, charsread);
254    }
255    } finally {
256  10 in.close();
257    }
258    }
259   
260    /**
261    * Reads a file and returns the contents as a <code>String</code>.
262    *
263    * @param file File to load from.
264    * @return Contents of file.
265    * @throws IOException File exception occurred.
266    */
 
267  4 toggle public static final byte[] loadFileBinary(final File file) throws IOException {
268  4 final int size = (int) file.length();
269  4 final FileInputStream in = new FileInputStream(file);
270  4 try {
271  4 final byte[] data = new byte[size];
272  4 int charsread = 0;
273  8 while (charsread < size) {
274  4 final int read = in.read(data, charsread, size - charsread);
275  4 if (read == -1) {
276  0 final byte[] result = new byte[charsread];
277  0 System.arraycopy(data, 0, result, 0, charsread);
278  0 return result;
279    }
280  4 charsread += read;
281    }
282  4 in.close();
283  4 return data;
284    } finally {
285  4 close(in);
286    }
287    }
288   
289   
290    /**
291    * Reads contents of an URL into a string buffer. The filling is character set dependent.
292    * Content is added to the end of buffer. (Existing data is not cleared.)
293    * <p>
294    * All parameters should not be <code>null</code>.
295    * @param url This URL will be loaded.
296    * @param buffer Buffer to fill with file contents.
297    * @throws IOException Reading failed.
298    *
299    * @deprecated Choose correct encoding.
300    */
 
301  1 toggle public static void loadFile(final URL url, final StringBuffer buffer) throws IOException {
302  1 InputStream in = null;
303  1 BufferedReader dis = null;
304  1 try {
305  1 in = url.openStream();
306  1 dis = new BufferedReader(new InputStreamReader(in));
307  1 int i;
308  ? while ((i = dis.read()) != -1) {
309  37 buffer.append((char) i);
310    }
311    } finally {
312  1 close(in);
313  1 close(dis);
314    }
315    }
316   
317    /**
318    * Reads contents of an URL into a StringBuffer. The filling is character set dependent. The
319    * buffer is not cleared, contents is just added.
320    * <p>
321    * All parameters should not be <code>null</code>.
322    * @param url This URL will be loaded.
323    * @param buffer Buffer to fill with file contents.
324    * @param encoding Take this encoding.
325    * @throws IOException Reading failed.
326    */
 
327  3 toggle public static void loadFile(final URL url, final StringBuffer buffer, final String encoding)
328    throws IOException {
329  3 InputStream in = null;
330  3 BufferedReader dis = null;
331  3 try {
332  3 in = url.openStream();
333  3 dis = new BufferedReader(new InputStreamReader(in, encoding));
334  3 int i;
335  ? while ((i = dis.read()) != -1) {
336  6141 buffer.append((char) i);
337    }
338    } finally {
339  3 close(in);
340  3 close(dis);
341    }
342    }
343   
344    /**
345    * Save binary contents of an URL into a file. Existing files are overwritten.
346    *
347    * @param url This URL will be loaded.
348    * @param file Write into this file.
349    * @throws IOException Reading or writing failed.
350    */
 
351  2 toggle public static void saveFile(final URL url, final File file) throws IOException {
352  2 saveFile(url.openStream(), file);
353    }
354   
355    /**
356    * Save binary contents of an input stream into a file. The input stream is closed even
357    * if exceptions occur. Existing files are overwritten.
358    * @param in Read this stream.
359    * @param file Write into this file.
360    *
361    * @throws IOException Reading or writing failed.
362    */
 
363  47 toggle public static void saveFile(final InputStream in, final File file) throws IOException {
364  47 FileOutputStream out = null;
365  47 try {
366  47 out = new FileOutputStream(file);
367  47 final byte[] data = new byte[8 * 1024];
368  47 int length;
369  ? while ((length = in.read(data)) != -1) {
370  241 out.write(data, 0, length);
371    }
372    } finally {
373  47 close(in);
374  47 close(out);
375    }
376    }
377   
378    /**
379    * Convert String into a {@link Reader}.
380    *
381    * <a href="http://bugs.sun.com/bugdatabase/view_bug.do;:WuuT?bug_id=4094886">
382    * Bug ID: 4094886</a>
383    *
384    * @param data Convert this.
385    * @return Resulting reader.
386    */
 
387  448 toggle public static final Reader stringToReader(final String data) {
388  448 try {
389  448 return new InputStreamReader(new ByteArrayInputStream(data.getBytes("ISO-8859-1")));
390    } catch (UnsupportedEncodingException e) {
391    // should never occur
392  0 throw new RuntimeException(e);
393    }
394    }
395   
396    /**
397    * Saves a <code>String</code> into a file. Existing files are overwritten.
398    *
399    * @param filename Name of the file (could include path).
400    * @param text Data to save in the file.
401    * @throws IOException File exception occurred.
402    *
403    * @deprecated Use {@link #saveFile(File, String, String)} that has an encoding.
404    */
 
405  1 toggle public static void saveFile(final String filename, final String text)
406    throws IOException {
407  1 saveFile(new File(filename), text);
408    }
409   
410    /**
411    * Saves a <code>StringBuffer</code> in a file. Existing files are overwritten.
412    *
413    * @param filename Name of the file (could include path).
414    * @param text Data to save in the file.
415    * @throws IOException File exception occurred.
416    *
417    * @deprecated Use {@link #saveFile(File, StringBuffer, String)} that has an encoding.
418    */
 
419  1 toggle public static void saveFile(final String filename, final StringBuffer text)
420    throws IOException {
421  1 saveFile(new File(filename), text.toString());
422    }
423   
424    /**
425    * Saves a <code>StringBuffer</code> in a file. Existing files are overwritten.
426    *
427    * @param file File to save into.
428    * @param text Data to save in the file.
429    * @throws IOException File exception occurred.
430    *
431    * @deprecated Use {@link #saveFile(File, StringBuffer, String)} that has an encoding
432    * parameter.
433    */
 
434  1 toggle public static void saveFile(final File file, final StringBuffer text)
435    throws IOException {
436  1 saveFile(file, text.toString());
437    }
438   
439    /**
440    * Saves a <code>String</code> in a file. Uses default encoding. Existing files are
441    * overwritten.
442    *
443    * @param file File to save the data in.
444    * @param text Data to save in the file.
445    * @throws IOException File exception occurred.
446    *
447    * @deprecated Use {@link #saveFile(File, String, String)} that has an encoding parameter.
448    */
 
449  5 toggle public static void saveFile(final File file, final String text)
450    throws IOException {
451  5 BufferedWriter out = null;
452  5 try {
453  5 out = new BufferedWriter(new FileWriter(file));
454  5 out.write(text);
455    } finally {
456  5 close(out);
457    }
458    }
459   
460    /**
461    * Saves a <code>String</code> in a file. Existing files are overwritten.
462    *
463    * @param file File to save the data in.
464    * @param text Data to save in the file.
465    * @param encoding Use this encoding.
466    * @throws IOException File exception occurred.
467    */
 
468  4 toggle public static void saveFile(final File file, final StringBuffer text, final String encoding)
469    throws IOException {
470  4 saveFile(file, text.toString(), encoding);
471    }
472   
473    /**
474    * Saves a <code>String</code> in a file.
475    *
476    * @param file File to save the data in.
477    * @param text Data to save in the file.
478    * @param encoding Use this encoding.
479    * @throws IOException File exception occurred.
480    */
 
481  137 toggle public static void saveFile(final File file, final String text, final String encoding)
482    throws IOException {
483  137 BufferedWriter out = new BufferedWriter(
484    new OutputStreamWriter(new FileOutputStream(file), encoding));
485  136 try {
486  136 out.write(text);
487    } finally {
488  136 out.close();
489    }
490    }
491   
492    /**
493    * Saves a <code>data</code> in a file. Existing files are overwritten.
494    *
495    * @param file File to save the data in.
496    * @param data Data to save in the file.
497    * @throws IOException File exception occurred.
498    */
 
499  23 toggle public static void saveFileBinary(final File file, final byte[] data)
500    throws IOException {
501  23 BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
502  23 try {
503  23 out.write(data);
504    } finally {
505  23 out.close();
506    }
507    }
508   
509    /**
510    * Copies a file to a different location.
511    *
512    * @param from Copy source.
513    * @param to Copy destination.
514    * @throws IOException File exception occurred.
515    */
 
516  193 toggle public static void copyFile(final File from, final File to)
517    throws IOException {
518   
519  193 if (from.getCanonicalFile().equals(to.getCanonicalFile())) {
520  1 return;
521    }
522  192 createNecessaryDirectories(to);
523  192 FileInputStream in = null;
524  192 FileOutputStream out = null;
525  192 try {
526  192 in = new FileInputStream(from);
527  192 out = new FileOutputStream(to);
528   
529  192 byte[] data = new byte[8 * 1024];
530  192 int length;
531  ? while ((length = in.read(data)) != -1) {
532  1950 out.write(data, 0, length);
533    }
534    } finally {
535  192 close(in);
536  192 close(out);
537    }
538    }
539   
540    /**
541    * Copy one file or directory to another location.
542    * If targetLocation does not exist, it will be created.
543    *
544    * @param sourceLocation Copy from here. This can be a file or a directory.
545    * @param targetLocation Copy to this location. If source is a file this must be a file too.
546    * @throws IOException Something went wrong.
547    */
 
548  1 toggle public static void copy(final String sourceLocation, final String targetLocation)
549    throws IOException {
550  1 copy(new File(sourceLocation), new File(targetLocation));
551    }
552   
553    /**
554    * Copy one directory to another location.
555    * If targetLocation does not exist, it will be created.
556    *
557    * @param sourceLocation Copy from here.
558    * @param targetLocation Copy to this location
559    * @throws IOException Something went wrong.
560    */
 
561  15 toggle public static void copy(final File sourceLocation, final File targetLocation)
562    throws IOException {
563   
564  15 if (sourceLocation.isDirectory()) {
565  6 if (!targetLocation.exists()) {
566  6 targetLocation.mkdir();
567    }
568  6 String[] children = sourceLocation.list();
569  18 for (int i = 0; i < children.length; i++) { // recursive call for all children
570  12 copy(new File(sourceLocation, children[i]),
571    new File(targetLocation, children[i]));
572    }
573    } else { // copy file
574  9 copyFile(sourceLocation, targetLocation);
575    }
576    }
577   
578    /**
579    * List all matching files. Searches all matching sub directories recursively.
580    * Remember to return <code>true</code> for <code>accept(File pathname)</code> if
581    * <code>pathname</code> is a directory if you want to search all sub directories!
582    * If <code>sourceLocation</code> is a single file, this is the only file that will
583    * be in the resulting list.
584    *
585    * @param sourceLocation Check all files in this directory. (Or add this single file.)
586    * @param filter Accept only these directories and files.
587    * @return List of matching files. Contains no directories.
588    * @throws IOException Something went wrong.
589    */
 
590  8 toggle public static List listFilesRecursively(final File sourceLocation, final FileFilter filter)
591    throws IOException {
592  8 final List result = new ArrayList();
593  8 if (sourceLocation.isDirectory()) {
594  7 final File[] children = sourceLocation.listFiles();
595  65 for (int i = 0; i < children.length; i++) { // recursive call for all children
596  58 result.addAll(listFilesRecursivelyIntern(children[i], filter));
597    }
598    } else {
599  1 result.add(sourceLocation);
600    }
601  8 return result;
602    }
603   
604    /**
605    * List all matching files. Searches all matching sub directories recursively.
606    * Remember to return <code>true</code> for <code>accept(File pathname)</code> if
607    * <code>pathname</code> is a directory if you want to search all sub directories!
608    *
609    * @param sourceLocation Check all files in this directory.
610    * @param filter Accept only these directories and files.
611    * @return List of matching files. Contains no directories.
612    * @throws IOException Something went wrong.
613    */
 
614  265 toggle private static List listFilesRecursivelyIntern(final File sourceLocation,
615    final FileFilter filter) throws IOException {
616  265 final List result = new ArrayList();
617  265 if (filter.accept(sourceLocation)) {
618  169 if (sourceLocation.isDirectory()) {
619  21 File[] children = sourceLocation.listFiles();
620  228 for (int i = 0; i < children.length; i++) { // recursive call for all children
621  207 result.addAll(listFilesRecursivelyIntern(children[i], filter));
622    }
623    } else {
624  148 result.add(sourceLocation);
625    }
626    }
627  265 return result;
628    }
629   
630    /**
631    * Compare two files binary.
632    *
633    * @param from Compare source. This file must be <code>null</code> or be an existing file.
634    * @param with Compare with this file. This file must be <code>null</code> or be an
635    * existing file.
636    * @return Is the contents of the two files binary equal?
637    * @throws IOException File exception occurred.
638    */
 
639  34 toggle public static boolean compareFilesBinary(final File from, final File with)
640    throws IOException {
641  34 if (from == null && with == null) {
642  1 return true;
643    }
644  33 if (from == null || with == null) {
645  2 return false;
646    }
647  31 if (from.getAbsoluteFile().equals(with.getAbsoluteFile())) {
648  3 return true;
649    }
650  28 if (from.length() != with.length()) {
651  5 return false;
652    }
653  23 byte[] dataOne = new byte[8 * 1024];
654  23 byte[] dataTwo = new byte[8 * 1024];
655  23 int length;
656   
657  23 FileInputStream one = null;
658  23 FileInputStream two = null;
659  23 try {
660  23 one = new FileInputStream(from);
661  22 two = new FileInputStream(with);
662   
663  ? while ((length = one.read(dataOne)) != -1) {
664  22 if (length != two.read(dataTwo)) {
665  0 return false;
666    }
667  22 if (!Arrays.equals(dataOne, dataTwo)) {
668  2 return false;
669    }
670    }
671  20 return true;
672    } finally {
673  23 close(one);
674  23 close(two);
675    }
676    }
677   
678    /**
679    * Compare two text files. Ignores different line separators. As there are:
680    * LF, CR, CR + LF, NEL, FF, LS, PS.
681    *
682    * @param from Compare source.
683    * @param with Compare with this file.
684    * @param encoding Use this character encoding. Must not be <code>null</code>.
685    * @return Is the contents of the two text files equal?
686    * @throws IOException File exception occurred or encoding is not supported.
687    * @throws NullPointerException Is encoding different from <code>null</code>?
688    */
 
689  207 toggle public static boolean compareTextFiles(final File from, final File with, final String encoding)
690    throws IOException {
691  207 if (from == null && with == null) {
692  1 return true;
693    }
694  206 if (from == null || with == null) {
695  4 return false;
696    }
697  202 if (from.getAbsoluteFile().equals(with.getAbsoluteFile())) {
698  3 return true;
699    }
700   
701  199 BufferedReader one = null;
702  199 BufferedReader two = null;
703  199 FileInputStream fromIn = null;
704  199 FileInputStream withIn = null;
705  199 try {
706  199 fromIn = new FileInputStream(from);
707  198 one = new BufferedReader(new InputStreamReader(fromIn, encoding));
708  195 withIn = new FileInputStream(with);
709  195 two = new BufferedReader(new InputStreamReader(withIn, encoding));
710   
711  195 boolean crOne = false;
712  195 boolean crTwo = false;
713  195 do {
714  3007962 int readOne = one.read();
715  3007962 int readTwo = two.read();
716  3007962 if (readOne == readTwo) {
717  3000353 if (readOne < 0) {
718  174 break;
719    }
720    } else {
721  7609 crOne = readOne == 0x0D;
722  7609 crTwo = readTwo == 0x0D;
723  7609 if (crOne) {
724  7211 readOne = one.read();
725    }
726  7609 if (crTwo) {
727  375 readTwo = two.read();
728    }
729  7609 if (crOne && readOne != 0x0A && isCr(readTwo)) {
730  64 readTwo = two.read();
731    }
732  7609 if (crTwo && readTwo != 0x0A && isCr(readOne)) {
733  64 readOne = one.read();
734    }
735  7609 if (readOne != readTwo && (!isCr(readOne) && !isCr(readTwo))) {
736  21 return false;
737    }
738    }
739    } while (true);
740  174 return true;
741    } finally {
742  199 close(fromIn);
743  199 close(one);
744  199 close(two);
745  199 close(withIn);
746    }
747    }
748   
749    /**
750    * Compare two text files. Ignores different line separators. As there are:
751    * LF, CR, CR + LF
752    *
753    * @param from Compare source.
754    * @param with Compare with this file.
755    * @param startAtLine Start comparing at this line (beginning with 0).
756    * @param encoding Use this character encoding. Must not be <code>null</code>.
757    * @return Is the contents of the two text files equal?
758    * @throws IOException File exception occurred or encoding is not supported.
759    * @throws NullPointerException Is encoding different from <code>null</code>?
760    */
 
761  148 toggle public static boolean compareTextFiles(final File from, final File with, final int startAtLine,
762    final String encoding) throws IOException {
763   
764  148 if (from == null && with == null) {
765  3 return true;
766    }
767  145 if (from == null || with == null) {
768  6 return false;
769    }
770  139 if (from.getAbsoluteFile().equals(with.getAbsoluteFile())) {
771  3 return true;
772    }
773  136 if (startAtLine < 0) {
774  38 return true;
775    }
776  98 BufferedReader one = null;
777  98 BufferedReader two = null;
778  98 FileInputStream fromIn = null;
779  98 FileInputStream withIn = null;
780  98 try {
781  98 fromIn = new FileInputStream(from);
782  98 one = new BufferedReader(new InputStreamReader(fromIn, encoding));
783  96 withIn = new FileInputStream(with);
784  96 two = new BufferedReader(new InputStreamReader(withIn, encoding));
785  96 int pos = 0;
786  96 do {
787  2346 String lineOne = one.readLine();
788  2346 String lineTwo = two.readLine();
789  2346 if (lineOne == null) {
790  68 if (lineTwo == null) {
791  68 break;
792    }
793  0 return false;
794    }
795  2278 if (pos++ >= startAtLine && !lineOne.equals(lineTwo)) {
796  28 return false;
797    }
798    } while (true);
799  68 return true;
800    } finally {
801  98 close(fromIn);
802  98 close(one);
803  98 close(two);
804  98 close(withIn);
805    }
806    }
807   
808    /**
809    * Test if character is LF, CR, NEL, FF, LS, PS.
810    * @param c Character to test.
811    * @return Is character a line terminator?
812    */
 
813  464 toggle private static boolean isCr(final int c) {
814  464 return c == 0x0A || c == 0x0D || c == 0x85 || c == 0x0C || c == 0x2028 || c == 0x2029;
815    }
816   
817    /**
818    * Delete file directory recursive.
819    *
820    * @param directory Directory to delete. Must not be a symbolic link.
821    * @param deleteDir Delete directory itself too?
822    * @return Was deletion successful?
823    */
 
824  32 toggle public static boolean deleteDir(final File directory, final boolean deleteDir) {
825   
826    // first we check if the file is a symbolic link
827  32 try {
828  32 if (isSymbolicLink(directory)) {
829  0 return false;
830    }
831    } catch (IOException e) {
832  0 return false;
833    }
834  32 final File candir;
835  32 try {
836  32 candir = directory.getCanonicalFile();
837    } catch (IOException e) {
838  0 return false;
839    }
840   
841    // now we go through all of the files and subdirectories in the
842    // directory and delete them one by one
843  32 boolean success = true;
844  32 File[] files = candir.listFiles();
845  32 if (files != null) {
846  65 for (int i = 0; i < files.length; i++) {
847  39 File file = files[i];
848   
849    // in case this directory is actually a symbolic link, or it's
850    // empty, we want to try to delete the link before we try
851    // anything
852  39 boolean deleted = file.delete();
853  39 if (!deleted) {
854    // deleting the file failed, so maybe it's a non-empty
855    // directory
856  16 if (file.isDirectory()) {
857  16 deleted = deleteDir(file, true);
858    }
859   
860    // otherwise, there's nothing else we can do
861    }
862  39 success = success && deleted;
863    }
864    }
865   
866    // now that we tried to clear the directory out, we can try to delete it
867  32 if (deleteDir && directory.exists()) {
868  26 return directory.delete();
869    }
870  6 return success;
871    }
872   
873    /**
874    * Delete directory contents for all files that match the filter. The main directory itself is
875    * not deleted.
876    *
877    * @param directory Directory to scan for files to delete.
878    * @param filter Filter files (and directories) to delete.
879    * @return Was deletion successful?
880    */
 
881  1 toggle public static boolean deleteDir(final File directory, final FileFilter filter) {
882    // first we check if the file is a symbolic link
883  1 try {
884  1 if (isSymbolicLink(directory)) {
885  0 return false;
886    }
887    } catch (IOException e) {
888  0 return false;
889    }
890  1 final File candir;
891  1 try {
892  1 candir = directory.getCanonicalFile();
893    } catch (IOException e) {
894  0 return false;
895    }
896   
897    // now we go through all of the files and subdirectories in the
898    // directory and delete them one by one
899  1 boolean success = true;
900  1 File[] files = candir.listFiles(filter);
901  1 if (files != null) {
902  4 for (int i = 0; i < files.length; i++) {
903  3 File file = files[i];
904   
905    // in case this directory is actually a symbolic link, or it's
906    // empty, we want to try to delete the link before we try
907    // anything
908  3 boolean deleted = file.delete();
909  3 if (!deleted) {
910    // deleting the file failed, so maybe it's a non-empty
911    // directory
912  1 if (file.isDirectory()) {
913  1 deleted = deleteDir(file, true);
914    }
915   
916    // otherwise, there's nothing else we can do
917    }
918  3 success = success && deleted;
919    }
920    }
921   
922  1 return success;
923    }
924   
925    /**
926    * Determines whether the specified file is a symbolic link rather than an actual file.
927    * See {@link
928    * https://svn.apache.org/repos/asf/commons/proper/io/trunk/src/main/java/org/apache/commons/io/FileUtils.java}.
929    * @param file File to check.
930    * @return Is the file is a symbolic link?
931    * @throws IOException IO error while checking the file.
932    */
 
933  33 toggle public static boolean isSymbolicLink(final File file) throws IOException {
934  33 if (file == null) {
935  0 throw new NullPointerException("File must not be null");
936    }
937    // is windows file system in use?
938  33 if (File.separatorChar == '\\') {
939    // we have no symbolic links
940  0 return false;
941    }
942  33 File fileInCanonicalDir = null;
943  33 if (file.getParent() == null) {
944  1 fileInCanonicalDir = file;
945    } else {
946  32 File canonicalDir = file.getParentFile().getCanonicalFile();
947  32 fileInCanonicalDir = new File(canonicalDir, file.getName());
948    }
949  33 if (fileInCanonicalDir.getCanonicalFile().equals(fileInCanonicalDir.getAbsoluteFile())) {
950  33 return false;
951    }
952  0 return true;
953    }
954   
955    /**
956    * Print current system properties to System.out.
957    */
 
958  1 toggle public static void printAllSystemProperties() {
959  1 Properties sysprops = System.getProperties();
960  54 for (Enumeration e = sysprops.propertyNames(); e.hasMoreElements(); ) {
961  53 String key = (String) e.nextElement();
962  53 String value = sysprops.getProperty(key);
963  53 System.out.println(key + "=" + value);
964    }
965    }
966   
967    /**
968    * Get home directory of user.
969    *
970    * @return Home directory of user.
971    */
 
972  4 toggle public static File getUserHomeDirectory() {
973  4 return new File((String) System.getProperties().get("user.home"));
974    }
975   
976    /**
977    * Creates necessary parent directories for a file.
978    *
979    * @param file File.
980    * @throws IOException Creation failed.
981    */
 
982  913 toggle public static void createNecessaryDirectories(final File file) throws IOException {
983  913 if (file != null && file.getParentFile() != null) {
984  912 file.getParentFile().mkdirs();
985  912 if (!file.getParentFile().exists()) {
986  0 throw new IOException("directory creation failed: " + file.getParent());
987    }
988    }
989    }
990   
991    /**
992    * Create relative address from <code>origin</code> to <code>next</code>.
993    * The resulting file path has "/" as directory name separator.
994    * If the resulting file path is the same as origin specifies, we return "".
995    * Otherwise the result will always have an "/" as last character.
996    *
997    * @param origin This is the original location. Must be a directory.
998    * @param next This should be the next location. Must also be a directory.
999    * @return Relative (or if necessary absolute) file path.
1000    */
 
1001  14 toggle public static final String createRelativePath(final File origin, final File next) {
1002  14 if (origin.equals(next)) {
1003  2 return "";
1004    }
1005  12 final Path org = new Path(origin.getPath().replace(File.separatorChar, '/'), "");
1006  12 final Path ne = new Path(next.getPath().replace(File.separatorChar, '/'), "");
1007  12 return org.createRelative(ne.toString()).toString();
1008    }
1009   
1010    /**
1011    * Waits until a '\n' was read from System.in.
1012    */
 
1013  1 toggle public static void waitln() {
1014  1 System.out.println("\n..press <return> to continue");
1015  1 try {
1016  1 (new java.io.BufferedReader(new java.io.InputStreamReader(
1017    System.in))).readLine();
1018    } catch (IOException e) {
1019    // ignore
1020    }
1021    }
1022   
1023    /**
1024    * Closes input stream without exception.
1025    *
1026    * @param in Input stream, maybe <code>null</code>.
1027    */
 
1028  200221 toggle public static void close(final InputStream in) {
1029  200221 if (in != null) {
1030  200205 try {
1031  200205 in.close();
1032    } catch (Exception e) {
1033    // ignore
1034    }
1035    }
1036    }
1037   
1038    /**
1039    * Closes writer without exception.
1040    *
1041    * @param writer Writer, maybe <code>null</code>.
1042    */
 
1043  8 toggle public static void close(final Writer writer) {
1044  8 if (writer != null) {
1045  7 try {
1046  7 writer.close();
1047    } catch (Exception e) {
1048    // ignore
1049    }
1050    }
1051    }
1052   
1053    /**
1054    * Closes out stream without exception.
1055    *
1056    * @param out Output stream, maybe <code>null</code>.
1057    */
 
1058  1067 toggle public static void close(final OutputStream out) {
1059  1067 if (out != null) {
1060  999 try {
1061  999 out.close();
1062    } catch (Exception e) {
1063    // ignore
1064    }
1065    }
1066    }
1067   
1068    /**
1069    * Closes input reader without exception.
1070    *
1071    * @param reader Reader, maybe <code>null</code>.
1072    */
 
1073  191716 toggle public static void close(final Reader reader) {
1074  191716 if (reader != null) {
1075  191702 try {
1076  191702 reader.close();
1077    } catch (Exception e) {
1078    // ignore
1079    }
1080    }
1081    }
1082   
1083    /**
1084    * Get start directory for application. Within the start directory all newly created data is
1085    * stored in. If this is no Java Webstart version the result is
1086    * <code>new File(".")</code>. Otherwise the start directory is the subdirectory
1087    * "." concatenated <code>application</code> within <code>user.home</code>.
1088    *
1089    * @param application Application name, used for Java Webstart version. Should
1090    * be written in lowercase letters. A "." is automatically appended at
1091    * the beginning.
1092    * @return Start directory for application.
1093    */
 
1094  2 toggle public static final File getStartDirectory(final String application) {
1095  2 final File startDirectory;
1096  2 if (isWebStarted()) {
1097  1 startDirectory = new File(getUserHomeDirectory(), "." + application);
1098    } else {
1099  1 startDirectory = new File(".");
1100    }
1101  2 return startDirectory;
1102    }
1103   
1104    /**
1105    * Was the application started by Java Webstart?
1106    *
1107    * @return Was the application started by Java Webstart.
1108    */
 
1109  9 toggle public static final boolean isWebStarted() {
1110  9 final String webStart = (String) System.getProperties().get("javawebstart.version");
1111  9 return webStart != null;
1112    }
1113   
1114    /**
1115    * Loads a property file from given URL.
1116    *
1117    * @param url URL to load properties from. Must not be <code>null</code>.
1118    * @return Loaded properties.
1119    * @throws IOException Reading error.
1120    */
 
1121  2 toggle public static Properties loadProperties(final URL url)
1122    throws IOException {
1123  2 Properties newprops = new Properties();
1124  2 InputStream in = null;
1125  2 try {
1126  2 in = url.openStream();
1127  1 newprops.load(in);
1128    } finally {
1129  2 close(in);
1130    }
1131  1 return newprops;
1132    }
1133   
1134    /**
1135    * Sleep my little class.
1136    *
1137    * @param ms Milliseconds to wait.
1138    */
 
1139  1 toggle public static void sleep(final int ms) {
1140  1 final Object monitor = new Object();
1141  1 synchronized (monitor) {
1142  1 try {
1143  1 monitor.wait(ms);
1144    } catch (InterruptedException e) {
1145    }
1146    }
1147    }
1148   
1149    /**
1150    * Get currently running java version and subversion numbers. This is the running JRE version.
1151    * If no version could be identified <code>null</code> is returned.
1152    *
1153    * @return Array of version and subversion numbers.
1154    */
 
1155  498 toggle public static int[] getJavaVersion() {
1156  498 final String version = System.getProperty("java.version");
1157  498 final List numbers = new ArrayList();
1158  498 final StringTokenizer tokenizer = new StringTokenizer(version, ".");
1159  1992 while (tokenizer.hasMoreElements()) {
1160  1494 String sub = tokenizer.nextToken();
1161  2988 for (int i = 0; i < sub.length(); i++) {
1162  1992 if (!Character.isDigit(sub.charAt(i))) {
1163  498 sub = sub.substring(0, i);
1164  498 break;
1165    }
1166    }
1167  1494 try {
1168  1494 numbers.add(new Integer(Integer.parseInt(sub)));
1169    } catch (Exception e) {
1170  0 e.printStackTrace();
1171  0 break;
1172    }
1173    }
1174  498 if (numbers.size() == 0) {
1175  0 return null;
1176    }
1177  498 final int[] result = new int[numbers.size()];
1178  1992 for (int i = 0; i < numbers.size(); i++) {
1179  1494 result[i] = ((Integer) numbers.get(i)).intValue();
1180    }
1181  498 return result;
1182    }
1183   
1184    /**
1185    * Get key sorted list of all System Properties.
1186    *
1187    * @return Array with the two columns key and value.
1188    */
 
1189  1 toggle public static String[][] getSortedSystemProperties() {
1190  1 final Map map = new TreeMap(System.getProperties());
1191  1 String[][] rowData = new String[map.size()][2];
1192  1 int rowNum = 0;
1193  1 final Iterator iterator = map.entrySet().iterator();
1194  54 while (iterator.hasNext()) {
1195  53 Map.Entry entry = (Map.Entry) iterator.next();
1196  53 rowData[rowNum][0] = (String) entry.getKey();
1197  53 rowData[rowNum][1] = (String) entry.getValue();
1198  53 rowNum++;
1199    }
1200  1 return rowData;
1201    }
1202   
1203    }