org.colombbus.tangara.FileUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.colombbus.tangara.FileUtils.java

Source

/**
 * Tangara is an educational platform to get started with programming.
 * Copyright (C) 2008 Colombbus (http://www.colombbus.org)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.colombbus.tangara;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;

import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;

/**
 * This class can check if a file can be used by
 * tangara (file. Tgr or. Txt) from the path (in form java.io.File or string).
 * @author gwen
 *
 */
public class FileUtils {

    private static final String TEXT_FILE_EXTENSION = "txt";

    private static String tangaraFileExt = null;

    private static String tangaraObjectExt = null;

    /**  Class logger */
    private static Logger LOG = Logger.getLogger(FileUtils.class);

    private static JarUtils jar = null;

    private static Vector<File> tempDirectories = null;

    static {
        tempDirectories = new Vector<File>();
    }

    private FileUtils() {
        super();
    }

    public static final boolean isExtension(File file, String extension) {
        return file.getName().toLowerCase().endsWith("." + extension.toLowerCase());
    }

    public static final boolean isExtension(String fileName, String extension) {
        return fileName.toLowerCase().endsWith("." + extension.toLowerCase());
    }

    /**
     * Returns if the extension of path is "tgr" or not
     * @param path
     *       java.io.File the path file
     * @return
     *       true if the extension is "tgr"
     */
    public static final boolean isTangaraFile(File path) {
        return isExtension(path, getTangaraFileExt());
    }

    /**
     * Returns if the extension of path is "tgr" or not
     * @param path
     *       java.lang.String the path file
     * @return
     *       true if the extension is "tgr"
     */
    public static final boolean isTangaraFile(String path) {
        return isExtension(path, getTangaraFileExt());
    }

    /**
     * Returns if the extension of path is "tgo" or not
     * @param path
     *       java.io.File the path file
     * @return
     *       true if the extension is "tgo"
     */
    public static final boolean isTangaraObjectFile(File path) {
        return isExtension(path, getTangaraObjectExt());
    }

    /**
     * Returns if the extension of path is "tgr" or not
     * @param path
     *       java.lang.String the path file
     * @return
     *       true if the extension is "tgr"
     */
    public static final boolean isTangaraObjectFile(String path) {
        return isExtension(path, getTangaraObjectExt());
    }

    /**
     * Returns if the extension of path is "txt" or not
     * @param path
     *       java.io.File the path file
     * @return
     *       true if the extension is "txt"
     */
    public static final boolean isTextFile(File path) {
        return isExtension(path, getTextFileExt());
    }

    /**
     * Returns if the extension of path is "txt" or not
     * @param path
     *       java.lang.String the path file
     * @return
     *       true if the extension is "txt"
     */
    public static final boolean isTextFile(String path) {
        return isExtension(path, getTextFileExt());
    }

    /**
     * Returns a string corresponding to the extension of Tangara files "tgr"
     * @return
     *       "tgr"
     */
    public static final String getTangaraFileExt() {
        if (tangaraFileExt == null) {
            // we don't care if the content is overriden
            tangaraFileExt = Configuration.instance().getProperty("tangara.file.extension").toLowerCase();
        }
        return tangaraFileExt;
    }

    /**
     * Returns a string corresponding to the extension of Tangara files "tgo"
     * @return
     *       "tgo"
     */
    public static final String getTangaraObjectExt() {
        if (tangaraObjectExt == null) {
            // we don't care if the content is overriden
            tangaraObjectExt = Configuration.instance().getProperty("tangara.object.extension").toLowerCase();
        }
        return tangaraObjectExt;
    }

    /**
     * Returns a string corresponding to the extension of text files "txt"
     * @return
     *       "txt"
     */
    public static final String getTextFileExt() {
        return TEXT_FILE_EXTENSION;
    }

    /**
     * Try to find a file from its filename.
     * <p>
     * The algorithm checks if the filename is a full path, a path relative to
     * the current directory or a path relative to home directory.<br/> If no
     * file has been found, the extension is append to its name and the same
     * directories are parsed in the same order.
     * </p>
     *
     * @param filename
     *            the filename of the file to found
     * @param fileExt
     *            the default extension of the file. May be <code>null</code>.
     *            No dot is added during aggregation with the filename, so think
     *            to add it if it is required.
     * @return the <code>java.lang.File</code> instance associated to the
     *         filename if it was found, <code>null</code> otherwise.
     */
    public static File findPath(String filename, String fileExt) {
        File path = findPath(filename);
        if (path == null && fileExt != null) {
            String filenameWithExt = filename + fileExt;
            path = findPath(filenameWithExt);
        }
        return path;
    }

    /**
     * Try to find a file from its filename.
     * <p>
     * The algorithm checks if the filename is a full path, a path relative to
     * the current directory or a path relative to home directory.
     * </p>
     *
     * @param filename
     *            the filename of the file to found
     * @return the <code>java.lang.File</code> instance associated to the
     *         filename if it was found, <code>null</code> otherwise.
     */
    public static File findPath(String filename) {
        // case 1: full path
        File path = new File(filename);
        if (path.exists()) {
            return path;
        }

        // case 2: path relative to current directory
        File currentDir = Program.instance().getCurrentDirectory();
        path = new File(currentDir, filename);
        if (path.exists()) {
            return path;
        }

        // case 3: path relative to home directory
        File homeDir = Configuration.instance().getUserHome();
        path = new File(homeDir, filename);
        if (path.exists()) {
            return path;
        }
        return null;
    }

    public static void copyFile(BufferedInputStream source, File destination) {
        BufferedOutputStream output = null;
        try {
            output = new BufferedOutputStream(new FileOutputStream(destination));
            byte buffer[] = new byte[2048];
            while (true) {
                int n = source.read(buffer);
                if (n <= 0)
                    break;
                output.write(buffer, 0, n);
            }
        } catch (IOException e) {
            LOG.error("could not copy file '" + destination.getName() + "'", e);
        } finally {
            if (output != null) {
                try {
                    output.close();
                } catch (IOException e) {
                }
            }
        }
    }

    public static void copyFile(File source, File destination) {
        BufferedInputStream input = null;
        try {
            input = new BufferedInputStream(new FileInputStream(source));
            copyFile(input, destination);
        } catch (IOException e) {
            IOUtils.closeQuietly(input);
        }
    }

    public static File createTempDirectory() {
        try {
            File tempDirectory = File.createTempFile("resources", "");
            tempDirectory.delete();
            tempDirectory.mkdir();
            tempDirectories.add(tempDirectory);
            return tempDirectory;
        } catch (IOException e) {
            LOG.error("Error while creating temp directory", e);
            return null;
        }
    }

    public static int extractJar(File jar, File directory) {
        JarEntry entry = null;
        File currentFile = null;
        BufferedInputStream input = null;
        JarFile jarFile = null;
        int filesCount = 0;
        try {
            jarFile = new JarFile(jar);
            Enumeration<JarEntry> entries = jarFile.entries();

            while (entries.hasMoreElements()) {
                entry = entries.nextElement();
                currentFile = new File(directory, entry.getName());
                if (entry.isDirectory()) {
                    currentFile.mkdir();
                } else {
                    currentFile.createNewFile();
                    input = new BufferedInputStream(jarFile.getInputStream(entry));
                    copyFile(input, currentFile);
                    input.close();
                    filesCount++;
                }
            }
        } catch (IOException e) {
            LOG.error("Error extracting JAR file " + jar.getAbsolutePath(), e);
        } finally {
            try {
                if (input != null) {
                    input.close();
                }
                if (jarFile != null) {
                    jarFile.close();
                }
            } catch (IOException e) {
            }
        }
        return filesCount;
    }

    private static void addDirectoryToJar(File directory, JarOutputStream output, String prefix,
            PropertyChangeListener listener) throws IOException {
        try {
            File files[] = directory.listFiles();
            JarEntry entry = null;
            for (int i = 0; i < files.length; i++) {
                if (files[i].isDirectory()) {
                    if (prefix != null) {
                        entry = new JarEntry(prefix + "/" + files[i].getName() + "/");
                        output.putNextEntry(entry);
                        addDirectoryToJar(files[i], output, prefix + "/" + files[i].getName(), listener);
                    } else {
                        entry = new JarEntry(files[i].getName() + "/");
                        output.putNextEntry(entry);
                        addDirectoryToJar(files[i], output, files[i].getName(), listener);
                    }
                } else {
                    addFileToJar(files[i], output, prefix);
                    if (listener != null) {
                        listener.propertyChange(new PropertyChangeEvent(directory, "fileAdded", null, null));
                    }
                }
            }
        } catch (IOException e) {
            LOG.error("Error while adding directory '" + directory.getAbsolutePath() + "'", e);
            throw e;
        }
    }

    private static void addFileToJar(File fileToAdd, JarOutputStream output, String prefix) throws IOException {
        BufferedInputStream input = null;
        JarEntry entry = null;
        try {
            if (prefix != null)
                entry = new JarEntry(prefix + "/" + fileToAdd.getName());
            else
                entry = new JarEntry(fileToAdd.getName());
            output.putNextEntry(entry);
            input = new BufferedInputStream(new FileInputStream(fileToAdd));
            byte buffer[] = new byte[2048];
            while (true) {
                int n = input.read(buffer);
                if (n <= 0)
                    break;
                output.write(buffer, 0, n);
            }
            input.close();
        } catch (IOException e) {
            LOG.error("Error trying to add file '" + fileToAdd.getAbsolutePath() + "' to jar", e);
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e2) {
                }
            }
            throw e;
        }
    }

    public static void startJarEdit(File jarFile) {
        jar = new JarUtils(jarFile);
    }

    public static boolean stopJarEdit(File jarFile) {
        try {
            jar.save();
            jar = null;
            return true;
        } catch (IOException e) {
            LOG.error("Error while trying to save jar edits", e);
        }
        return false;
    }

    public static boolean addFileToJar(File fileToAdd, File jarFile, String prefix) {
        if (fileToAdd.isDirectory())
            return false;
        if (jar == null)
            startJarEdit(jarFile);
        try {
            jar.addFile(fileToAdd, prefix);
            return true;
        } catch (IOException e) {
            LOG.error("Error while adding file '" + fileToAdd.getAbsolutePath() + "' to jar file '"
                    + jarFile.getAbsolutePath() + "'", e);
            return false;
        }
    }

    public static boolean addDirectoryToJar(File directoryToAdd, File jarFile, String prefix) {
        if (!directoryToAdd.isDirectory())
            return false;
        if (jar == null)
            startJarEdit(jarFile);
        try {
            jar.addDirectory(directoryToAdd, prefix);
            return true;
        } catch (IOException e) {
            LOG.error("Error while trying to umount files", e);
            return false;
        }
    }

    public static void makeJar(File directory, File jar, String mainClass, PropertyChangeListener listener,
            Hashtable<String, String> manifestAttributes) {
        JarOutputStream jarOutput = null;
        try {
            jarOutput = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(jar)));
            addDirectoryToJar(directory, jarOutput, null, listener);
            StringBuffer sbuf = new StringBuffer();
            sbuf.append("Manifest-Version: 1.0\n");
            sbuf.append("Built-By: Colombbus\n");
            if (mainClass != null)
                sbuf.append("Main-Class: " + mainClass + "\n");
            if (manifestAttributes != null) {
                for (Enumeration<String> keys = manifestAttributes.keys(); keys.hasMoreElements();) {
                    String name = keys.nextElement();
                    sbuf.append(name + ": " + manifestAttributes.get(name) + "\n");
                }
            }
            InputStream is = new ByteArrayInputStream(sbuf.toString().getBytes("UTF-8"));

            JarEntry manifestEntry = new JarEntry("META-INF/MANIFEST.MF");
            jarOutput.putNextEntry(manifestEntry);

            byte buffer[] = new byte[2048];
            while (true) {
                int n = is.read(buffer);
                if (n <= 0)
                    break;
                jarOutput.write(buffer, 0, n);
            }
            is.close();
            jarOutput.close();
        } catch (Exception e) {
            LOG.error("Error while creating JAR file '" + jar.getAbsolutePath() + "'", e);
        } finally {
            try {
                if (jarOutput != null)
                    jarOutput.close();
            } catch (IOException e) {
            }
        }
    }

    public static int copyDirectory(File source, File destination) {
        int filesCount = 0;
        File[] sourceFiles = source.listFiles();
        for (File file : sourceFiles) {
            if (file.isDirectory()) {
                File destinationDirectory = new File(destination, file.getName());
                destinationDirectory.mkdir();
                filesCount += copyDirectory(file, destinationDirectory);
            } else {
                File destinationFile = new File(destination, file.getName());
                copyFile(file, destinationFile);
                filesCount++;
            }
        }
        return filesCount;
    }

    public static boolean deleteDirectory(File source) {
        if (!source.isDirectory())
            return false;
        File[] elements = source.listFiles();
        for (int i = 0; i < elements.length; i++) {
            if (elements[i].isDirectory()) {
                if (!deleteDirectory(elements[i]))
                    return false;
            } else {
                if (!elements[i].delete())
                    return false;
            }
        }
        return source.delete();
    }

    public static void clean() {
        for (File tempDirectory : tempDirectories) {
            deleteDirectory(tempDirectory);
        }
    }

    public static File findFile(String fileName) {
        File file = new File(fileName);
        if (!file.isAbsolute()) {
            // the name does not contain any directory reference : add the current directory
            file = new File(Program.instance().getCurrentDirectory(), fileName);
            // if file does not exist, try with user home directory
            if (!file.exists())
                file = new File(Configuration.instance().getUserHome(), fileName);
            fileName = file.getAbsolutePath();
        }
        if (!(file.exists()))
            return null;
        else
            return file;
    }

    /**
     * Creates a BufferedImage from a file.
     * @param fileName
     * @return
     * @throws Exception
     */
    public static File findFile(String fileName, String[] possibleExtensions) {
        int pointPosition = fileName.lastIndexOf('.');
        boolean extensionFound = false;
        if (pointPosition > -1) {
            // dot Found
            String extension = fileName.substring(pointPosition + 1);
            if (extension.length() >= 0) {
                extensionFound = true;
            }
        } else {
            // no dot found
            fileName += "."; //$NON-NLS-1$
        }
        if (extensionFound) {
            return findFile(fileName);
        } else {
            File file = new File(fileName);
            if (!file.isAbsolute()) {
                // the name does not contain any directory reference : add the current directory
                File currentDirectory = Program.instance().getCurrentDirectory();
                for (String extension : possibleExtensions) {
                    file = new File(currentDirectory, fileName + extension);
                    if (file.exists())
                        return file;
                }
                File userHome = Configuration.instance().getUserHome();
                LOG.debug("USER HOME : " + userHome);
                for (String extension : possibleExtensions) {
                    file = new File(userHome, fileName + extension);
                    if (file.exists())
                        return file;
                }
            } else {
                // File is absolute: we simply try to find the file with possible extensions
                for (String extension : possibleExtensions) {
                    file = new File(fileName + extension);
                    if (file.exists())
                        return file;
                }
            }
        }
        return null;
    }

}