Clover Coverage Report
Coverage timestamp: Thu Feb 13 2014 22:50:26 UTC
../../../../img/srcFileCovDistChart10.png 0% of files have more coverage
387   1,212   161   7.74
158   694   0.42   50
50     3.22  
1    
 
  IoUtility       Line # 58 387 161 91.3% 0.91260505
 
  (56)
 
1    /* This file is part of the project "Hilbert II" - http://www.qedeq.org
2    *
3    * Copyright 2000-2014, 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  10 toggle public static String loadStreamWithoutException(final InputStream in, final int maxLength) {
163   
164  10 if (in == null) {
165  2 return "";
166    }
167  8 final StringBuffer buffer = new StringBuffer();
168  8 buffer.setLength(0);
169  8 try {
170  8 int counter = 0;
171  8 int c;
172  6184 while (counter++ < maxLength) {
173  6178 c = in.read();
174  6178 if (c < 0) {
175  2 break;
176    }
177  6176 buffer.append((char) c);
178    }
179    } catch (IOException e) {
180    // ignored
181    } catch (RuntimeException e) {
182    // ignored
183    }
184  8 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  1 toggle public static void loadReader(final Reader in, final StringBuffer buffer)
195    throws IOException {
196   
197  1 buffer.setLength(0);
198  1 int c;
199  ? while ((c = in.read()) >= 0) {
200  37 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  9 toggle public static void loadFile(final File file,
242    final StringBuffer buffer, final String encoding)
243    throws IOException {
244   
245  9 buffer.setLength((int) file.length()); // ensure capacity
246  9 buffer.setLength(0);
247  9 final InputStreamReader in = new InputStreamReader(new FileInputStream(file), encoding);
248  9 final char[] data = new char[10 * 1024];
249   
250  9 try {
251  9 int charsread = 0;
252  ? while (0 < (charsread = in.read(data, 0, data.length))) {
253  9 buffer.append(data, 0, charsread);
254    }
255    } finally {
256  9 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  9 toggle public static void saveFile(final InputStream in, final File file) throws IOException {
364  9 createNecessaryDirectories(file);
365  9 FileOutputStream out = null;
366  9 try {
367  9 out = new FileOutputStream(file);
368  9 final byte[] data = new byte[8 * 1024];
369  9 int length;
370  ? while ((length = in.read(data)) != -1) {
371  9 out.write(data, 0, length);
372    }
373    } finally {
374  9 close(in);
375  9 close(out);
376    }
377    }
378   
379    /**
380    * Convert String into a {@link Reader}.
381    *
382    * <a href="http://bugs.sun.com/bugdatabase/view_bug.do;:WuuT?bug_id=4094886">
383    * Bug ID: 4094886</a>
384    *
385    * @param data Convert this.
386    * @return Resulting reader.
387    */
 
388  1 toggle public static final Reader stringToReader(final String data) {
389  1 try {
390  1 return new InputStreamReader(new ByteArrayInputStream(data.getBytes("ISO-8859-1")));
391    } catch (UnsupportedEncodingException e) {
392    // should never occur
393  0 throw new RuntimeException(e);
394    }
395    }
396   
397    /**
398    * Saves a <code>String</code> into a file. Existing files are overwritten.
399    *
400    * @param filename Name of the file (could include path).
401    * @param text Data to save in the file.
402    * @throws IOException File exception occurred.
403    *
404    * @deprecated Use {@link #saveFile(File, String, String)} that has an encoding.
405    */
 
406  1 toggle public static void saveFile(final String filename, final String text)
407    throws IOException {
408  1 saveFile(new File(filename), text);
409    }
410   
411    /**
412    * Saves a <code>StringBuffer</code> in a file. Existing files are overwritten.
413    *
414    * @param filename Name of the file (could include path).
415    * @param text Data to save in the file.
416    * @throws IOException File exception occurred.
417    *
418    * @deprecated Use {@link #saveFile(File, StringBuffer, String)} that has an encoding.
419    */
 
420  1 toggle public static void saveFile(final String filename, final StringBuffer text)
421    throws IOException {
422  1 saveFile(new File(filename), text.toString());
423    }
424   
425    /**
426    * Saves a <code>StringBuffer</code> in a file. Existing files are overwritten.
427    *
428    * @param file File to save into.
429    * @param text Data to save in the file.
430    * @throws IOException File exception occurred.
431    *
432    * @deprecated Use {@link #saveFile(File, StringBuffer, String)} that has an encoding
433    * parameter.
434    */
 
435  1 toggle public static void saveFile(final File file, final StringBuffer text)
436    throws IOException {
437  1 saveFile(file, text.toString());
438    }
439   
440    /**
441    * Saves a <code>String</code> in a file. Uses default encoding. Existing files are
442    * overwritten.
443    *
444    * @param file File to save the data in.
445    * @param text Data to save in the file.
446    * @throws IOException File exception occurred.
447    *
448    * @deprecated Use {@link #saveFile(File, String, String)} that has an encoding parameter.
449    */
 
450  5 toggle public static void saveFile(final File file, final String text)
451    throws IOException {
452  5 createNecessaryDirectories(file);
453  5 BufferedWriter out = null;
454  5 try {
455  5 out = new BufferedWriter(new FileWriter(file));
456  5 out.write(text);
457    } finally {
458  5 close(out);
459    }
460    }
461   
462    /**
463    * Saves a <code>String</code> in a file. Existing files are overwritten.
464    *
465    * @param file File to save the data in.
466    * @param text Data to save in the file.
467    * @param encoding Use this encoding.
468    * @throws IOException File exception occurred.
469    */
 
470  4 toggle public static void saveFile(final File file, final StringBuffer text, final String encoding)
471    throws IOException {
472  4 saveFile(file, text.toString(), encoding);
473    }
474   
475    /**
476    * Saves a <code>String</code> in a file.
477    *
478    * @param file File to save the data in.
479    * @param text Data to save in the file.
480    * @param encoding Use this encoding.
481    * @throws IOException File exception occurred.
482    */
 
483  137 toggle public static void saveFile(final File file, final String text, final String encoding)
484    throws IOException {
485  137 createNecessaryDirectories(file);
486  137 BufferedWriter out = new BufferedWriter(
487    new OutputStreamWriter(new FileOutputStream(file), encoding));
488  136 try {
489  136 out.write(text);
490    } finally {
491  136 out.close();
492    }
493    }
494   
495    /**
496    * Saves a <code>data</code> in a file. Existing files are overwritten.
497    *
498    * @param file File to save the data in.
499    * @param data Data to save in the file.
500    * @throws IOException File exception occurred.
501    */
 
502  23 toggle public static void saveFileBinary(final File file, final byte[] data)
503    throws IOException {
504  23 createNecessaryDirectories(file);
505  23 BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
506  23 try {
507  23 out.write(data);
508    } finally {
509  23 out.close();
510    }
511    }
512   
513    /**
514    * Copies a file to a different location.
515    *
516    * @param from Copy source.
517    * @param to Copy destination.
518    * @throws IOException File exception occurred.
519    */
 
520  11 toggle public static void copyFile(final File from, final File to)
521    throws IOException {
522   
523  11 if (from.getCanonicalFile().equals(to.getCanonicalFile())) {
524  1 return;
525    }
526  10 createNecessaryDirectories(to);
527  10 FileInputStream in = null;
528  10 FileOutputStream out = null;
529  10 try {
530  10 in = new FileInputStream(from);
531  10 out = new FileOutputStream(to);
532   
533  10 byte[] data = new byte[8 * 1024];
534  10 int length;
535  ? while ((length = in.read(data)) != -1) {
536  10 out.write(data, 0, length);
537    }
538    } finally {
539  10 close(in);
540  10 close(out);
541    }
542    }
543   
544    /**
545    * Copy one file or directory to another location.
546    * If targetLocation does not exist, it will be created.
547    *
548    * @param sourceLocation Copy from here. This can be a file or a directory.
549    * @param targetLocation Copy to this location. If source is a file this must be a file too.
550    * @throws IOException Something went wrong.
551    */
 
552  1 toggle public static void copy(final String sourceLocation, final String targetLocation)
553    throws IOException {
554  1 copy(new File(sourceLocation), new File(targetLocation));
555    }
556   
557    /**
558    * Copy one directory to another location.
559    * If targetLocation does not exist, it will be created.
560    *
561    * @param sourceLocation Copy from here.
562    * @param targetLocation Copy to this location
563    * @throws IOException Something went wrong.
564    */
 
565  15 toggle public static void copy(final File sourceLocation, final File targetLocation)
566    throws IOException {
567   
568  15 if (sourceLocation.isDirectory()) {
569  6 if (!targetLocation.exists()) {
570  6 targetLocation.mkdir();
571    }
572  6 String[] children = sourceLocation.list();
573  18 for (int i = 0; i < children.length; i++) { // recursive call for all children
574  12 copy(new File(sourceLocation, children[i]),
575    new File(targetLocation, children[i]));
576    }
577    } else { // copy file
578  9 copyFile(sourceLocation, targetLocation);
579    }
580    }
581   
582    /**
583    * List all matching files. Searches all matching sub directories recursively.
584    * Remember to return <code>true</code> for <code>accept(File pathname)</code> if
585    * <code>pathname</code> is a directory if you want to search all sub directories!
586    * If <code>sourceLocation</code> is a single file, this is the only file that will
587    * be in the resulting list.
588    *
589    * @param sourceLocation Check all files in this directory. (Or add this single file.)
590    * @param filter Accept only these directories and files.
591    * @return List of matching files. Contains no directories.
592    * @throws IOException Something went wrong.
593    */
 
594  6 toggle public static List listFilesRecursively(final File sourceLocation, final FileFilter filter)
595    throws IOException {
596  6 final List result = new ArrayList();
597  6 if (sourceLocation.isDirectory()) {
598  5 final File[] children = sourceLocation.listFiles();
599  25 for (int i = 0; i < children.length; i++) { // recursive call for all children
600  20 result.addAll(listFilesRecursivelyIntern(children[i], filter));
601    }
602    } else {
603  1 result.add(sourceLocation);
604    }
605  6 return result;
606    }
607   
608    /**
609    * List all matching files. Searches all matching sub directories recursively.
610    * Remember to return <code>true</code> for <code>accept(File pathname)</code> if
611    * <code>pathname</code> is a directory if you want to search all sub directories!
612    *
613    * @param sourceLocation Check all files in this directory.
614    * @param filter Accept only these directories and files.
615    * @return List of matching files. Contains no directories.
616    * @throws IOException Something went wrong.
617    */
 
618  24 toggle private static List listFilesRecursivelyIntern(final File sourceLocation,
619    final FileFilter filter) throws IOException {
620  24 final List result = new ArrayList();
621  24 if (filter.accept(sourceLocation)) {
622  11 if (sourceLocation.isDirectory()) {
623  4 File[] children = sourceLocation.listFiles();
624  8 for (int i = 0; i < children.length; i++) { // recursive call for all children
625  4 result.addAll(listFilesRecursivelyIntern(children[i], filter));
626    }
627    } else {
628  7 result.add(sourceLocation);
629    }
630    }
631  24 return result;
632    }
633   
634    /**
635    * Compare two files binary.
636    *
637    * @param from Compare source. This file must be <code>null</code> or be an existing file.
638    * @param with Compare with this file. This file must be <code>null</code> or be an
639    * existing file.
640    * @return Is the contents of the two files binary equal?
641    * @throws IOException File exception occurred.
642    */
 
643  34 toggle public static boolean compareFilesBinary(final File from, final File with)
644    throws IOException {
645  34 if (from == null && with == null) {
646  1 return true;
647    }
648  33 if (from == null || with == null) {
649  2 return false;
650    }
651  31 if (from.getAbsoluteFile().equals(with.getAbsoluteFile())) {
652  3 return true;
653    }
654  28 if (from.length() != with.length()) {
655  5 return false;
656    }
657  23 byte[] dataOne = new byte[8 * 1024];
658  23 byte[] dataTwo = new byte[8 * 1024];
659  23 int length;
660   
661  23 FileInputStream one = null;
662  23 FileInputStream two = null;
663  23 try {
664  23 one = new FileInputStream(from);
665  22 two = new FileInputStream(with);
666   
667  ? while ((length = one.read(dataOne)) != -1) {
668  22 if (length != two.read(dataTwo)) {
669  0 return false;
670    }
671  22 if (!Arrays.equals(dataOne, dataTwo)) {
672  2 return false;
673    }
674    }
675  20 return true;
676    } finally {
677  23 close(one);
678  23 close(two);
679    }
680    }
681   
682    /**
683    * Compare two text files. Ignores different line separators. As there are:
684    * LF, CR, CR + LF, NEL, FF, LS, PS.
685    *
686    * @param from Compare source.
687    * @param with Compare with this file.
688    * @param encoding Use this character encoding. Must not be <code>null</code>.
689    * @return Is the contents of the two text files equal?
690    * @throws IOException File exception occurred or encoding is not supported.
691    * @throws NullPointerException Is encoding different from <code>null</code>?
692    */
 
693  75 toggle public static boolean compareTextFiles(final File from, final File with, final String encoding)
694    throws IOException {
695  75 if (from == null && with == null) {
696  1 return true;
697    }
698  74 if (from == null || with == null) {
699  4 return false;
700    }
701  70 if (from.getAbsoluteFile().equals(with.getAbsoluteFile())) {
702  3 return true;
703    }
704   
705  67 BufferedReader one = null;
706  67 BufferedReader two = null;
707  67 FileInputStream fromIn = null;
708  67 FileInputStream withIn = null;
709  67 try {
710  67 fromIn = new FileInputStream(from);
711  66 one = new BufferedReader(new InputStreamReader(fromIn, encoding));
712  63 withIn = new FileInputStream(with);
713  63 two = new BufferedReader(new InputStreamReader(withIn, encoding));
714   
715  63 boolean crOne = false;
716  63 boolean crTwo = false;
717  63 do {
718  39600 int readOne = one.read();
719  39600 int readTwo = two.read();
720  39600 if (readOne == readTwo) {
721  38827 if (readOne < 0) {
722  42 break;
723    }
724    } else {
725  773 crOne = readOne == 0x0D;
726  773 crTwo = readTwo == 0x0D;
727  773 if (crOne) {
728  375 readOne = one.read();
729    }
730  773 if (crTwo) {
731  375 readTwo = two.read();
732    }
733  773 if (crOne && readOne != 0x0A && isCr(readTwo)) {
734  64 readTwo = two.read();
735    }
736  773 if (crTwo && readTwo != 0x0A && isCr(readOne)) {
737  64 readOne = one.read();
738    }
739  773 if (readOne != readTwo && (!isCr(readOne) && !isCr(readTwo))) {
740  21 return false;
741    }
742    }
743    } while (true);
744  42 return true;
745    } finally {
746  67 close(fromIn);
747  67 close(one);
748  67 close(two);
749  67 close(withIn);
750    }
751    }
752   
753    /**
754    * Compare two text files. Ignores different line separators. As there are:
755    * LF, CR, CR + LF
756    *
757    * @param from Compare source.
758    * @param with Compare with this file.
759    * @param startAtLine Start comparing at this line (beginning with 0).
760    * @param encoding Use this character encoding. Must not be <code>null</code>.
761    * @return Is the contents of the two text files equal?
762    * @throws IOException File exception occurred or encoding is not supported.
763    * @throws NullPointerException Is encoding different from <code>null</code>?
764    */
 
765  148 toggle public static boolean compareTextFiles(final File from, final File with, final int startAtLine,
766    final String encoding) throws IOException {
767   
768  148 if (from == null && with == null) {
769  3 return true;
770    }
771  145 if (from == null || with == null) {
772  6 return false;
773    }
774  139 if (from.getAbsoluteFile().equals(with.getAbsoluteFile())) {
775  3 return true;
776    }
777  136 if (startAtLine < 0) {
778  38 return true;
779    }
780  98 BufferedReader one = null;
781  98 BufferedReader two = null;
782  98 FileInputStream fromIn = null;
783  98 FileInputStream withIn = null;
784  98 try {
785  98 fromIn = new FileInputStream(from);
786  98 one = new BufferedReader(new InputStreamReader(fromIn, encoding));
787  96 withIn = new FileInputStream(with);
788  96 two = new BufferedReader(new InputStreamReader(withIn, encoding));
789  96 int pos = 0;
790  96 do {
791  2346 String lineOne = one.readLine();
792  2346 String lineTwo = two.readLine();
793  2346 if (lineOne == null) {
794  68 if (lineTwo == null) {
795  68 break;
796    }
797  0 return false;
798    }
799  2278 if (pos++ >= startAtLine && !lineOne.equals(lineTwo)) {
800  28 return false;
801    }
802    } while (true);
803  68 return true;
804    } finally {
805  98 close(fromIn);
806  98 close(one);
807  98 close(two);
808  98 close(withIn);
809    }
810    }
811   
812    /**
813    * Test if character is LF, CR, NEL, FF, LS, PS.
814    * @param c Character to test.
815    * @return Is character a line terminator?
816    */
 
817  464 toggle private static boolean isCr(final int c) {
818  464 return c == 0x0A || c == 0x0D || c == 0x85 || c == 0x0C || c == 0x2028 || c == 0x2029;
819    }
820   
821    /**
822    * Delete file directory recursive.
823    *
824    * @param directory Directory to delete. Must not be a symbolic link.
825    * @param deleteDir Delete directory itself too?
826    * @return Was deletion successful?
827    */
 
828  30 toggle public static boolean deleteDir(final File directory, final boolean deleteDir) {
829   
830    // first we check if the file is a symbolic link
831  30 try {
832  30 if (isSymbolicLink(directory)) {
833  0 return false;
834    }
835    } catch (IOException e) {
836  0 return false;
837    }
838  30 final File candir;
839  30 try {
840  30 candir = directory.getCanonicalFile();
841    } catch (IOException e) {
842  0 return false;
843    }
844   
845    // now we go through all of the files and subdirectories in the
846    // directory and delete them one by one
847  30 boolean success = true;
848  30 File[] files = candir.listFiles();
849  30 if (files != null) {
850  65 for (int i = 0; i < files.length; i++) {
851  39 File file = files[i];
852   
853    // in case this directory is actually a symbolic link, or it's
854    // empty, we want to try to delete the link before we try
855    // anything
856  39 boolean deleted = file.delete();
857  39 if (!deleted) {
858    // deleting the file failed, so maybe it's a non-empty
859    // directory
860  16 if (file.isDirectory()) {
861  16 deleted = deleteDir(file, true);
862    }
863   
864    // otherwise, there's nothing else we can do
865    }
866  39 success = success && deleted;
867    }
868    }
869   
870    // now that we tried to clear the directory out, we can try to delete it
871  30 if (deleteDir && directory.exists()) {
872  26 return directory.delete();
873    }
874  4 return success;
875    }
876   
877    /**
878    * Delete directory contents for all files that match the filter. The main directory itself is
879    * not deleted.
880    *
881    * @param directory Directory to scan for files to delete.
882    * @param filter Filter files (and directories) to delete.
883    * @return Was deletion successful?
884    */
 
885  1 toggle public static boolean deleteDir(final File directory, final FileFilter filter) {
886    // first we check if the file is a symbolic link
887  1 try {
888  1 if (isSymbolicLink(directory)) {
889  0 return false;
890    }
891    } catch (IOException e) {
892  0 return false;
893    }
894  1 final File candir;
895  1 try {
896  1 candir = directory.getCanonicalFile();
897    } catch (IOException e) {
898  0 return false;
899    }
900   
901    // now we go through all of the files and subdirectories in the
902    // directory and delete them one by one
903  1 boolean success = true;
904  1 File[] files = candir.listFiles(filter);
905  1 if (files != null) {
906  4 for (int i = 0; i < files.length; i++) {
907  3 File file = files[i];
908   
909    // in case this directory is actually a symbolic link, or it's
910    // empty, we want to try to delete the link before we try
911    // anything
912  3 boolean deleted = file.delete();
913  3 if (!deleted) {
914    // deleting the file failed, so maybe it's a non-empty
915    // directory
916  1 if (file.isDirectory()) {
917  1 deleted = deleteDir(file, true);
918    }
919   
920    // otherwise, there's nothing else we can do
921    }
922  3 success = success && deleted;
923    }
924    }
925   
926  1 return success;
927    }
928   
929    /**
930    * Determines whether the specified file is a symbolic link rather than an actual file.
931    * See {@link
932    * https://svn.apache.org/repos/asf/commons/proper/io/trunk/src/main/java/org/apache/commons/io/FileUtils.java}.
933    * @param file File to check.
934    * @return Is the file is a symbolic link?
935    * @throws IOException IO error while checking the file.
936    */
 
937  31 toggle public static boolean isSymbolicLink(final File file) throws IOException {
938  31 if (file == null) {
939  0 throw new NullPointerException("File must not be null");
940    }
941    // is windows file system in use?
942  31 if (File.separatorChar == '\\') {
943    // we have no symbolic links
944  0 return false;
945    }
946  31 File fileInCanonicalDir = null;
947  31 if (file.getParent() == null) {
948  1 fileInCanonicalDir = file;
949    } else {
950  30 File canonicalDir = file.getParentFile().getCanonicalFile();
951  30 fileInCanonicalDir = new File(canonicalDir, file.getName());
952    }
953  31 if (fileInCanonicalDir.getCanonicalFile().equals(fileInCanonicalDir.getAbsoluteFile())) {
954  31 return false;
955    }
956  0 return true;
957    }
958   
959    /**
960    * Print current system properties to System.out.
961    */
 
962  1 toggle public static void printAllSystemProperties() {
963  1 Properties sysprops = System.getProperties();
964  54 for (Enumeration e = sysprops.propertyNames(); e.hasMoreElements(); ) {
965  53 String key = (String) e.nextElement();
966  53 String value = sysprops.getProperty(key);
967  53 System.out.println(key + "=" + value);
968    }
969    }
970   
971    /**
972    * Get home directory of user.
973    *
974    * @return Home directory of user.
975    */
 
976  4 toggle public static File getUserHomeDirectory() {
977  4 return new File((String) System.getProperties().get("user.home"));
978    }
979   
980    /**
981    * Creates necessary parent directories for a file.
982    *
983    * @param file File.
984    * @throws IOException Creation failed.
985    */
 
986  187 toggle public static void createNecessaryDirectories(final File file) throws IOException {
987  187 if (file != null && file.getParentFile() != null) {
988  185 file.getParentFile().mkdirs();
989  185 if (!file.getParentFile().exists()) {
990  0 throw new IOException("directory creation failed: " + file.getParent());
991    }
992    }
993    }
994   
995    /**
996    * Create relative address from <code>origin</code> to <code>next</code>.
997    * The resulting file path has "/" as directory name separator.
998    * If the resulting file path is the same as origin specifies, we return "".
999    * Otherwise the result will always have an "/" as last character.
1000    *
1001    * @param origin This is the original location. Must be a directory.
1002    * @param next This should be the next location. Must also be a directory.
1003    * @return Relative (or if necessary absolute) file path.
1004    */
 
1005  8 toggle public static final String createRelativePath(final File origin, final File next) {
1006  8 if (origin.equals(next)) {
1007  2 return "";
1008    }
1009  6 final Path org = new Path(origin.getPath().replace(File.separatorChar, '/'), "");
1010  6 final Path ne = new Path(next.getPath().replace(File.separatorChar, '/'), "");
1011  6 return org.createRelative(ne.toString()).toString();
1012    }
1013   
1014    /**
1015    * Waits until a '\n' was read from System.in.
1016    */
 
1017  1 toggle public static void waitln() {
1018  1 System.out.println("\n..press <return> to continue");
1019  1 try {
1020  1 (new java.io.BufferedReader(new java.io.InputStreamReader(
1021    System.in))).readLine();
1022    } catch (IOException e) {
1023    // ignore
1024    }
1025    }
1026   
1027    /**
1028    * Closes input stream without exception.
1029    *
1030    * @param in Input stream, maybe <code>null</code>.
1031    */
 
1032  409 toggle public static void close(final InputStream in) {
1033  409 if (in != null) {
1034  398 try {
1035  398 in.close();
1036    } catch (Exception e) {
1037    // ignore
1038    }
1039    }
1040    }
1041   
1042    /**
1043    * Closes writer without exception.
1044    *
1045    * @param writer Writer, maybe <code>null</code>.
1046    */
 
1047  8 toggle public static void close(final Writer writer) {
1048  8 if (writer != null) {
1049  7 try {
1050  7 writer.close();
1051    } catch (Exception e) {
1052    // ignore
1053    }
1054    }
1055    }
1056   
1057    /**
1058    * Closes out stream without exception.
1059    *
1060    * @param out Output stream, maybe <code>null</code>.
1061    */
 
1062  23 toggle public static void close(final OutputStream out) {
1063  23 if (out != null) {
1064  22 try {
1065  22 out.close();
1066    } catch (Exception e) {
1067    // ignore
1068    }
1069    }
1070    }
1071   
1072    /**
1073    * Closes input reader without exception.
1074    *
1075    * @param reader Reader, maybe <code>null</code>.
1076    */
 
1077  340 toggle public static void close(final Reader reader) {
1078  340 if (reader != null) {
1079  326 try {
1080  326 reader.close();
1081    } catch (Exception e) {
1082    // ignore
1083    }
1084    }
1085    }
1086   
1087    /**
1088    * Get start directory for application. Within the start directory all newly created data is
1089    * stored in. If this is no Java Webstart version the result is
1090    * <code>new File(".")</code>. Otherwise the start directory is the subdirectory
1091    * "." concatenated <code>application</code> within <code>user.home</code>.
1092    * If a system property <code>application + ".startDirectory"</code> is defined we take this
1093    * as the start directory.
1094    *
1095    * @param application Application name, used for Java Webstart version. Should
1096    * be written in lowercase letters. A "." is automatically appended at
1097    * the beginning.
1098    * @return Start directory for application.
1099    */
 
1100  2 toggle public static final File getStartDirectory(final String application) {
1101  2 final File startDirectory;
1102  2 final String property = System.getProperty(application + ".startDirectory");
1103  2 if (property != null && property.length() > 0) {
1104  0 startDirectory = new File(property);
1105  2 } else if (isWebStarted()) {
1106  1 startDirectory = new File(getUserHomeDirectory(), "." + application);
1107    } else {
1108  1 startDirectory = new File(".");
1109    }
1110  2 return startDirectory;
1111    }
1112   
1113    /**
1114    * Was the application started by Java Webstart?
1115    *
1116    * @return Was the application started by Java Webstart.
1117    */
 
1118  3 toggle public static final boolean isWebStarted() {
1119  3 final String webStart = (String) System.getProperties().get("javawebstart.version");
1120  3 return webStart != null;
1121    }
1122   
1123    /**
1124    * Loads a property file from given URL.
1125    *
1126    * @param url URL to load properties from. Must not be <code>null</code>.
1127    * @return Loaded properties.
1128    * @throws IOException Reading error.
1129    */
 
1130  2 toggle public static Properties loadProperties(final URL url)
1131    throws IOException {
1132  2 Properties newprops = new Properties();
1133  2 InputStream in = null;
1134  2 try {
1135  2 in = url.openStream();
1136  1 newprops.load(in);
1137    } finally {
1138  2 close(in);
1139    }
1140  1 return newprops;
1141    }
1142   
1143    /**
1144    * Sleep my little class.
1145    *
1146    * @param ms Milliseconds to wait.
1147    */
 
1148  1 toggle public static void sleep(final int ms) {
1149  1 final Object monitor = new Object();
1150  1 synchronized (monitor) {
1151  1 try {
1152  1 monitor.wait(ms);
1153    } catch (InterruptedException e) {
1154    }
1155    }
1156    }
1157   
1158    /**
1159    * Get currently running java version and subversion numbers. This is the running JRE version.
1160    * If no version could be identified <code>null</code> is returned.
1161    *
1162    * @return Array of version and subversion numbers.
1163    */
 
1164  1 toggle public static int[] getJavaVersion() {
1165  1 final String version = System.getProperty("java.version");
1166  1 final List numbers = new ArrayList();
1167  1 final StringTokenizer tokenizer = new StringTokenizer(version, ".");
1168  4 while (tokenizer.hasMoreElements()) {
1169  3 String sub = tokenizer.nextToken();
1170  6 for (int i = 0; i < sub.length(); i++) {
1171  4 if (!Character.isDigit(sub.charAt(i))) {
1172  1 sub = sub.substring(0, i);
1173  1 break;
1174    }
1175    }
1176  3 try {
1177  3 numbers.add(new Integer(Integer.parseInt(sub)));
1178    } catch (Exception e) {
1179  0 e.printStackTrace();
1180  0 break;
1181    }
1182    }
1183  1 if (numbers.size() == 0) {
1184  0 return null;
1185    }
1186  1 final int[] result = new int[numbers.size()];
1187  4 for (int i = 0; i < numbers.size(); i++) {
1188  3 result[i] = ((Integer) numbers.get(i)).intValue();
1189    }
1190  1 return result;
1191    }
1192   
1193    /**
1194    * Get key sorted list of all System Properties.
1195    *
1196    * @return Array with the two columns key and value.
1197    */
 
1198  1 toggle public static String[][] getSortedSystemProperties() {
1199  1 final Map map = new TreeMap(System.getProperties());
1200  1 String[][] rowData = new String[map.size()][2];
1201  1 int rowNum = 0;
1202  1 final Iterator iterator = map.entrySet().iterator();
1203  54 while (iterator.hasNext()) {
1204  53 Map.Entry entry = (Map.Entry) iterator.next();
1205  53 rowData[rowNum][0] = (String) entry.getKey();
1206  53 rowData[rowNum][1] = (String) entry.getValue();
1207  53 rowNum++;
1208    }
1209  1 return rowData;
1210    }
1211   
1212    }