Clover coverage report - QedeqKernelSe Coverage Report
Coverage timestamp: Sa Dez 22 2007 01:35:21 CET
file stats: LOC: 748   Methods: 34
NCLOC: 406   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
IoUtility.java 33,7% 54,8% 55,9% 49%
coverage coverage
 1    /* $Id: IoUtility.java,v 1.13 2007/12/21 23:33:47 m31 Exp $
 2    *
 3    * This file is part of the project "Hilbert II" - http://www.qedeq.org
 4    *
 5    * Copyright 2000-2007, Michael Meyling <mime@qedeq.org>.
 6    *
 7    * "Hilbert II" is free software; you can redistribute
 8    * it and/or modify it under the terms of the GNU General Public
 9    * License as published by the Free Software Foundation; either
 10    * version 2 of the License, or (at your option) any later version.
 11    *
 12    * This program is distributed in the hope that it will be useful,
 13    * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15    * GNU General Public License for more details.
 16    */
 17   
 18    package org.qedeq.kernel.utility;
 19   
 20    import java.io.BufferedOutputStream;
 21    import java.io.BufferedReader;
 22    import java.io.BufferedWriter;
 23    import java.io.ByteArrayInputStream;
 24    import java.io.ByteArrayOutputStream;
 25    import java.io.File;
 26    import java.io.FileInputStream;
 27    import java.io.FileOutputStream;
 28    import java.io.FileReader;
 29    import java.io.FileWriter;
 30    import java.io.IOException;
 31    import java.io.InputStream;
 32    import java.io.InputStreamReader;
 33    import java.io.Reader;
 34    import java.io.UnsupportedEncodingException;
 35    import java.net.MalformedURLException;
 36    import java.net.URL;
 37    import java.util.Arrays;
 38    import java.util.Enumeration;
 39    import java.util.Properties;
 40   
 41   
 42    /**
 43    * A collection of useful static methods for input and output.
 44    *
 45    * LATER mime 20070101: use StringBuilder instead of StringBuffer if working under JDK 1.5
 46    *
 47    * FIXME mime 20070926: load* and loadBinary are mixed. loarUrl should be binary load!
 48    *
 49    * @version $Revision: 1.13 $
 50    * @author Michael Meyling
 51    */
 52    public final class IoUtility {
 53   
 54    /**
 55    * Constructor, should never be called.
 56    */
 57  0 private IoUtility() {
 58    // don't call me
 59    }
 60   
 61    /**
 62    * Reads a file and returns the contents as a <code>String</code>.
 63    *
 64    * @param filename Name of the file (could include path).
 65    * @return Contents of file.
 66    * @throws IOException File exception occurred.
 67    */
 68  0 public static String loadFile(final String filename)
 69    throws IOException {
 70   
 71  0 final StringBuffer buffer = new StringBuffer();
 72  0 loadFile(filename, buffer);
 73  0 return buffer.toString();
 74    }
 75   
 76    /**
 77    * Reads contents of a file into a string buffer.
 78    *
 79    * @param filename Name of the file (could include path).
 80    * @param buffer Buffer to fill with file contents.
 81    * @throws IOException File exception occurred.
 82    */
 83  0 public static void loadFile(final String filename,
 84    final StringBuffer buffer)
 85    throws IOException {
 86  0 loadFile(new File(filename), buffer);
 87    }
 88   
 89    /**
 90    * Reads contents of a stream into a string buffer.
 91    *
 92    * @param in This stream will be loaded.
 93    * @param buffer Buffer to fill with file contents.
 94    * @throws IOException File exception occurred.
 95    */
 96  0 public static void loadStream(final InputStream in,
 97    final StringBuffer buffer)
 98    throws IOException {
 99   
 100  0 buffer.setLength(0);
 101  0 int c;
 102  0 while ((c = in.read()) >= 0) {
 103  0 buffer.append((char) c);
 104    }
 105    }
 106   
 107    /**
 108    * Reads contents of a file into a string buffer.
 109    *
 110    * @param file This file will be loaded.
 111    * @param buffer Buffer to fill with file contents.
 112    * @throws IOException File exception occurred.
 113    */
 114  33109 public static void loadFile(final File file,
 115    final StringBuffer buffer)
 116    throws IOException {
 117   
 118  33109 final int size = (int) file.length();
 119  33109 buffer.setLength(0);
 120  33109 final FileReader in = new FileReader(file);
 121  33109 final char[] data = new char[size];
 122  33109 int charsread = 0;
 123  33109 while (charsread < size) {
 124  33109 charsread += in.read(data, charsread, size - charsread);
 125    }
 126  33109 in.close();
 127  33109 buffer.insert(0, data);
 128    }
 129   
 130    /**
 131    * Reads a file and returns the contents as a <code>String</code>.
 132    *
 133    * @param file File to load from.
 134    * @return Contents of file.
 135    * @throws IOException File exception occurred.
 136    */
 137  0 public static final byte[] loadFileBinary(final File file) throws IOException {
 138  0 final int size = (int) file.length();
 139  0 final FileInputStream in = new FileInputStream(file);
 140  0 try {
 141  0 final byte[] data = new byte[size];
 142  0 int charsread = 0;
 143  0 while (charsread < size) {
 144  0 final int read = in.read(data, charsread, size - charsread);
 145  0 if (read == -1) {
 146  0 final byte[] result = new byte[charsread];
 147  0 System.arraycopy(data, 0, result, 0, charsread);
 148  0 return result;
 149    }
 150  0 charsread += read;
 151    }
 152  0 in.close();
 153  0 return data;
 154    } finally {
 155  0 closeStream(in);
 156    }
 157    }
 158   
 159    /**
 160    * Reads contents of an URL into a string buffer. The filling is character set dependent.
 161    *
 162    * @param url This URL will be loaded.
 163    * @param buffer Buffer to fill with file contents.
 164    * @throws IOException Reading failed.
 165    */
 166  20 public static void loadFile(final URL url, final StringBuffer buffer) throws IOException {
 167  20 InputStream in = null;
 168  20 BufferedReader dis = null;
 169  20 try {
 170  20 in = url.openStream();
 171  20 dis = new BufferedReader(new InputStreamReader(in));
 172  20 int i;
 173  ? while ((i = dis.read()) != -1) {
 174  110372 buffer.append((char) i);
 175    }
 176    } finally {
 177  20 closeStream(in);
 178  20 closeReader(dis);
 179    }
 180    }
 181   
 182    /**
 183    * Save contents of an URL into a file.
 184    *
 185    * @param url This URL will be loaded.
 186    * @param file Write into this file.
 187    * @throws IOException Reading or writing failed.
 188    */
 189  2 public static void saveFile(final URL url, final File file) throws IOException {
 190  2 final InputStream in = url.openStream();
 191  2 final FileOutputStream out = new FileOutputStream(file);
 192   
 193  2 byte[] data = new byte[8 * 1024];
 194  2 int length;
 195   
 196  ? while ((length = in.read(data)) != -1) {
 197  2 out.write(data, 0, length);
 198    }
 199  2 in.close();
 200  2 out.close();
 201    }
 202   
 203    /**
 204    * Convert String into a {@link Reader}.
 205    *
 206    * <a href="http://bugs.sun.com/bugdatabase/view_bug.do;:WuuT?bug_id=4094886">
 207    * Bug ID: 4094886</a>
 208    *
 209    * @param data Convert this.
 210    * @return Resulting reader.
 211    */
 212  0 public static final Reader stringToReader(final String data) {
 213  0 try {
 214  0 return new InputStreamReader(new ByteArrayInputStream(data.getBytes("ISO-8859-1")));
 215    } catch (UnsupportedEncodingException e) {
 216  0 throw new RuntimeException(e);
 217    }
 218    }
 219   
 220    /**
 221    * Saves a <code>String</code> into a file.
 222    *
 223    * @param filename Name of the file (could include path).
 224    * @param text Data to save in the file.
 225    * @throws IOException File exception occurred.
 226    */
 227  0 public static void saveFile(final String filename, final String text)
 228    throws IOException {
 229  0 saveFile(new File(filename), text);
 230    }
 231   
 232    /**
 233    * Saves a <code>StringBuffer</code> in a file.
 234    *
 235    * @param filename Name of the file (could include path).
 236    * @param text Data to save in the file.
 237    * @throws IOException File exception occurred.
 238    */
 239  0 public static void saveFile(final String filename, final StringBuffer text)
 240    throws IOException {
 241  0 saveFile(new File(filename), text.toString());
 242    }
 243   
 244   
 245    /**
 246    * Saves a <code>StringBuffer</code> in a file.
 247    *
 248    * @param file File to save into.
 249    * @param text Data to save in the file.
 250    * @throws IOException File exception occurred.
 251    */
 252  1 public static void saveFile(final File file, final StringBuffer text)
 253    throws IOException {
 254  1 saveFile(file, text.toString());
 255    }
 256   
 257   
 258    /**
 259    * Saves a <code>String</code> in a file.
 260    *
 261    * @param file File to save the data in.
 262    * @param text Data to save in the file.
 263    * @throws IOException File exception occurred.
 264    */
 265  2 public static void saveFile(final File file, final String text)
 266    throws IOException {
 267  2 BufferedWriter out = new BufferedWriter(
 268    new FileWriter(file));
 269  2 out.write(text);
 270  2 out.close();
 271    }
 272   
 273    /**
 274    * Saves a <code>String</code> in a file.
 275    *
 276    * @param file File to save the data in.
 277    * @param data Data to save in the file.
 278    * @throws IOException File exception occurred.
 279    */
 280  0 public static void saveFileBinary(final File file, final byte[] data)
 281    throws IOException {
 282  0 BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
 283  0 out.write(data);
 284  0 out.close();
 285    }
 286   
 287    /**
 288    * Copies a file to a different location.
 289    *
 290    * @param from Copy source.
 291    * @param to Copy destination.
 292    * @throws IOException File exception occurred.
 293    */
 294  24 public static void copyFile(final File from, final File to)
 295    throws IOException {
 296   
 297  24 if (from.getCanonicalFile().equals(to.getCanonicalFile())) {
 298  6 return;
 299    }
 300  18 FileInputStream in = new FileInputStream(from);
 301  18 FileOutputStream out = new FileOutputStream(to);
 302   
 303  18 byte[] data = new byte[8 * 1024];
 304  18 int length;
 305   
 306  ? while ((length = in.read(data)) != -1) {
 307  145 out.write(data, 0, length);
 308    }
 309  18 in.close();
 310  18 out.close();
 311    }
 312   
 313    /**
 314    * Compare two files.
 315    *
 316    * @param from Compare source.
 317    * @param with Compare with this file.
 318    * @return Is the contents of the two files binary equal?
 319    * @throws IOException File exception occurred.
 320    */
 321  3 public static boolean compareFilesBinary(final File from, final File with)
 322    throws IOException {
 323  3 if (from == null && with == null) {
 324  0 return true;
 325    }
 326  3 if (from == null || with == null) {
 327  0 return false;
 328    }
 329  3 if (from.getAbsoluteFile().equals(with.getAbsoluteFile())) {
 330  0 return true;
 331    }
 332  3 if (from.length() != with.length()) {
 333  0 return false;
 334    }
 335  3 byte[] dataOne = new byte[8 * 1024];
 336  3 byte[] dataTwo = new byte[8 * 1024];
 337  3 int length;
 338   
 339  3 FileInputStream one = null;
 340  3 FileInputStream two = null;
 341  3 try {
 342  3 one = new FileInputStream(from);
 343  3 two = new FileInputStream(with);
 344   
 345  ? while ((length = one.read(dataOne)) != -1) {
 346  36 if (length != two.read(dataTwo)) {
 347  0 return false;
 348    }
 349  36 if (!Arrays.equals(dataOne, dataTwo)) {
 350  0 return false;
 351    }
 352    }
 353  3 return true;
 354    } finally {
 355  3 closeStream(one);
 356  3 closeStream(two);
 357    }
 358    }
 359   
 360    /**
 361    * Quotes a <code>String</code>. If no quotes exist in the
 362    * <code>String</code>, a quote character is appended at the
 363    * beginning and the end of the <code>String</code>.
 364    *
 365    * @param unquoted the unquoted <code>String</code>
 366    * @return quoted <code>String</code>
 367    * @throws NullPointerException if <code>unquoted == null</code>
 368    */
 369  448 public static String quote(final String unquoted) {
 370   
 371  448 String result = "\"";
 372   
 373  448 for (int i = 0; i < unquoted.length(); i++) {
 374  616 if (unquoted.charAt(i) == '\"') {
 375  0 result += "\"\"";
 376    } else {
 377  616 result += unquoted.charAt(i);
 378    }
 379    }
 380  448 result += '\"';
 381  448 return result;
 382    }
 383   
 384    /**
 385    * Tests if given <code>String</code> begins with a letter and contains
 386    * only letters and digits.
 387    *
 388    * @param text test this
 389    * @return is <code>text</code> only made of letters and digits and has
 390    * a leading letter?
 391    * @throws NullPointerException if <code>text == null</code>
 392    */
 393  0 public static boolean isLetterDigitString(final String text) {
 394  0 if (text.length() <= 0) {
 395  0 return false;
 396    }
 397  0 if (!Character.isLetter(text.charAt(0))) {
 398  0 return false;
 399    }
 400  0 for (int i = 1; i < text.length(); i++) {
 401  0 if (!Character.isLetterOrDigit(text.charAt(i))) {
 402  0 return false;
 403    }
 404    }
 405  0 return true;
 406    }
 407   
 408    /**
 409    * Delete file directory recursive.
 410    *
 411    * @param directory Directory to delete.
 412    * @param deleteDir Delete directory itself too?
 413    * @return Was deletion successful?
 414    */
 415  4 public static boolean deleteDir(final File directory, final boolean deleteDir) {
 416    // to see if this directory is actually a symbolic link to a directory,
 417    // we want to get its canonical path - that is, we follow the link to
 418    // the file it's actually linked to
 419  4 File candir;
 420  4 try {
 421  4 candir = directory.getCanonicalFile();
 422    } catch (IOException e) {
 423  0 return false;
 424    }
 425   
 426    // a symbolic link has a different canonical path than its actual path,
 427    // unless it's a link to itself
 428  4 if (!candir.equals(directory.getAbsoluteFile())) {
 429    // this file is a symbolic link, and there's no reason for us to
 430    // follow it, because then we might be deleting something outside of
 431    // the directory we were told to delete
 432  0 return false;
 433    }
 434   
 435    // now we go through all of the files and subdirectories in the
 436    // directory and delete them one by one
 437  4 boolean success = true;
 438  4 File[] files = candir.listFiles();
 439  4 if (files != null) {
 440  4 for (int i = 0; i < files.length; i++) {
 441  36 File file = files[i];
 442   
 443    // in case this directory is actually a symbolic link, or it's
 444    // empty, we want to try to delete the link before we try
 445    // anything
 446  36 boolean deleted = file.delete();
 447  36 if (!deleted) {
 448    // deleting the file failed, so maybe it's a non-empty
 449    // directory
 450  0 if (file.isDirectory()) {
 451  0 deleted = deleteDir(file, true);
 452    }
 453   
 454    // otherwise, there's nothing else we can do
 455    }
 456  36 success = success && deleted;
 457    }
 458    }
 459   
 460    // now that we tried to clear the directory out, we can try to delete it
 461    // again
 462  4 if (deleteDir) {
 463  0 return directory.delete();
 464    }
 465  4 return success;
 466    }
 467   
 468    /**
 469    * Get amount of spaces.
 470    *
 471    * @param length number of spaces
 472    * @return String contains exactly <code>number</code> spaces
 473    */
 474  1056 public static StringBuffer getSpaces(final int length) {
 475  1056 final StringBuffer buffer = new StringBuffer(length >= 0 ? length : 0);
 476  1056 for (int i = 0; i < length; i++) {
 477  3754 buffer.append(' ');
 478    }
 479  1056 return buffer;
 480    }
 481   
 482    /**
 483    * Get non qualified class name.
 484    *
 485    * @param clazz Class.
 486    * @return Non qualified class name.
 487    */
 488  19646 public static String getClassName(final Class clazz) {
 489  19646 return clazz.getName().substring(clazz.getName().lastIndexOf('.') + 1);
 490    }
 491   
 492    /**
 493    * Print current system properties to System.out.
 494    */
 495  0 public static void printAllSystemProperties() {
 496  0 Properties sysprops = System.getProperties();
 497  0 for (Enumeration e = sysprops.propertyNames(); e.hasMoreElements(); ) {
 498  0 String key = (String) e.nextElement();
 499  0 String value = sysprops.getProperty(key);
 500  0 System.out.println(key + "=" + value);
 501    }
 502    }
 503   
 504    /**
 505    * Get home directory of user.
 506    *
 507    * @return Home directory of user.
 508    */
 509  0 public static File getUserHomeDirectory() {
 510  0 return new File((String) System.getProperties().get("user.home"));
 511    }
 512   
 513    /**
 514    * Convert file in URL.
 515    *
 516    * @param file File.
 517    * @return URL.
 518    */
 519  8137 public static URL toUrl(final File file) {
 520  8137 try {
 521  8137 return file.toURI().toURL();
 522    } catch (MalformedURLException e) { // should only happen if there is a bug in the JDK
 523  0 throw new RuntimeException(e);
 524    }
 525    }
 526   
 527    /**
 528    * Creates necessary parent directories for a file.
 529    *
 530    * @param file File.
 531    */
 532  24 public static void createNecessaryDirectories(final File file) {
 533  24 if (file.getParentFile() != null) {
 534  24 file.getParentFile().mkdirs();
 535    }
 536    }
 537   
 538    /**
 539    * Create relative address from <code>orgin</code> to <code>next</code>.
 540    *
 541    * @param orgin this is the original location
 542    * @param next this should be the next location
 543    * @return relative (or if necessary absolute) file path
 544    */
 545  0 public static final String createRelativePath(final File orgin, final File next) {
 546  0 try {
 547  0 if (orgin.equals(next)) {
 548  0 return "";
 549    }
 550  0 try {
 551  0 String org = orgin.getCanonicalPath().replace('\\', '/');
 552  0 if (orgin.isDirectory() && !org.endsWith("/")) {
 553  0 org += "/";
 554    }
 555  0 String nex = next.getCanonicalPath().replace('\\', '/');
 556  0 if (next.isDirectory() && !nex.endsWith("/")) {
 557  0 nex += "/";
 558    }
 559  0 int i = -1; // position of next '/'
 560  0 int j = 0; // position of last '/'
 561  0 while (0 <= (i = org.indexOf("/", j))) {
 562  0 if (i >= 0 && nex.length() > i
 563    && org.substring(j, i).equals(
 564    nex.substring(j, i))) {
 565  0 j = i + 1;
 566    } else {
 567  0 break;
 568    }
 569    }
 570  0 if (j > 0) {
 571  0 i = j;
 572  0 StringBuffer result = new StringBuffer(nex.length());
 573  0 while (0 <= (i = org.indexOf("/", i))) {
 574  0 i++;
 575  0 result.append("../");
 576    }
 577  0 result.append(nex.substring(j));
 578  0 return result.toString();
 579    }
 580  0 return "/" + nex;
 581    } catch (RuntimeException e) {
 582  0 return next.toString();
 583    }
 584    } catch (IOException e) {
 585  0 return next.toString();
 586    }
 587    }
 588   
 589    /**
 590    * Waits until a '\n' was read from System.in.
 591    */
 592  0 public static void waitln() {
 593  0 System.out.println("\n..press <return> to continue");
 594  0 try {
 595  0 (new java.io.BufferedReader(new java.io.InputStreamReader(
 596    System.in))).readLine();
 597    } catch (IOException e) {
 598    // ignore
 599    }
 600    }
 601   
 602    /**
 603    * Closes input stream without exception.
 604    *
 605    * @param in Input stream, maybe <code>null</code>.
 606    */
 607  26 public static void closeStream(final InputStream in) {
 608  26 if (in != null) {
 609  26 try {
 610  26 in.close();
 611    } catch (Exception e) {
 612    // ignore
 613    }
 614    }
 615    }
 616   
 617    /**
 618    * Closes input reader without exception.
 619    *
 620    * @param reader Reader, maybe <code>null</code>.
 621    */
 622  20 public static void closeReader(final Reader reader) {
 623  20 if (reader != null) {
 624  20 try {
 625  20 reader.close();
 626    } catch (Exception e) {
 627    // ignore
 628    }
 629    }
 630    }
 631   
 632    /**
 633    * Search for first line followed by whitespace and delete this string within the whole
 634    * text.
 635    * <p>
 636    * For example the following text
 637    *<pre>
 638    * Do you know the muffin man,
 639    * The muffin man, the muffin man,
 640    * Do you know the muffin man,
 641    * Who lives on Drury Lane?
 642    *</pre>
 643    * will be converted into:
 644    *<pre>
 645    *Do you know the muffin man,
 646    *The muffin man, the muffin man,
 647    *Do you know the muffin man,
 648    *Who lives on Drury Lane?
 649    *</pre>
 650    *
 651    * @param buffer Work on this text.
 652    */
 653  1218 public static void deleteLineLeadingWhitespace(final StringBuffer buffer) {
 654  1218 int start = -1;
 655  ? while (0 <= (start = buffer.indexOf("\n", start + 1))) {
 656  300 if (start + 1 < buffer.length() && '\n' != buffer.charAt(start + 1)) {
 657  266 break;
 658    }
 659    }
 660  1218 if (start >= 0) {
 661  266 int next = start + 1;
 662  266 while (next < buffer.length() && Character.isWhitespace(buffer.charAt(next))
 663    && '\n' != buffer.charAt(next)) {
 664  3502 next++;
 665    }
 666  266 final String empty = buffer.substring(start, next);
 667  266 if (empty.length() > 0) {
 668  266 ReplaceUtility.replace(buffer, empty, "\n");
 669    }
 670    }
 671    }
 672   
 673    /**
 674    * Get start directory for application. If this is no Java Webstart version
 675    * the result is <code>new File(".")</code>.
 676    *
 677    * @param application Application name, used for Java Webstart version. Should
 678    * be written in lowercase letters. A "." is automatically appended at
 679    * the beginning.
 680    * @return Start directory for application.
 681    */
 682  8 public static final File getStartDirectory(final String application) {
 683  8 final File startDirectory;
 684  8 if (isWebStarted()) {
 685  0 final String userHomeWS = System.getProperties().get("jnlpx.deployment.user.home")
 686    != null ? (String) System.getProperties().get("jnlpx.deployment.user.home")
 687    : "";
 688  0 final String userHome = System.getProperties().get("user.home") != null
 689    ? (String) System.getProperties().get("user.home") : "";
 690  0 startDirectory = new File(
 691  0 new File((userHomeWS.length() != 0 ? userHomeWS : userHome)), "." + application);
 692    } else {
 693  8 startDirectory = new File(".");
 694    }
 695  8 return startDirectory;
 696    }
 697   
 698    /**
 699    * Was the application started by Java Webstart?
 700    *
 701    * @return Was the application started by Java Webstart.
 702    */
 703  12 public static final boolean isWebStarted() {
 704  12 final String webStart = (String) System.getProperties().get("javawebstart.version");
 705  12 return webStart != null;
 706    }
 707   
 708    /**
 709    * Loads a property file from given URL.
 710    *
 711    * @param url URL to load properties from.
 712    * @return Loaded properties.
 713    * @throws MalformedURLException Invalid URL.
 714    * @throws IOException Reading error.
 715    */
 716  0 public static Properties loadProperties(final URL url)
 717    throws IOException {
 718  0 Properties newprops = new Properties();
 719  0 InputStream in = url.openStream();
 720  0 newprops.load(in);
 721  0 in.close();
 722  0 return newprops;
 723    }
 724   
 725    /**
 726    * Return a String like it appears in an property file. Thus certain characters are escaped.
 727    *
 728    * @param value Escape this value.
 729    * @return Escaped form.
 730    */
 731  1 public static String escapeProperty(final String value) {
 732  1 Properties newprops = new Properties();
 733  1 newprops.put("key", value);
 734  1 ByteArrayOutputStream out = new ByteArrayOutputStream();
 735  1 try {
 736  1 newprops.store(out, null);
 737    } catch (IOException e) {
 738  0 throw new RuntimeException(e);
 739    }
 740  1 try {
 741  1 final String file = out.toString("ISO-8859-1");
 742  1 return file.substring(file.indexOf('\n') + 1 + "key=".length());
 743    } catch (UnsupportedEncodingException e) {
 744  0 throw new RuntimeException(e);
 745    }
 746    }
 747   
 748    }