/*
 * Written by Dawid Kurzyniec and released to the public domain, as explained
 * at http://creativecommons.org/licenses/publicdomain
 */

package edu.emory.mathcs.util.natives;

import java.io.*;
import edu.emory.mathcs.util.io.*;
import java.security.*;

/**
 * Utility methods to operate on files.
 *
 * @author Dawid Kurzyniec
 * @version 1.0
 */
public class FilesystemUtils {

    private static final String[] chmodCandidates = new String[] {
        "/bin/chmod", "/usr/bin/chmod", "/bin/chmod.exe", "/usr/bin/chmod.exe"
    };

    private FilesystemUtils() {}

    public static boolean setExecutable(final File file, final boolean executable) {
        checkWrite(file);
        return ((Boolean)AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                return Boolean.valueOf(setExecutablePrivileged(file, executable));
            }
        })).booleanValue();
    }

    private static boolean setExecutablePrivileged(File file, boolean executable) {
        File chmod = findFile(chmodCandidates);
        if (chmod == null) return false;
        String[] cmdarr = new String[] { chmod.getAbsolutePath(),
            "a" + (executable ? "+" : "-") + "x", file.getPath() };
        return cmdexec(cmdarr);
    }

    public static boolean setPrivate(final File file) {
        checkWrite(file);
        return ((Boolean)AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                return Boolean.valueOf(setPrivatePrivileged(file));
            }
        })).booleanValue();
    }

    private static boolean setPrivatePrivileged(File file) {
        File chmod = findFile(chmodCandidates);
        if (chmod == null) return false;
        String[] cmdarr = new String[] { chmod.getAbsolutePath(),
            "og=", file.getPath() };
        return cmdexec(cmdarr);
    }


    private static boolean cmdexec(String[] cmdarr) {
        try {
            Process p = Runtime.getRuntime().exec(cmdarr);
            p.waitFor();
            return p.exitValue() != 0;
        }
        catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return false;
        }
        catch (IOException e) {
            return false;
        }
    }

    public static File findFile(String[] candidates) {
        for (int i=0; i<candidates.length; i++) {
            File f = new File(candidates[i]);
            if (f.isFile()) return f;
        }
        return null;
    }


    private static void checkWrite(File file) {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkWrite(file.getPath());
        }
    }

}
