    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *     https://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017package org.apache.commons.exec;
    018
    019import java.io.File;
    020import java.util.Locale;
    021
    022/**
    023 * Condition that tests the OS type.
    024 *
    025 * Copied and adapted from Apache Ant 1.9.6 from org.apache.tools.ant.taskdefs.condition.OS.
    026 */
    027public final class OS {
    028
    029    /**
    030     * OS family that can be tested for. {@value}
    031     */
    032    public static final String FAMILY_9X = "win9x";
    033    /**
    034     * OS family that can be tested for. {@value}
    035     */
    036    public static final String FAMILY_DOS = "dos";
    037    /**
    038     * OS family that can be tested for. {@value}
    039     */
    040    public static final String FAMILY_MAC = "mac";
    041    /**
    042     * OS family that can be tested for. {@value}
    043     */
    044    public static final String FAMILY_NETWARE = "netware";
    045    /**
    046     * OS family that can be tested for. {@value}
    047     */
    048    public static final String FAMILY_NT = "winnt";
    049    /**
    050     * OS family that can be tested for. {@value}
    051     */
    052    public static final String FAMILY_OS2 = "os/2";
    053    /**
    054     * OS family that can be tested for. {@value}
    055     */
    056    public static final String FAMILY_OS400 = "os/400";
    057    /**
    058     * OS family that can be tested for. {@value}
    059     */
    060    public static final String FAMILY_TANDEM = "tandem";
    061    /**
    062     * OS family that can be tested for. {@value}
    063     */
    064    public static final String FAMILY_UNIX = "unix";
    065    /**
    066     * OS family that can be tested for. {@value}
    067     */
    068    public static final String FAMILY_VMS = "openvms";
    069    /**
    070     * OS family that can be tested for. {@value}
    071     */
    072    public static final String FAMILY_WINDOWS = "windows";
    073    /**
    074     * OS family that can be tested for. {@value}
    075     */
    076    public static final String FAMILY_ZOS = "z/os";
    077
    078    private static final String DARWIN = "darwin";
    079
    080    private static final String OS_NAME = System.getProperty("os.name").toLowerCase(Locale.ROOT);
    081    private static final String OS_ARCH = System.getProperty("os.arch").toLowerCase(Locale.ROOT);
    082    private static final String OS_VERSION = System.getProperty("os.version").toLowerCase(Locale.ROOT);
    083    private static final String PATH_SEP = File.pathSeparator;
    084
    085    /**
    086     * Tests whether the OS on which commons-exec is executing matches the given OS architecture.
    087     *
    088     * @param arch the OS architecture to check for.
    089     * @return whether if the OS matches.
    090     */
    091    public static boolean isArch(final String arch) {
    092        return isOs(null, null, arch, null);
    093    }
    094
    095    /**
    096     * Tests whether the OS on which commons-exec is executing matches the given OS family.
    097     *
    098     * @param family the family to check for.
    099     * @return whether if the OS matches.
    100     */
    101    private static boolean isFamily(final String family) {
    102        return isOs(family, null, null, null);
    103    }
    104
    105    /**
    106     * Tests whether the OS is in the DOS family.
    107     *
    108     * @return whether the OS is in the DOS family.
    109     */
    110    public static boolean isFamilyDOS() {
    111        return isFamily(FAMILY_DOS);
    112    }
    113
    114    /**
    115     * Tests whether the OS is in the Mac family.
    116     *
    117     * @return whether the OS is in the Mac family.
    118     */
    119    public static boolean isFamilyMac() {
    120        return isFamily(FAMILY_MAC);
    121    }
    122
    123    /**
    124     * Tests whether the OS is in the Netware family.
    125     *
    126     * @return whether the OS is in the Netware family.
    127     */
    128    public static boolean isFamilyNetware() {
    129        return isFamily(FAMILY_NETWARE);
    130    }
    131
    132    /**
    133     * Tests whether the OS is in the OpenVMS family.
    134     *
    135     * @return whether the OS is in the OpenVMS family.
    136     */
    137    public static boolean isFamilyOpenVms() {
    138        return isFamily(FAMILY_VMS);
    139    }
    140
    141    /**
    142     * Tests whether the OS is in the OS/2 family.
    143     *
    144     * @return whether the OS is in the OS/2 family.
    145     */
    146    public static boolean isFamilyOS2() {
    147        return isFamily(FAMILY_OS2);
    148    }
    149
    150    /**
    151     * Tests whether the OS is in the OS/400 family.
    152     *
    153     * @return whether the OS is in the OS/400 family.
    154     */
    155    public static boolean isFamilyOS400() {
    156        return isFamily(FAMILY_OS400);
    157    }
    158
    159    /**
    160     * Tests whether the OS is in the Tandem family.
    161     *
    162     * @return whether the OS is in the Tandem family.
    163     */
    164    public static boolean isFamilyTandem() {
    165        return isFamily(FAMILY_TANDEM);
    166    }
    167
    168    /**
    169     * Tests whether the OS is in the Unix family.
    170     *
    171     * @return whether the OS is in the Unix family.
    172     */
    173    public static boolean isFamilyUnix() {
    174        return isFamily(FAMILY_UNIX);
    175    }
    176
    177    /**
    178     * Tests whether the OS is in the Windows 9x family.
    179     *
    180     * @return whether the OS is in the Windows 9x family.
    181     */
    182    public static boolean isFamilyWin9x() {
    183        return isFamily(FAMILY_9X);
    184    }
    185
    186    /**
    187     * Tests whether the OS is in the Windows family.
    188     *
    189     * @return whether the OS is in the Windows family.
    190     */
    191    public static boolean isFamilyWindows() {
    192        return isFamily(FAMILY_WINDOWS);
    193    }
    194
    195    /**
    196     * Tests whether the OS is in the Windows NT family.
    197     *
    198     * @return whether the OS is in the Windows NT family.
    199     */
    200    public static boolean isFamilyWinNT() {
    201        return isFamily(FAMILY_NT);
    202    }
    203
    204    /**
    205     * Tests whether the OS is in the z/OS family.
    206     *
    207     * @return whether the OS is in the z/OS family.
    208     */
    209    public static boolean isFamilyZOS() {
    210        return isFamily(FAMILY_ZOS);
    211    }
    212
    213    /**
    214     * Tests whether if the OS on which commons-exec is executing matches the given OS name.
    215     *
    216     * @param name the OS name to check for.
    217     * @return whether the OS matches.
    218     */
    219    public static boolean isName(final String name) {
    220        return isOs(null, name, null, null);
    221    }
    222
    223    /**
    224     * Tests whether the OS on which commons-exec is executing matches the given OS family, name, architecture and version.
    225     *
    226     * @param family  The OS family.
    227     * @param name    The OS name.
    228     * @param arch    The OS architecture.
    229     * @param version The OS version.
    230     * @return whether the OS matches.
    231     */
    232    public static boolean isOs(final String family, final String name, final String arch, final String version) {
    233        boolean retValue = false;
    234        if (family != null || name != null || arch != null || version != null) {
    235            boolean isFamily = true;
    236            boolean isName = true;
    237            boolean isArch = true;
    238            boolean isVersion = true;
    239            if (family != null) {
    240                // Windows probing logic relies on the word 'windows' in the OS
    241                final boolean isWindows = OS_NAME.contains(FAMILY_WINDOWS);
    242                boolean is9x = false;
    243                boolean isNT = false;
    244                if (isWindows) {
    245                    // there are only four 9x platforms that we look for
    246                    is9x = OS_NAME.contains("95") || OS_NAME.contains("98") || OS_NAME.contains("me")
    247                    // Windows CE isn't really 9x, but crippled enough to
    248                    // be a muchness. Ant doesn't run on CE, anyway.
    249                            || OS_NAME.contains("ce");
    250                    isNT = !is9x;
    251                }
    252                switch (family) {
    253                case FAMILY_WINDOWS:
    254                    isFamily = isWindows;
    255                    break;
    256                case FAMILY_9X:
    257                    isFamily = isWindows && is9x;
    258                    break;
    259                case FAMILY_NT:
    260                    isFamily = isWindows && isNT;
    261                    break;
    262                case FAMILY_OS2:
    263                    isFamily = OS_NAME.contains(FAMILY_OS2);
    264                    break;
    265                case FAMILY_NETWARE:
    266                    isFamily = OS_NAME.contains(FAMILY_NETWARE);
    267                    break;
    268                case FAMILY_DOS:
    269                    isFamily = PATH_SEP.equals(";") && !isFamily(FAMILY_NETWARE);
    270                    break;
    271                case FAMILY_MAC:
    272                    isFamily = OS_NAME.contains(FAMILY_MAC) || OS_NAME.contains(DARWIN);
    273                    break;
    274                case FAMILY_TANDEM:
    275                    isFamily = OS_NAME.contains("nonstop_kernel");
    276                    break;
    277                case FAMILY_UNIX:
    278                    isFamily = PATH_SEP.equals(":") && !isFamily(FAMILY_VMS) && (!isFamily(FAMILY_MAC) || OS_NAME.endsWith("x") || OS_NAME.contains(DARWIN));
    279                    break;
    280                case FAMILY_ZOS:
    281                    isFamily = OS_NAME.contains(FAMILY_ZOS) || OS_NAME.contains("os/390");
    282                    break;
    283                case FAMILY_OS400:
    284                    isFamily = OS_NAME.contains(FAMILY_OS400);
    285                    break;
    286                case FAMILY_VMS:
    287                    isFamily = OS_NAME.contains(FAMILY_VMS);
    288                    break;
    289                default:
    290                    throw new IllegalArgumentException("Don\'t know how to detect OS family \"" + family + "\"");
    291                }
    292            }
    293            if (name != null) {
    294                isName = name.equals(OS_NAME);
    295            }
    296            if (arch != null) {
    297                isArch = arch.equals(OS_ARCH);
    298            }
    299            if (version != null) {
    300                isVersion = version.equals(OS_VERSION);
    301            }
    302            retValue = isFamily && isName && isArch && isVersion;
    303        }
    304        return retValue;
    305    }
    306
    307    /**
    308     * Tests whether the OS on which commonss-exec is executing matches the given OS version.
    309     *
    310     * @param version the OS version to check for.
    311     * @return whether if the OS matches.
    312     */
    313    public static boolean isVersion(final String version) {
    314        return isOs(null, null, null, version);
    315    }
    316
    317    /**
    318     * Avoids instances.
    319     */
    320    private OS() {
    321    }
    322}