org.paxle.tools.sysmon.impl.DiskspaceMonitoring.java Source code

Java tutorial

Introduction

Here is the source code for org.paxle.tools.sysmon.impl.DiskspaceMonitoring.java

Source

/**
 * This file is part of the Paxle project.
 * Visit http://www.paxle.net for more information.
 * Copyright 2007-2010 the original author or authors.
 *
 * Licensed under the terms of the Common Public License 1.0 ("CPL 1.0").
 * Any use, reproduction or distribution of this program constitutes the recipient's acceptance of this agreement.
 * The full license text is available under http://www.opensource.org/licenses/cpl1.0.txt
 * or in the file LICENSE.txt in the root directory of the Paxle distribution.
 *
 * Unless required by applicable law or agreed to in writing, this software is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 */

package org.paxle.tools.sysmon.impl;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.ResourceBundle;

import org.apache.commons.io.FileSystemUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import org.osgi.framework.Constants;
import org.osgi.service.monitor.Monitorable;
import org.osgi.service.monitor.StatusVariable;

@Component(metatype = false, name = DiskspaceMonitoring.PID)
@Service(Monitorable.class)
@Property(name = "Monitorable-Localization", value = DiskspaceMonitoring.RB_BASENAME)
public class DiskspaceMonitoring implements Monitorable {
    /**
     * The {@link Constants#SERVICE_PID} of this {@link Monitorable}
     */
    static final String PID = "os.disk";

    /**
     * {@link ResourceBundle} basename
     */
    static final String RB_BASENAME = "OSGI-INF/l10n/DiskspaceMonitoring";

    private static enum Mode {
        commons_io, jre6
    };

    /**
     * Query mode: jre6 or commons-io
     */
    static final String VAR_QUERY_MODE = "query.mode";

    /**
     * Free disk space in MB.
     */
    static final String VAR_SPACE_FREE = "disk.space.free";

    /**
     * The names of all {@link StatusVariable status-variables} supported by this {@link Monitorable}
     */
    @SuppressWarnings("serial")
    private static final HashSet<String> VAR_NAMES = new HashSet<String>() {
        {
            add(VAR_QUERY_MODE);
            add(VAR_SPACE_FREE);
        }
    };

    /**
     * Descriptions of all {@link StatusVariable status-variables} supported by this {@link Monitorable}
     */
    private final ResourceBundle rb = ResourceBundle.getBundle(RB_BASENAME);

    /**
     * For logging
     */
    private Log logger = LogFactory.getLog(this.getClass());

    /**
     * Defines if commons-io or the appropriate method of java 6.0
     * should be used for disk space querying.
     */
    private Mode queryMode = Mode.commons_io;

    public DiskspaceMonitoring() {
        try {
            File.class.getMethod("getUsableSpace", (Class[]) null);
            this.queryMode = Mode.jre6;
        } catch (NoSuchMethodException e) {
            this.queryMode = Mode.commons_io;
        }
    }

    public String[] getStatusVariableNames() {
        return VAR_NAMES.toArray(new String[VAR_NAMES.size()]);
    }

    public String getDescription(String name) throws IllegalArgumentException {
        if (!VAR_NAMES.contains(name)) {
            throw new IllegalArgumentException("Invalid Status Variable name " + name);
        }

        return this.rb.getString(name);
    }

    public StatusVariable getStatusVariable(String name) throws IllegalArgumentException {
        if (!VAR_NAMES.contains(name)) {
            throw new IllegalArgumentException("Invalid Status Variable name " + name);
        }

        if (name.equalsIgnoreCase(VAR_SPACE_FREE)) {
            long freeDisk = -1;
            try {
                /* 
                 * Query free disk space.
                 * 
                 * We need to call this within a separate thread due to the following bug: 
                 * https://bugs.pxl.li/view.php?id=278
                 */
                FreeSpaceThread queryThread = new FreeSpaceThread();
                queryThread.start();

                // waiting for the result
                queryThread.join(10000);

                if (queryThread.isAlive()) {
                    final StackTraceElement[] stackTrace = queryThread.getStackTrace();
                    final Exception rte = new RuntimeException("Query thread is still alive");
                    rte.setStackTrace(stackTrace);
                    this.logger.warn("FreeSpace query thread is still alive!", rte);

                } else {
                    freeDisk = queryThread.freeSpace;
                }
            } catch (InterruptedException e) {
                // ignore this
            }

            return new StatusVariable(name, StatusVariable.CM_GAUGE, freeDisk);
        } else if (name.equalsIgnoreCase(VAR_QUERY_MODE)) {
            return new StatusVariable(name, StatusVariable.CM_SI, this.queryMode.toString());
        }

        return null;
    }

    public boolean notifiesOnChange(String name) throws IllegalArgumentException {
        return false;
    }

    public boolean resetStatusVariable(String name) throws IllegalArgumentException {
        return false;
    }

    private class FreeSpaceThread extends Thread {
        /**
         * For logging
         */
        private final Log logger = LogFactory.getLog(this.getClass());

        public long freeSpace = 0;

        public FreeSpaceThread() {
            super("FreeDiskSpaceThread");
        }

        @Override
        public void run() {
            try {
                final File paxleDir = new File(System.getProperty("paxle.data")).getCanonicalFile();
                switch (queryMode) {
                case jre6:
                    this.freeSpace = freeSpaceMB_jre6(paxleDir);
                    break;

                default:
                    this.freeSpace = freeSpaceMB_commons(paxleDir);
                    break;
                }
            } catch (Throwable e) {
                this.logger.error(String.format("Unexpected '%s' while trying to query free disk-space.",
                        e.getClass().getName()), e);
                this.freeSpace = -1;
            }
        }

        private long freeSpaceMB_commons(File paxleDir) throws IOException {
            long freeDisk = FileSystemUtils.freeSpaceKb(paxleDir.toString());
            freeDisk /= 1024;
            return freeDisk;
        }

        private long freeSpaceMB_jre6(File paxleDir) throws SecurityException, NoSuchMethodException,
                IllegalArgumentException, IllegalAccessException, InvocationTargetException {
            Method m = File.class.getMethod("getUsableSpace", (Class[]) null);
            Long bytes = (Long) m.invoke(paxleDir, (Object[]) null);
            return bytes.longValue() / (1024 * 1024);
        }
    }
}