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