/*
 * $Id: FileUtils.java,v 1.15 2007/11/05 09:19:04 marbobo Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 *
 * $Log: FileUtils.java,v $
 * Revision 1.15  2007/11/05 09:19:04  marbobo
 * + Bugfix (Statt List werden HashSet benutzt)
 *
 * Revision 1.14  2007/11/05 09:17:34  marbobo
 * + Bugfix (Statt List werden HashSet benutzt)
 *
 * Revision 1.13  2007/11/05 08:53:48  marbobo
 * + Bugfix (Statt List werden HashSet benutzt)
 *
 * Revision 1.12  2007/10/30 12:27:07  marbobo
 * + removed unnecessary statements
 *
 * Revision 1.11  2004/11/10 15:02:46  koppy
 * Projektweite Überarbeitung von Error-Logs, Stacktraces,..
 *
 * Revision 1.10  2004/06/24 23:33:33  marbobo
 * Quellcode maintenance
 *
 * Revision 1.9  2004/02/24 12:41:02  koppy
 * saveInputStream(..)
 *
 * Revision 1.8  2004/01/27 10:44:07  bigmac
 * + toStringBuffer(InputStream)
 *
 * Revision 1.7  2004/01/16 14:28:28  koppy
 * Kleine Erweiterung in write( InputStream, OutputStream )
 *
 * Revision 1.6  2003/12/24 10:11:58  bigmac
 * Projektweite Import-Optimierung
 *
 * Revision 1.5  2003/12/02 23:55:43  koppy
 * An Änderungen von VKCInputStream angepasst
 *
 * Revision 1.4  2003/11/29 22:23:28  koppy
 * Debug-Ausgabe rausgenommen
 *
 * Revision 1.3  2003/11/28 17:17:13  koppy
 * + write( in, out )
 *
 * Revision 1.2  2003/03/20 09:19:20  lawern
 * Methode saveInputStream ergänzt
 *
 * Revision 1.1  2002/10/21 14:36:26  bigmac
 * *** empty log message ***
 *
 * Revision 1.1.1.3  2002/09/17 08:18:23  jonyp
 * no message
 *
 * Revision 1.1.1.2  2002/09/11 13:20:22  jonyp
 * no message
 *
 * Revision 1.1.1.1  2002/04/02 10:55:46  lawern
 * initiale Version
 *
 * Revision 1.3  2002/02/26 09:47:13  bigmac
 * + getFileAsStringBuffer()
 *
 * Revision 1.2  2002/02/01 15:18:54  bigmac
 * + copyFile()
 *
 */
package vkc.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;

import vkc.misc.VKCLogManager;


/**
 * Sammelklasse für Dateizugriffsfunktionen
 * 
 * <p></p>
 *
 * @author bigmac
 */
final public class FileUtils {
    /**
     * Keine Instanzen erlauben ...
     */
    private FileUtils() {
    }

    /**
     * kopiert Dateien rekursiv
     * 
     * <p>
     * Besonderheit unter Windows: falls "source" oder "destination"  auf ein
     * Filesystem-Wurzelverzeichnis zeigen , sollte der Pfadname mit  einem
     * "\" enden !!!!!!!! Java macht sonst beispielsweise aus
     * "c:".getAbsoluteFile() oder "c:".getCanonicalFile() ein "c:\(hier wird
     * die VM ausgefürht)"-Fileobjekt. "c:\".getAbsoluteFile() funktionert
     * dagegen einwandfrei. d.h. es werden letzten Endes die falschen
     * Verzeichnisse kopiert
     * </p>
     * 
     * <p></p>
     */
    public final static void copyFile(File source, File destination)
        throws IOException, IllegalArgumentException {
        source = source.getCanonicalFile();
        destination = destination.getCanonicalFile();

        if (!source.exists()) {
            throw new IOException("source file does not exists: " + source);
        }

        if (!source.canRead()) {
            throw new IOException("source file is not readable: " + source);
        }

        if (destination.exists()) {
            if (!destination.canWrite()) {
                throw new IOException(
                    "can write to existing destination file: " + destination);
            }
        }

        if (source.isDirectory() && destination.isFile()) {
            throw new IllegalArgumentException("cannot copy source directory '" +
                source + "'into existing file '" + destination + "'");
        }

        if (source.isFile() && destination.isFile()) {
            copyFileToFile(source, destination);

            return;
        }

        if (source.isFile() && destination.isDirectory()) {
            copyFileToFile(source, new File(destination, source.getName()));

            return;
        }

        // Quelle ist Verzeichnis und Ziel ist Verzeichnis
        java.util.Vector v = new java.util.Vector();

        File[] files = source.listFiles();
        v.addElement(files);

        String basePath = source.getCanonicalPath();
        int basePathLength = basePath.length();
        String str = null;
        File d = null;

        while (v.size() > 0) {
            files = (File[]) v.remove(0);

            for (int i = 0; i < files.length; i++) {
                str = files[i].getCanonicalPath();
                str = str.substring(basePathLength);

                if (files[i].isDirectory()) {
                    v.addElement(files[i].listFiles());
                    d = new File(destination, str);
                    d.mkdirs();
                } else {
                    d = new File(destination, str);
                    copyFileToFile(files[i], d);
                }
            }
        }
    }

    /**
     * Hilfsmethode für copyFile
     * 
     * <p></p>
     */
    private final static void copyFileToFile(File source, File destination)
        throws IOException {
        BufferedInputStream in = null;
        BufferedOutputStream out = null;

        try {
            in = new BufferedInputStream(new FileInputStream(source));

            if (!destination.exists()) {
                destination.createNewFile();
            }

            out = new BufferedOutputStream(new FileOutputStream(destination));

            int chunkSize = 8192;
            byte[] chunk = new byte[chunkSize];
            int readBytes = 0;

            while (in.available() > 0) {
                readBytes = in.read(chunk, 0, chunkSize);
                out.write(chunk, 0, readBytes);
            }
        } finally {
            if (in != null) {
                closeInputStream(in);
            }

            if (out != null) {
                closeOutputStream(out);
            }
        }
    }

    /**
     * Hilfsmethode die ein Bytearray in eine Datei speichert.
     * @param file Zieldatei
     * @param data das zu speichernde Byte-Array
     * @param encoding Kodierung der Datei
     * @param overwrite falls true, werden existierende Dateien überschrieben
     */
    public final static void saveByteArray(File file, byte[] data,
        String encoding, boolean overwrite) throws IOException, IllegalArgumentException {
        if (file == null) {
            throw new IllegalArgumentException("file must not be null");
        }

        if ((data == null) || (data.length == 0)) {
            throw new IllegalArgumentException("no data specified for file: " +
                file);
        }

        if (file.exists()) {
            if (file.isDirectory()) {
                throw new IOException(
                    "can't write data to existing directory: " + file);
            }

            if (!overwrite) {
                throw new IOException("can't overwrite existing file: " + file);
            }

            if (!file.delete()) {
                throw new IOException("could not delete existing file: " +
                    file);
            }
        }

        BufferedOutputStream bw = null;
        Writer out = null;

        try {
            if (StringUtils.isEmpty(encoding)) {
                bw = new BufferedOutputStream(new FileOutputStream(file));
                bw.write(data, 0, data.length);
                bw.flush();
            } else {
                out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), encoding));
                String s = new String(data, encoding); 
                out.write(s);
                out.flush();
            }
            
        } finally {
            closeOutputStream(bw);
            closeWriter(out);
        }
    }

    /**
     * @see #saveByteArray( File file, byte[] data, String encoding, boolean overwrite ) <p>
     */
    public static void saveByteArray(String file, byte[] data, boolean overwrite)
        throws IOException, IllegalArgumentException {
        saveByteArray(new File(file), data, null, overwrite);
    }

    /**
     * Hilfsmethode die einen Inputstream in eine Datei speichert.
     *
     * @param data das zu speichernde Byte-Array
     * @param file Zieldatei
     * @param overwrite falls true, wird die existierende Datei überschrieben
     */
    public final static void saveInputStream(File file, InputStream data,
        boolean overwrite) throws IOException, IllegalArgumentException {
        if (file == null) {
            throw new IllegalArgumentException("file must not be null");
        }

        if ((data == null) || (data.available() == 0)) {
            throw new IllegalArgumentException("no data specified for file: " +
                file);
        }

        if (file.exists()) {
            if (file.isDirectory()) {
                throw new IOException(
                    "can't write data to existing directory: " + file);
            }

            if (!overwrite) {
                throw new IOException("can't overwrite existing file: " + file);
            }

            if (!file.delete()) {
                throw new IOException("could not delete existing file: " +
                    file);
            }
        }

        OutputStream fos = new BufferedOutputStream(new FileOutputStream(file));
        FileUtils.write(data,fos);
		fos.close();
        
    }

    /**
     * Hilfsmethode um einen String in eine Datei zu speichern. Falls die
     * Zeildatei bereits existiert, wird sie überschrieben
     * 
     * <p></p>
     * @param data abzuspeichernder String
     * @param encoding Kodierung der Datei
     * @param overwrite zeigt an, ob eine existierende Datei  überschrieben
     *        werden soll
     * @param fname Name der Zieldatei
     */
    public final static void saveString(File file, String data,
        String encoding, boolean overwrite) throws IllegalArgumentException, IOException {
        if ((data == null) || (data.length() == 0)) {
            throw new IllegalArgumentException(
                "string to save must not be null");
        }

        saveByteArray(file, StringUtils.isEmpty(encoding) ? data.getBytes() : data.getBytes(encoding), encoding, overwrite);
    }

    public final static void saveString(String file, String data,
        String encoding, boolean overwrite) throws IllegalArgumentException, IOException {
        if ((data == null) || (data.length() == 0)) {
            throw new IllegalArgumentException(
                "string to save must not be null or empty");
        }

        if ((file == null) || (file.length() == 0)) {
            throw new IllegalArgumentException(
                "file name must not be null or empty");
        }

        saveByteArray(new File(file), StringUtils.isEmpty(encoding) ? data.getBytes() : data.getBytes(encoding), encoding, overwrite);
    }

    public static void saveStringBuffer(File file, StringBuffer data,
        String encoding, boolean overwrite) throws IllegalArgumentException, IOException {
        if ((data == null) || (data.length() == 0)) {
            throw new IllegalArgumentException(
                "stringbuffer to save must not be null or empty");
        }

        saveByteArray(file, StringUtils.isEmpty(encoding) ? data.toString().getBytes() : data.toString().getBytes(encoding), encoding, overwrite);
    }

    /**
     * Hilfsmethode die den Inhalt einer Datei als Bytearray zurueckliefert
     * 
     * <p></p>
     *
     * @param fname Name der auszulesenden Datei
     *
     * @return byte-Array, falls die Datei gelesen werden konnte.
     */
    public static byte[] getFileAsByteArray(File file)
        throws IOException, IllegalArgumentException {
        if (file == null) {
            throw new IllegalArgumentException("file must not be null");
        }

        if (!file.exists()) {
            throw new IOException("file does not exists: " + file);
        }

        if (file.isDirectory()) {
            throw new IllegalArgumentException("file point to a directory: " +
                file);
        }

        long length = file.length();

        if (length <= 0) {
            throw new IOException("file exists but has no content: " + file);
        }

        if (length > Integer.MAX_VALUE) {
            throw new IOException(
                "file size exceeds internal arraysize limit: " + file + " > " +
                Integer.MAX_VALUE);
        }

        BufferedInputStream bis = null;

        try {
            int fLength = (int) length;
            bis = new BufferedInputStream(new FileInputStream(file));

            byte[] data = new byte[fLength];

            int read = bis.read(data, 0, fLength);
            bis.close();
            bis = null;

            if (read != fLength) {
                throw new IOException("error reading file '" + file + "', " +
                    read + " != " + fLength);
            }

            return data;
        } finally {
            if (bis != null) {
                closeInputStream(bis);
            }
        }
    }

    /**
     * Hilfsmethode die den Inhalt einer Datei als StringBuffer zurueckliefert
     * 
     * <p></p>
     *
     * @param file die einzulesende Datei
     *
     * @return StringBuffer byte-Array, falls die Datei gelesen werden konnte.
     *         null, bei Fehlern.
     */
    final public static StringBuffer getFileAsStringBuffer(File file)
        throws IOException, IllegalArgumentException {
        if (file == null) {
            throw new IllegalArgumentException("file must not be null");
        }

        if (!file.exists()) {
            throw new IOException("file does not exists: " + file);
        }

        if (file.isDirectory()) {
            throw new IllegalArgumentException("file points to a directory: " +
                file);
        }

        int length = (int) file.length();

        if (length <= 0) {
            throw new IOException("file exists but has no content: " + file);
        }

        BufferedReader reader = null;

        try {
            
            char[] c = new char[length];
            reader = new BufferedReader(new FileReader(file));

            int read = reader.read(c, 0, length);

            if (read != length) {
                throw new IOException("error reading file '" + file + "', " +
                    read + " != " + length);
            }

            return new StringBuffer().append(c);
        } finally {
            if (reader != null) {
                closeReader(reader);
            }
        }
    }

    /**
     * Lädt eine Datei und gibt den Inhalt als String zurück.
     * 
     * <p></p>
     *
     * @param file File-Objekt der zu lesenden Datei
     */
    public static String getFileAsString(File file)
        throws IOException, IllegalArgumentException {
        return new String(getFileAsByteArray(file));
    }

    /**
     * Verschiebt Datei 'sourceName' nach 'targetName'. Falls die Datei
     * 'targetName' bereits existiert, wird sie überschrieben! Für
     * 'targetName' werden alle notwendigen Ordner angelegt, falls sie noch
     * nicht existieren sollten. Falls das Umbenennen nicht funktioniert hat,
     * wird es insgesamt 50x mit Pausen dazwischen wiederholt ( Windows sucks
     * ... )
     * 
     * <p></p>
     *
     * @param source Quelldatei
     * @param target Zieldatei
     */
    public static void moveFile(File source, File target, boolean overwrite)
        throws IllegalArgumentException, IOException {
        if (source == null) {
            throw new IllegalArgumentException("source file must not be null");
        }

        if (!source.exists()) {
            throw new IOException("source file not found: " + source);
        }

        if (source.isDirectory()) {
            throw new IllegalArgumentException(
                "source points to directory. can only move files");
        }

        if (target == null) {
            throw new IllegalArgumentException("target file must not be null");
        }

        if (target.exists()) {
            if (target.isDirectory()) {
                throw new IllegalArgumentException(
                    "target point to a existing directory: " + target);
            }

            if (!overwrite) {
                throw new IOException(
                    "can't overwrite existing destination file: " + target);
            }

            target.delete();

            int count = 0;

            while (count < 50) {
                if (count == 50) {
                    throw new IOException(
                        "target file exists but could not be deleted after 50 retries: " +
                        target);
                }

                if ((target.exists() == false) || target.delete()) {
                    break;
                }

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException iex) {
                    throw new IOException(
                        "target could not be removed due to interruption");
                }

                count++;
            }
        }

        File parent = target.getParentFile();

        if ((parent != null) && !parent.exists()) {
            if (!parent.mkdirs()) {
                throw new IOException(
                    "directory for target file could not be created: " +
                    parent);
            }
        }

        int count = 0;

        while (true) {
            if (count == 50) {
                throw new IOException("source file '" + source +
                    "' could not be moved to '" + target +
                    "' after 50 retries ... aborting");
            }

            if (source.renameTo(target)) {
                break;
            }

            try {
                Thread.sleep(1000);
            } catch (InterruptedException iex) {
                throw new IOException(
                    "source file could not be moved due to interruption");
            }

            count++;

            continue;
        }
    }

    /**
     * Wrapper-Methode um einen InputStream zu schliessen
     *
     * @param is der zu schliessende InputStream
     */
    public static void closeInputStream(InputStream is) {
        try {
            if (is != null) {
                is.close();
            }
        } catch (Exception ex) {
            VKCLogManager.errorLog(FileUtils.class, "", ex.getMessage(),ex);
        }
    }

    /**
     * Wrapper-Methode um einen OutputStream zu schliessen
     * 
     * <p></p>
     *
     * @param is der zu schliessende OutputStream
     */
    final public static void closeOutputStream(OutputStream os) {
        try {
            if (os != null) {
                os.flush();
                os.close();
            }
        } catch (Exception ex) {
            VKCLogManager.errorLog(FileUtils.class, "", ex.getMessage(),ex);
        }
    }

    /**
     * Wrapper-Methode um einen Reader zu schliessen
     * 
     * <p></p>
     *
     * @param r der zu schliessende Reader
     */
    final public static void closeReader(Reader r) {
        try {
            if (r != null) {
                r.close();
            }
        } catch (Exception ex) {
            VKCLogManager.errorLog(FileUtils.class, "", ex.getMessage(),ex);
        }
    }

    /**
     * Wrapper-Methode um einen Writer zu schliessen
     * 
     * <p></p>
     *
     * @param w der zu schliessende Writer
     */
    final public static void closeWriter(Writer w) {
        try {
            if (w != null) {
                w.close();
            }
        } catch (Exception ex) {
            VKCLogManager.errorLog(FileUtils.class, "", ex.getMessage(),ex);
        }
    }

    /**
     * Wrappermethode zum Löschen von 0-Byte Dateien
     * 
     * <p></p>
     *
     * @param fileName Name der zu testenden Datei
     */
    public static void deleteZeroByteFile(File file) {
        try {
            if (file == null) {
                return;
            }

            if (!file.exists()) {
                return;
            }

            if (file.isDirectory()) {
                return;
            }

            if (file.length() == 0) {
                file.delete();
            }
        } catch (Exception ex) {
            VKCLogManager.errorLog(FileUtils.class, "", ex.getMessage(),ex);
        }
    }

    /**
     * Wrapper-Methode um eine Datei zu löschen, ohne das Exceptions
     * weitergereicht werden ( sollte nur an 'sinnvollen' Stellen genutzt
     * werden )
     * 
     * <p></p>
     *
     * @param file die zu löschende Datei
     *
     * @return true, falls das Löschen geklappt hat. false, sonst.
     */
    final public static boolean deleteFile(File file) {
        try {
            if (file.isDirectory() || !file.exists()) {
                return false;
            }

            return file.delete();
        } catch (Exception ex) {
            VKCLogManager.errorLog(FileUtils.class, "", ex.getMessage(),ex);

            return false;
        }
    }

    /**
     * Hilfmethode die ein Verzeichnis incl. aller Dateien und
     * Unterverzeichnisse löscht.
     * 
     * <p></p>
     *
     * @return true, falls alles gelöscht werden konnte. false, sonst.
     */
    final public static boolean deleteDirectory(File dir) {
        if (dir == null) {
            return true;
        }

        boolean deleted = true;

        try {
            File[] file = dir.listFiles();

            if ((file == null) || (file.length == 0)) {
                // Verzeichnis ist leer
                return dir.delete();
            }

            for (int i = file.length - 1; i >= 0; i--) {
                if (file[i].isDirectory()) {
                    deleted = deleted & deleteDirectory(file[i]);
                } else {
                    deleted = deleted & file[i].delete();
                }
            }

            deleted = deleted & dir.delete();

            return deleted;
        } catch (Exception e) {
            VKCLogManager.errorLog(FileUtils.class, "", e.getMessage(),e);

            return false;
        }
    }

    /**
     * Hilfmethode die rekursiv den Inhalt eines Verzeichnisses löscht, ohne
     * das Verzeichnis selbst zu loeschen.
     * 
     * <p></p>
     *
     * @return true, falls alles gelöscht werden konnte. false, sonst.
     */
    final public static boolean deleteDirectoryContent(File dir) {
        if (dir == null) {
            return true;
        }

        boolean deleted = true;

        try {
            File[] file = dir.listFiles();

            for (int i = 0; i < file.length; i++) {
                if (file[i].isDirectory()) {
                    deleted = deleted & deleteDirectory(file[i]);
                } else {
                    deleted = deleted & file[i].delete();
                }
            }

            return deleted;
        } catch (Exception e) {
            VKCLogManager.errorLog(FileUtils.class, "", e.getMessage(),e);

            return false;
        }
    }

    /**
     * Listet alle Dateien in einem Verzeichnis auf, deren Namen mit einem
     * Präfix übereinstimmen.
     * 
     * <p></p>
     *
     * @return Array mit File-Objekten, falls Dateien in 'directory'  mit dem
     *         Präfix 'prefix' gefunden wurden. null, sonst.
     */
    final public static File[] listFilesByPrefix(File directory, String prefix) {
        try {
            if (directory == null) {
                return null;
            }

            if (prefix == null) {
                return null;
            }

            if (!directory.exists()) {
                return null;
            }

            if (!directory.isDirectory()) {
                return null;
            }

            PrefixFilenameFilter fileFilter = new PrefixFilenameFilter(prefix);

            return directory.listFiles(fileFilter);
        } catch (Exception ex) {
            VKCLogManager.errorLog(FileUtils.class, "", ex.getMessage(),ex);

            return null;
        }
    }

    /**
     * Listet alle Dateien in einem Verzeichnis auf, deren Namen mit einem
     * Suffix übereinstimmen.
     * 
     * <p></p>
     *
     * @return Array mit File-Objekten, falls Dateien in 'directory'  mit dem
     *         Suffix 'suffix' gefunden wurden. null, sonst.
     */
    final public static File[] listFilesBySuffix(File directory, String suffix) {
        try {
            if (directory == null) {
                return null;
            }

            if (suffix == null) {
                return null;
            }

            if (!directory.exists()) {
                return null;
            }

            if (!directory.isDirectory()) {
                return null;
            }

            SuffixFilenameFilter fileFilter = new SuffixFilenameFilter(suffix);

            return directory.listFiles(fileFilter);
        } catch (Exception ex) {
            VKCLogManager.errorLog(FileUtils.class, "", ex.getMessage(),ex);

            return null;
        }
    }

    /**
     * Verschiebt alle Dateien in einem Quell-Verzeichnis die mit einem
     * gegebenen Präfix beginnen in ein Zielverzeichnis.
     * 
     * <p></p>
     */
    final public static boolean moveFilesByPrefix(File source, File dest,
        String prefix) throws IllegalArgumentException, IOException {
        if ((prefix == null) || (prefix.length() == 0)) {
            throw new IllegalArgumentException(
                "prefix must not be null or empty");
        }

        if (source == null) {
            throw new IllegalArgumentException("source dir must not be null");
        }

        if (dest == null) {
            throw new IllegalArgumentException(
                "destination dir must not be null");
        }

        if (!source.exists()) {
            throw new IOException("source dir does not exists");
        }

        if (!dest.exists()) {
            throw new IOException("destination dir does not exists");
        }

        if (!source.isDirectory()) {
            throw new IllegalArgumentException("source dir points to a file");
        }

        if (!dest.isDirectory()) {
            throw new IllegalArgumentException(
                "destination dir points to a file");
        }

        boolean movedAll = true;
        File[] file = source.listFiles();

        for (int i = 0; i < file.length; i++) {
            if (!file[i].getName().startsWith(prefix)) {
                continue;
            }

            File targetFile = new File(dest, file[i].getName());
            movedAll = movedAll & file[i].renameTo(targetFile);
        }

        return movedAll;
    }

    /**
     * Löscht alle in einem Verzeichnis alle Dateien, deren Namen mit einem
     * bestimmten Präfix beginnen
     * 
     * <p></p>
     */
    final public static boolean deleteFilesByPrefix(File dir, String prefix)
        throws IllegalArgumentException, IOException {
        if ((prefix == null) || (prefix.length() == 0)) {
            throw new IllegalArgumentException(
                "prefix must not be null or empty");
        }

        if (dir == null) {
            throw new IllegalArgumentException("source dir must not be null");
        }

        if (!dir.exists()) {
            throw new IOException("directory does not exist: " + dir);
        }

        if (!dir.isDirectory()) {
            throw new IllegalArgumentException("filename points to a file: " +
                dir);
        }

        boolean allDeleted = true;

        File[] file = dir.listFiles();

        for (int i = 0; i < file.length; i++) {
            if (file[i].getName().startsWith(prefix)) {
                if (file[i].isDirectory()) {
                    allDeleted = allDeleted & deleteDirectory(file[i]);
                } else {
                    allDeleted = allDeleted & file[i].delete();
                }
            }
        }

        return allDeleted;
    }

	/**
	 * Writes the inputstream to the outputstream.
	 * If the outputstream points to null, the inputstream
	 * is just read until the end (-1).
	 * 
	 * @param is reads from this inputstream
	 * @param out writes to this outputstream, can be null
	 */
	public static final void write(InputStream is, OutputStream os) 
		throws IOException {
		
		int bytesRead = 0;		
		byte[] buffer = new byte[8192];
		
		if( os == null ){
			while ((bytesRead = is.read(buffer, 0, 8192)) != -1) {					
			    // --> /dev/null ;-)			
			}
		} else {
			while ((bytesRead = is.read(buffer, 0, 8192)) != -1) {					
				os.write(buffer, 0, bytesRead);			
			}	
		}
					
	}

	/**
	 * Method reads from a InputStream and returns its content as a StringBuffer
	 * <p>
	 */	
	public final static StringBuffer toStringBuffer( InputStream is ) throws IOException {
		
		if ( is==null ) {
			return null;
		}

		int    bufferLength = 1024;
		byte[] data = new byte[ bufferLength ];
		int    read = 0;

		StringBuffer sb = new StringBuffer();
		while ( ( read = is.read(data, 0, bufferLength) ) != -1 ) {
			sb.append( new String( data, 0, read ) );
		}

		return sb;
	}	
}


/**
 * Hilfsklasse für getFilesByPrefix()
 */
final class PrefixFilenameFilter implements FilenameFilter {
    private String prefix = null;

    private PrefixFilenameFilter() {
    }

    public PrefixFilenameFilter(String prefix) {
        this();
        this.prefix = prefix;
    }

    public final boolean accept(File dir, String name) {
        return name.startsWith(prefix);
    }
}


/**
 * Hilfsklasse für getFilesBySuffix()
 */
final class SuffixFilenameFilter implements FilenameFilter {
    private String suffix = null;

    private SuffixFilenameFilter() {
    }

    public SuffixFilenameFilter(String suffix) {
        this();
        this.suffix = suffix;
    }

    public final boolean accept(File dir, String name) {
        return name.endsWith(suffix);
    }
}
