All Downloads are FREE. Search and download functionalities are using the official Maven repository.

oshi.software.common.AbstractOperatingSystem Maven / Gradle / Ivy

/**
 * MIT License
 *
 * Copyright (c) 2010 - 2020 The OSHI Project Contributors: https://github.com/oshi/oshi/graphs/contributors
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package oshi.software.common;

import static oshi.util.Memoizer.memoize;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.function.Supplier;

import com.sun.jna.Platform; // NOSONAR squid:S1191

import oshi.driver.unix.Who;
import oshi.software.os.OSProcess;
import oshi.software.os.OSService;
import oshi.software.os.OSSession;
import oshi.software.os.OperatingSystem;
import oshi.util.GlobalConfig;

public abstract class AbstractOperatingSystem implements OperatingSystem {

    public static final String OSHI_OS_UNIX_WHOCOMMAND = "oshi.os.unix.whoCommand";
    protected static final boolean USE_WHO_COMMAND = GlobalConfig.get(OSHI_OS_UNIX_WHOCOMMAND, false);

    private final Supplier manufacturer = memoize(this::queryManufacturer);
    private final Supplier familyVersionInfo = memoize(this::queryFamilyVersionInfo);
    private final Supplier bitness = memoize(this::queryPlatformBitness);
    // Test if sudo or admin privileges: 1 = unknown, 0 = no, 1 = yes
    private final Supplier elevated = memoize(this::queryElevated);

    /*
     * Comparators for use in processSort().
     */
    private static final Comparator CPU_DESC_SORT = Comparator
            .comparingDouble(OSProcess::getProcessCpuLoadCumulative).reversed();

    private static final Comparator RSS_DESC_SORT = Comparator.comparingLong(OSProcess::getResidentSetSize)
            .reversed();

    private static final Comparator UPTIME_ASC_SORT = Comparator.comparingLong(OSProcess::getUpTime);

    private static final Comparator UPTIME_DESC_SORT = UPTIME_ASC_SORT.reversed();

    private static final Comparator PID_ASC_SORT = Comparator.comparingInt(OSProcess::getProcessID);

    private static final Comparator PARENTPID_ASC_SORT = Comparator
            .comparingInt(OSProcess::getParentProcessID);

    private static final Comparator NAME_ASC_SORT = Comparator.comparing(OSProcess::getName,
            String.CASE_INSENSITIVE_ORDER);

    @Override
    public String getManufacturer() {
        return manufacturer.get();
    }

    protected abstract String queryManufacturer();

    @Override
    public String getFamily() {
        return familyVersionInfo.get().family;
    }

    @Override
    public OSVersionInfo getVersionInfo() {
        return familyVersionInfo.get().versionInfo;
    }

    protected abstract FamilyVersionInfo queryFamilyVersionInfo();

    @Override
    public int getBitness() {
        return bitness.get();
    }

    private int queryPlatformBitness() {
        if (Platform.is64Bit()) {
            return 64;
        }
        // Initialize based on JVM Bitness. Individual OS implementations will test
        // if 32-bit JVM running on 64-bit OS
        int jvmBitness = System.getProperty("os.arch").indexOf("64") != -1 ? 64 : 32;
        return queryBitness(jvmBitness);
    }

    /**
     * Backup OS-specific query to determine bitness if previous checks fail
     *
     * @param jvmBitness
     *            The bitness of the JVM
     * @return The operating system bitness
     */
    protected abstract int queryBitness(int jvmBitness);

    @Override
    public boolean isElevated() {
        return elevated.get();
    }

    @Override
    public OSService[] getServices() {
        return new OSService[0];
    }

    protected abstract boolean queryElevated();

    /**
     * Sorts an array of processes using the specified sorting, returning an array
     * with the top limit results if positive.
     *
     * @param processes
     *            The array to sort
     * @param limit
     *            The number of results to return if positive; if zero returns all
     *            results
     * @param sort
     *            The sorting to use, or null
     * @return An array of size limit (if positive) or of all processes, sorted as
     *         specified
     */
    protected List processSort(List processes, int limit, ProcessSort sort) {
        if (sort != null) {
            switch (sort) {
            case CPU:
                processes.sort(CPU_DESC_SORT);
                break;
            case MEMORY:
                processes.sort(RSS_DESC_SORT);
                break;
            case OLDEST:
                processes.sort(UPTIME_DESC_SORT);
                break;
            case NEWEST:
                processes.sort(UPTIME_ASC_SORT);
                break;
            case PID:
                processes.sort(PID_ASC_SORT);
                break;
            case PARENTPID:
                processes.sort(PARENTPID_ASC_SORT);
                break;
            case NAME:
                processes.sort(NAME_ASC_SORT);
                break;
            default:
                // Should never get here! If you get this exception you've
                // added something to the enum without adding it here. Tsk.
                throw new IllegalArgumentException("Unimplemented enum type: " + sort.toString());
            }
        }
        // Return max of limit or process size
        // Nonpositive limit means return all
        int maxProcs = processes.size();
        if (limit > 0 && maxProcs > limit) {
            maxProcs = limit;
        } else {
            return processes;
        }
        List procs = new ArrayList<>();
        for (int i = 0; i < maxProcs; i++) {
            procs.add(processes.get(i));
        }
        return procs;
    }

    @Override
    public List getSessions() {
        return Collections.unmodifiableList(Who.queryWho());
    }

    @Override
    public List getProcesses() {
        return getProcesses(0, null);
    }

    @Override
    public List getProcesses(Collection pids) {
        List returnValue = new ArrayList<>(pids.size());
        for (Integer pid : pids) {
            OSProcess process = getProcess(pid);
            if (process != null) {
                returnValue.add(process);
            }
        }
        return Collections.unmodifiableList(returnValue);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(getManufacturer()).append(' ').append(getFamily()).append(' ').append(getVersionInfo());
        return sb.toString();
    }

    protected static final class FamilyVersionInfo {
        private final String family;
        private final OSVersionInfo versionInfo;

        public FamilyVersionInfo(String family, OSVersionInfo versionInfo) {
            this.family = family;
            this.versionInfo = versionInfo;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy