DiskSpaceUtil.java 8.95 KB
/*
 * Decompiled with CFR 0_118.
 */
package com.day.io.disk;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;

public class DiskSpaceUtil {
    public static final String COMMAND_DISK_SPACE = "crx.diskSpaceMeasureCommand";
    public static final String COMMAND_ULIMIT = "crx.ulimitMeasureCommand";
    public static final String INTERVAL = "crx.diskSpaceMeasureInterval";
    private static final DiskSpaceUtil INSTANCE = new DiskSpaceUtil();
    private long defaultMeasureInterval = Long.decode(System.getProperty("crx.diskSpaceMeasureInterval", "60000"));
    private boolean unsupportedFileUsableSpace;
    private boolean unsupportedDiskFree;
    private long lastMeasuredTime;
    private long lastMeasuredAvailableSpace;
    private int maxOpenFiles;

    public static DiskSpaceUtil getInstance() {
        return INSTANCE;
    }

    public int getMaxOpenFiles() {
        if (this.maxOpenFiles != 0) {
            return this.maxOpenFiles;
        }
        if (this.isWindows()) {
            this.maxOpenFiles = Integer.MAX_VALUE;
        } else {
            String result = "";
            try {
                String command = System.getProperty("crx.ulimitMeasureCommand", "ulimit,-n");
                List cmd = DiskSpaceUtil.tokenize(command, ",");
                result = this.runProcess(cmd).trim();
                this.maxOpenFiles = Integer.parseInt(result);
            }
            catch (Exception e) {
                this.logDebug("ulimit not working: " + result + " " + e);
                this.maxOpenFiles = Integer.MAX_VALUE;
            }
        }
        this.logDebug("Maximum number of open files: " + this.maxOpenFiles);
        return this.maxOpenFiles;
    }

    public long getAvailableDiskSpaceMB() {
        return this.getAvailableDiskSpaceMB(new File("."), this.defaultMeasureInterval);
    }

    public long getAvailableDiskSpaceMB(File dir) {
        return this.getAvailableDiskSpaceMB(dir, this.defaultMeasureInterval);
    }

    public long getAvailableDiskSpaceMB(File dir, long interval) {
        if (interval < 0) {
            return Integer.MAX_VALUE;
        }
        long now = System.currentTimeMillis();
        if (this.lastMeasuredTime == 0 || now > this.lastMeasuredTime + interval) {
            this.lastMeasuredTime = now;
            this.lastMeasuredAvailableSpace = this.getUsableSpace(dir);
        }
        return this.lastMeasuredAvailableSpace;
    }

    private long getUsableSpace(File dir) {
        if (!this.unsupportedFileUsableSpace) {
            try {
                Class class_ = File.class;
                Method usable = class_.getMethod("getUsableSpace", new Class[0]);
                long space = (Long)usable.invoke(dir, new Object[0]);
                if (space == 0) {
                    return -1;
                }
                this.logDebug("Usable disk space: " + (space /= 0x100000) + " MB (using \"File.getUsableSpace\")");
                return space;
            }
            catch (Exception e) {
                this.logDebug("Method File.getUsableSpace is not supported: " + e);
            }
        }
        this.unsupportedFileUsableSpace = true;
        return this.diskFree(dir);
    }

    private boolean isWindows() {
        return System.getProperty("os.name").startsWith("Windows");
    }

    private long diskFree(File dir) {
        if (!this.unsupportedDiskFree) {
            try {
                boolean isWindows;
                String defaultCommand;
                if (this.isWindows()) {
                    defaultCommand = "cmd,/c,dir,${dir}";
                    isWindows = true;
                } else {
                    defaultCommand = "df,-m,${dir}";
                    isWindows = false;
                }
                String command = System.getProperty("crx.diskSpaceMeasureCommand", defaultCommand);
                List cmd = DiskSpaceUtil.tokenize(command, ",");
                for (int i = 0; i < cmd.size(); ++i) {
                    if (!"${dir}".equals(cmd.get(i))) continue;
                    cmd.set(i, dir.getAbsolutePath());
                }
                String result = this.runProcess(cmd);
                long x = this.parseResult(result, isWindows);
                if (x != -1) {
                    return x;
                }
            }
            catch (Exception e) {
                this.logDebug("df / dir not working: " + e);
            }
        }
        this.unsupportedDiskFree = true;
        return -1;
    }

    private long parseResult(String result, boolean isWindows) {
        String[] lines = result.split("\n");
        if (!isWindows && lines.length > 1) {
            int index = 0;
            boolean found = false;
            List lineList = DiskSpaceUtil.tokenize(lines[0], " ");
            for (int i = 0; i < lineList.size(); ++i) {
                String h = (String)lineList.get(i);
                if (h.startsWith("Avail")) {
                    found = true;
                    break;
                }
                ++index;
            }
            if (found) {
                List data;
                if (lines.length > 2 && !lines[2].trim().equals(lines[2])) {
                    lines[1] = lines[1].trim() + " " + lines[2].trim();
                }
                if ((data = DiskSpaceUtil.tokenize(lines[1], " ")).size() >= index) {
                    long space = Long.parseLong((String)data.get(index));
                    this.logDebug("Usable disk space: " + space + " MB (using \"df\")");
                    return space;
                }
            }
        }
        if (isWindows && lines.length > 0) {
            int i;
            String line = lines[lines.length - 1];
            int end = -1;
            for (i = line.length() - 1; i >= 0; --i) {
                if (!Character.isDigit(line.charAt(i))) continue;
                end = i;
                break;
            }
            while (i >= 0 && line.charAt(i) != ' ') {
                --i;
            }
            StringBuilder buff = new StringBuilder();
            while (i <= end) {
                char c = line.charAt(i);
                if (Character.isDigit(c)) {
                    buff.append(line.charAt(i));
                }
                ++i;
            }
            String s = buff.toString();
            long space = Long.parseLong(s) / 1024 / 1024;
            this.logDebug("Usable disk space: " + space + " MB (using \"dir\")");
            return space;
        }
        return -1;
    }

    private static List tokenize(String s, String delimiters) {
        if (s == null || s.length() == 0) {
            return Collections.emptyList();
        }
        ArrayList<String> list = new ArrayList<String>();
        StringTokenizer tokenizer = new StringTokenizer(s, delimiters);
        while (tokenizer.hasMoreTokens()) {
            list.add(tokenizer.nextToken());
        }
        return list;
    }

    private String runProcess(List args) {
        try {
            this.logDebug("runProcess args: " + args);
            String[] argList = new String[args.size()];
            args.toArray(argList);
            Process p = Runtime.getRuntime().exec(argList);
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            Thread threadOut = this.copyInThread(p.getInputStream(), out, false);
            Thread threadErr = this.copyInThread(p.getErrorStream(), out, false);
            p.waitFor();
            int exitValue = p.exitValue();
            threadOut.join();
            threadErr.join();
            String result = new String(out.toByteArray());
            this.logDebug("exitValue=" + exitValue);
            this.logDebug(result);
            return result;
        }
        catch (IOException e) {
            throw new RuntimeException(e);
        }
        catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    private void logDebug(String message) {
    }

    private Thread copyInThread(final InputStream in, final OutputStream out, final boolean toSysOut) {
        Thread t = new Thread(){

            public void run() {
                try {
                    do {
                        int x;
                        if ((x = in.read()) < 0) {
                            return;
                        }
                        if (out == null) continue;
                        out.write(x);
                        if (!toSysOut) continue;
                        System.out.print((char)x);
                    } while (true);
                }
                catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        };
        t.start();
        return t;
    }

    public long getDefaultMeasureInterval() {
        return this.defaultMeasureInterval;
    }

}