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 *      http://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.lang3;
018
019import java.io.File;
020
021/**
022 * Helpers for {@code java.lang.System}.
023 *
024 * <p>
025 * If a system property cannot be read due to security restrictions, the corresponding field in this class will be set
026 * to {@code null} and a message will be written to {@code System.err}.
027 * </p>
028 * <p>
029 * #ThreadSafe#
030 * </p>
031 *
032 * @since 1.0
033 * @see SystemProperties
034 */
035public class SystemUtils {
036
037    /**
038     * The prefix String for all Windows OS.
039     */
040    private static final String OS_NAME_WINDOWS_PREFIX = "Windows";
041
042    // System property constants
043    // -----------------------------------------------------------------------
044    // These MUST be declared first. Other constants depend on this.
045
046    /**
047     * The {@code file.encoding} System Property.
048     *
049     * <p>
050     * File encoding, such as {@code Cp1252}.
051     * </p>
052     * <p>
053     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
054     * not exist.
055     * </p>
056     * <p>
057     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
058     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
059     * sync with that System property.
060     * </p>
061     *
062     * @see SystemProperties#getFileEncoding()
063     * @since 2.0
064     * @since Java 1.2
065     */
066    public static final String FILE_ENCODING = SystemProperties.getFileEncoding();
067
068    /**
069     * The {@code file.separator} System Property.
070     * The file separator is:
071     *
072     * <ul>
073     * <li>{@code "/"} on UNIX</li>
074     * <li>{@code "\"} on Windows.</li>
075     * </ul>
076     *
077     * <p>
078     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
079     * not exist.
080     * </p>
081     * <p>
082     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
083     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
084     * sync with that System property.
085     * </p>
086     *
087     * @see SystemProperties#getFileSeparator()
088     * @deprecated Use {@link File#separator}, since it is guaranteed to be a
089     *             string containing a single character and it does not require a privilege check.
090     * @since Java 1.1
091     */
092    @Deprecated
093    public static final String FILE_SEPARATOR = SystemProperties.getFileSeparator();
094
095    /**
096     * The {@code java.awt.fonts} System Property.
097     *
098     * <p>
099     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
100     * not exist.
101     * </p>
102     * <p>
103     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
104     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
105     * sync with that System property.
106     * </p>
107     *
108     * @see SystemProperties#getJavaAwtFonts()
109     * @since 2.1
110     */
111    public static final String JAVA_AWT_FONTS = SystemProperties.getJavaAwtFonts();
112
113    /**
114     * The {@code java.awt.graphicsenv} System Property.
115     *
116     * <p>
117     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
118     * not exist.
119     * </p>
120     * <p>
121     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
122     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
123     * sync with that System property.
124     * </p>
125     *
126     * @see SystemProperties#getJavaAwtGraphicsenv()
127     * @since 2.1
128     */
129    public static final String JAVA_AWT_GRAPHICSENV = SystemProperties.getJavaAwtGraphicsenv();
130
131    /**
132     * The {@code java.awt.headless} System Property. The value of this property is the String {@code "true"} or
133     * {@code "false"}.
134     *
135     * <p>
136     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
137     * not exist.
138     * </p>
139     * <p>
140     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
141     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
142     * sync with that System property.
143     * </p>
144     *
145     * @see #isJavaAwtHeadless()
146     * @see SystemProperties#getJavaAwtHeadless()
147     * @since 2.1
148     * @since Java 1.4
149     */
150    public static final String JAVA_AWT_HEADLESS = SystemProperties.getJavaAwtHeadless();
151
152    /**
153     * The {@code java.awt.printerjob} System Property.
154     *
155     * <p>
156     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
157     * not exist.
158     * </p>
159     * <p>
160     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
161     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
162     * sync with that System property.
163     * </p>
164     *
165     * @see SystemProperties#getJavaAwtPrinterjob()
166     * @since 2.1
167     */
168    public static final String JAVA_AWT_PRINTERJOB = SystemProperties.getJavaAwtPrinterjob();
169
170    /**
171     * The {@code java.class.path} System Property. Java class path.
172     *
173     * <p>
174     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
175     * not exist.
176     * </p>
177     * <p>
178     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
179     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
180     * sync with that System property.
181     * </p>
182     *
183     * @see SystemProperties#getJavaClassPath()
184     * @since Java 1.1
185     */
186    public static final String JAVA_CLASS_PATH = SystemProperties.getJavaClassPath();
187
188    /**
189     * The {@code java.class.version} System Property. Java class format version number.
190     *
191     * <p>
192     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
193     * not exist.
194     * </p>
195     * <p>
196     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
197     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
198     * sync with that System property.
199     * </p>
200     *
201     * @see SystemProperties#getJavaClassVersion()
202     * @since Java 1.1
203     */
204    public static final String JAVA_CLASS_VERSION = SystemProperties.getJavaClassVersion();
205
206    /**
207     * The {@code java.compiler} System Property. Name of JIT compiler to use. First in JDK version 1.2. Not used in Sun
208     * JDKs after 1.2.
209     *
210     * <p>
211     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
212     * not exist.
213     * </p>
214     * <p>
215     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
216     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
217     * sync with that System property.
218     * </p>
219     *
220     * @see SystemProperties#getJavaCompiler()
221     * @since Java 1.2. Not used in Sun versions after 1.2.
222     */
223    public static final String JAVA_COMPILER = SystemProperties.getJavaCompiler();
224
225    /**
226     * The {@code java.endorsed.dirs} System Property. Path of endorsed directory or directories.
227     *
228     * <p>
229     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
230     * not exist.
231     * </p>
232     * <p>
233     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
234     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
235     * sync with that System property.
236     * </p>
237     *
238     * @see SystemProperties#getJavaEndorsedDirs()
239     * @since Java 1.4
240     */
241    public static final String JAVA_ENDORSED_DIRS = SystemProperties.getJavaEndorsedDirs();
242
243    /**
244     * The {@code java.ext.dirs} System Property. Path of extension directory or directories.
245     *
246     * <p>
247     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
248     * not exist.
249     * </p>
250     * <p>
251     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
252     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
253     * sync with that System property.
254     * </p>
255     *
256     * @see SystemProperties#getJavaExtDirs()
257     * @since Java 1.3
258     */
259    public static final String JAVA_EXT_DIRS = SystemProperties.getJavaExtDirs();
260
261    /**
262     * The {@code java.home} System Property. Java installation directory.
263     *
264     * <p>
265     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
266     * not exist.
267     * </p>
268     * <p>
269     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
270     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
271     * sync with that System property.
272     * </p>
273     *
274     * @see SystemProperties#getJavaHome()
275     * @since Java 1.1
276     */
277    public static final String JAVA_HOME = SystemProperties.getJavaHome();
278
279    /**
280     * The {@code java.io.tmpdir} System Property. Default temp file path.
281     *
282     * <p>
283     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
284     * not exist.
285     * </p>
286     * <p>
287     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
288     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
289     * sync with that System property.
290     * </p>
291     *
292     * @see SystemProperties#getJavaIoTmpdir()
293     * @since Java 1.2
294     */
295    public static final String JAVA_IO_TMPDIR = SystemProperties.getJavaIoTmpdir();
296
297    /**
298     * The {@code java.library.path} System Property. List of paths to search when loading libraries.
299     *
300     * <p>
301     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
302     * not exist.
303     * </p>
304     * <p>
305     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
306     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
307     * sync with that System property.
308     * </p>
309     *
310     * @see SystemProperties#getJavaLibraryPath()
311     * @since Java 1.2
312     */
313    public static final String JAVA_LIBRARY_PATH = SystemProperties.getJavaLibraryPath();
314
315    /**
316     * The {@code java.runtime.name} System Property. Java Runtime Environment name.
317     *
318     * <p>
319     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
320     * not exist.
321     * </p>
322     * <p>
323     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
324     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
325     * sync with that System property.
326     * </p>
327     *
328     * @see SystemProperties#getJavaRuntimeName()
329     * @since 2.0
330     * @since Java 1.3
331     */
332    public static final String JAVA_RUNTIME_NAME = SystemProperties.getJavaRuntimeName();
333
334    /**
335     * The {@code java.runtime.version} System Property. Java Runtime Environment version.
336     *
337     * <p>
338     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
339     * not exist.
340     * </p>
341     * <p>
342     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
343     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
344     * sync with that System property.
345     * </p>
346     *
347     * @see SystemProperties#getJavaRuntimeVersion()
348     * @since 2.0
349     * @since Java 1.3
350     */
351    public static final String JAVA_RUNTIME_VERSION = SystemProperties.getJavaRuntimeVersion();
352
353    /**
354     * The {@code java.specification.name} System Property. Java Runtime Environment specification name.
355     *
356     * <p>
357     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
358     * not exist.
359     * </p>
360     * <p>
361     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
362     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
363     * sync with that System property.
364     * </p>
365     *
366     * @see SystemProperties#getJavaSpecificationName()
367     * @since Java 1.2
368     */
369    public static final String JAVA_SPECIFICATION_NAME = SystemProperties.getJavaSpecificationName();
370
371    /**
372     * The {@code java.specification.vendor} System Property. Java Runtime Environment specification vendor.
373     *
374     * <p>
375     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
376     * not exist.
377     * </p>
378     * <p>
379     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
380     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
381     * sync with that System property.
382     * </p>
383     *
384     * @see SystemProperties#getJavaSpecificationVendor()
385     * @since Java 1.2
386     */
387    public static final String JAVA_SPECIFICATION_VENDOR = SystemProperties.getJavaSpecificationVendor();
388
389    /**
390     * The {@code java.specification.version} System Property. Java Runtime Environment specification version.
391     *
392     * <p>
393     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
394     * not exist.
395     * </p>
396     * <p>
397     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
398     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
399     * sync with that System property.
400     * </p>
401     *
402     * @see SystemProperties#getJavaSpecificationVersion()
403     * @since Java 1.3
404     */
405    public static final String JAVA_SPECIFICATION_VERSION = SystemProperties.getJavaSpecificationVersion();
406
407    private static final JavaVersion JAVA_SPECIFICATION_VERSION_AS_ENUM = JavaVersion.get(JAVA_SPECIFICATION_VERSION);
408
409    /**
410     * The {@code java.util.prefs.PreferencesFactory} System Property. A class name.
411     *
412     * <p>
413     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
414     * not exist.
415     * </p>
416     * <p>
417     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
418     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
419     * sync with that System property.
420     * </p>
421     *
422     * @see SystemProperties#getJavaUtilPrefsPreferencesFactory()
423     * @since 2.1
424     * @since Java 1.4
425     */
426    public static final String JAVA_UTIL_PREFS_PREFERENCES_FACTORY = SystemProperties.getJavaUtilPrefsPreferencesFactory();
427
428    /**
429     * The {@code java.vendor} System Property. Java vendor-specific string.
430     *
431     * <p>
432     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
433     * not exist.
434     * </p>
435     * <p>
436     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
437     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
438     * sync with that System property.
439     * </p>
440     *
441     * @see SystemProperties#getJavaVendor()
442     * @since Java 1.1
443     */
444    public static final String JAVA_VENDOR = SystemProperties.getJavaVendor();
445
446    /**
447     * The {@code java.vendor.url} System Property. Java vendor URL.
448     *
449     * <p>
450     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
451     * not exist.
452     * </p>
453     * <p>
454     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
455     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
456     * sync with that System property.
457     * </p>
458     *
459     * @see SystemProperties#getJavaVendorUrl()
460     * @since Java 1.1
461     */
462    public static final String JAVA_VENDOR_URL = SystemProperties.getJavaVendorUrl();
463
464    /**
465     * The {@code java.version} System Property. Java version number.
466     *
467     * <p>
468     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
469     * not exist.
470     * </p>
471     * <p>
472     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
473     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
474     * sync with that System property.
475     * </p>
476     *
477     * @see SystemProperties#getJavaVersion()
478     * @since Java 1.1
479     */
480    public static final String JAVA_VERSION = SystemProperties.getJavaVersion();
481
482    /**
483     * The {@code java.vm.info} System Property. Java Virtual Machine implementation info.
484     *
485     * <p>
486     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
487     * not exist.
488     * </p>
489     * <p>
490     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
491     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
492     * sync with that System property.
493     * </p>
494     *
495     * @see SystemProperties#getJavaVmInfo()
496     * @since 2.0
497     * @since Java 1.2
498     */
499    public static final String JAVA_VM_INFO = SystemProperties.getJavaVmInfo();
500
501    /**
502     * The {@code java.vm.name} System Property. Java Virtual Machine implementation name.
503     *
504     * <p>
505     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
506     * not exist.
507     * </p>
508     * <p>
509     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
510     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
511     * sync with that System property.
512     * </p>
513     *
514     * @see SystemProperties#getJavaVmName()
515     * @since Java 1.2
516     */
517    public static final String JAVA_VM_NAME = SystemProperties.getJavaVmName();
518
519    /**
520     * The {@code java.vm.specification.name} System Property. Java Virtual Machine specification name.
521     *
522     * <p>
523     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
524     * not exist.
525     * </p>
526     * <p>
527     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
528     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
529     * sync with that System property.
530     * </p>
531     *
532     * @see SystemProperties#getJavaVmSpecificationName()
533     * @since Java 1.2
534     */
535    public static final String JAVA_VM_SPECIFICATION_NAME = SystemProperties.getJavaVmSpecificationName();
536
537    /**
538     * The {@code java.vm.specification.vendor} System Property. Java Virtual Machine specification vendor.
539     *
540     * <p>
541     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
542     * not exist.
543     * </p>
544     * <p>
545     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
546     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
547     * sync with that System property.
548     * </p>
549     *
550     * @see SystemProperties#getJavaVmSpecificationVendor()
551     * @since Java 1.2
552     */
553    public static final String JAVA_VM_SPECIFICATION_VENDOR = SystemProperties.getJavaVmSpecificationVendor();
554
555    /**
556     * The {@code java.vm.specification.version} System Property. Java Virtual Machine specification version.
557     *
558     * <p>
559     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
560     * not exist.
561     * </p>
562     * <p>
563     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
564     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
565     * sync with that System property.
566     * </p>
567     *
568     * @see SystemProperties#getJavaVmSpecificationVersion()
569     * @since Java 1.2
570     */
571    public static final String JAVA_VM_SPECIFICATION_VERSION = SystemProperties.getJavaVmSpecificationVersion();
572
573    /**
574     * The {@code java.vm.vendor} System Property. Java Virtual Machine implementation vendor.
575     *
576     * <p>
577     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
578     * not exist.
579     * </p>
580     * <p>
581     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
582     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
583     * sync with that System property.
584     * </p>
585     *
586     * @see SystemProperties#getJavaVmVendor()
587     * @since Java 1.2
588     */
589    public static final String JAVA_VM_VENDOR = SystemProperties.getJavaVmVendor();
590
591    /**
592     * The {@code java.vm.version} System Property. Java Virtual Machine implementation version.
593     *
594     * <p>
595     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
596     * not exist.
597     * </p>
598     * <p>
599     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
600     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
601     * sync with that System property.
602     * </p>
603     *
604     * @see SystemProperties#getJavaVmVersion()
605     * @since Java 1.2
606     */
607    public static final String JAVA_VM_VERSION = SystemProperties.getJavaVmVersion();
608
609    /**
610     * The {@code line.separator} System Property. Line separator ({@code &quot;\n&quot;} on UNIX).
611     *
612     * <p>
613     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
614     * not exist.
615     * </p>
616     * <p>
617     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
618     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
619     * sync with that System property.
620     * </p>
621     *
622     * @see SystemProperties#getLineSeparator()
623     * @deprecated Use {@link System#lineSeparator()} instead, since it does not require a privilege check.
624     * @since Java 1.1
625     */
626    @Deprecated
627    public static final String LINE_SEPARATOR = SystemProperties.getLineSeparator();
628
629    /**
630     * The {@code os.arch} System Property. Operating system architecture.
631     *
632     * <p>
633     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
634     * not exist.
635     * </p>
636     * <p>
637     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
638     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
639     * sync with that System property.
640     * </p>
641     *
642     * @see SystemProperties#getOsArch()
643     * @since Java 1.1
644     */
645    public static final String OS_ARCH = SystemProperties.getOsArch();
646
647    /**
648     * The {@code os.name} System Property. Operating system name.
649     *
650     * <p>
651     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
652     * not exist.
653     * </p>
654     * <p>
655     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
656     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
657     * sync with that System property.
658     * </p>
659     *
660     * @see SystemProperties#getOsName()
661     * @since Java 1.1
662     */
663    public static final String OS_NAME = SystemProperties.getOsName();
664
665    /**
666     * The {@code os.version} System Property. Operating system version.
667     *
668     * <p>
669     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
670     * not exist.
671     * </p>
672     * <p>
673     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
674     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
675     * sync with that System property.
676     * </p>
677     *
678     * @see SystemProperties#getOsVersion()
679     * @since Java 1.1
680     */
681    public static final String OS_VERSION = SystemProperties.getOsVersion();
682
683    /**
684     * The {@code path.separator} System Property. Path separator ({@code &quot;:&quot;} on UNIX).
685     *
686     * <p>
687     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
688     * not exist.
689     * </p>
690     * <p>
691     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
692     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
693     * sync with that System property.
694     * </p>
695     *
696     * @see SystemProperties#getPathSeparator()
697     * @deprecated Use {@link File#pathSeparator}, since it is guaranteed to be a
698     *             string containing a single character and it does not require a privilege check.
699     * @since Java 1.1
700     */
701    @Deprecated
702    public static final String PATH_SEPARATOR = SystemProperties.getPathSeparator();
703
704    /**
705     * The {@code user.country} or {@code user.region} System Property. User's country code, such as {@code "GB"}. First
706     * in Java version 1.2 as {@code user.region}. Renamed to {@code user.country} in 1.4
707     *
708     * <p>
709     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
710     * not exist.
711     * </p>
712     * <p>
713     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
714     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
715     * sync with that System property.
716     * </p>
717     *
718     * @since 2.0
719     * @since Java 1.2
720     */
721    public static final String USER_COUNTRY = SystemProperties.getProperty(SystemProperties.USER_COUNTRY,
722            () -> SystemProperties.getProperty(SystemProperties.USER_REGION));
723
724    /**
725     * The {@code user.dir} System Property. User's current working directory.
726     *
727     * <p>
728     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
729     * not exist.
730     * </p>
731     * <p>
732     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
733     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
734     * sync with that System property.
735     * </p>
736     *
737     * @see SystemProperties#getUserDir()
738     * @since Java 1.1
739     */
740    public static final String USER_DIR = SystemProperties.getUserDir();
741
742    /**
743     * The {@code user.home} System Property. User's home directory.
744     *
745     * <p>
746     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
747     * not exist.
748     * </p>
749     * <p>
750     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
751     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
752     * sync with that System property.
753     * </p>
754     *
755     * @see SystemProperties#getUserHome()
756     * @since Java 1.1
757     */
758    public static final String USER_HOME = SystemProperties.getUserHome();
759
760    /**
761     * The {@code user.language} System Property. User's language code, such as {@code "en"}.
762     *
763     * <p>
764     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
765     * not exist.
766     * </p>
767     * <p>
768     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
769     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
770     * sync with that System property.
771     * </p>
772     *
773     * @see SystemProperties#getUserLanguage()
774     * @since 2.0
775     * @since Java 1.2
776     */
777    public static final String USER_LANGUAGE = SystemProperties.getUserLanguage();
778
779    /**
780     * The {@code user.name} System Property. User's account name.
781     *
782     * <p>
783     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
784     * not exist.
785     * </p>
786     * <p>
787     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
788     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
789     * sync with that System property.
790     * </p>
791     *
792     * @see SystemProperties#getUserName()
793     * @since Java 1.1
794     */
795    public static final String USER_NAME = SystemProperties.getUserName();
796
797    /**
798     * The {@code user.timezone} System Property. For example: {@code "America/Los_Angeles"}.
799     *
800     * <p>
801     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
802     * not exist.
803     * </p>
804     * <p>
805     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
806     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
807     * sync with that System property.
808     * </p>
809     *
810     * @see SystemProperties#getUserTimezone()
811     * @since 2.1
812     */
813    public static final String USER_TIMEZONE = SystemProperties.getUserTimezone();
814
815    // Java version checks
816    // -----------------------------------------------------------------------
817    // These MUST be declared after those above as they depend on the
818    // values being set up
819
820    /**
821     * Is {@code true} if this is Java version 1.1 (also 1.1.x versions).
822     *
823     * <p>
824     * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
825     * </p>
826     * <p>
827     * This value is initialized when the class is loaded.
828     * </p>
829     */
830    public static final boolean IS_JAVA_1_1 = getJavaVersionMatches("1.1");
831
832    /**
833     * Is {@code true} if this is Java version 1.2 (also 1.2.x versions).
834     *
835     * <p>
836     * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
837     * </p>
838     * <p>
839     * This value is initialized when the class is loaded.
840     * </p>
841     */
842    public static final boolean IS_JAVA_1_2 = getJavaVersionMatches("1.2");
843
844    /**
845     * Is {@code true} if this is Java version 1.3 (also 1.3.x versions).
846     *
847     * <p>
848     * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
849     * </p>
850     * <p>
851     * This value is initialized when the class is loaded.
852     * </p>
853     */
854    public static final boolean IS_JAVA_1_3 = getJavaVersionMatches("1.3");
855
856    /**
857     * Is {@code true} if this is Java version 1.4 (also 1.4.x versions).
858     *
859     * <p>
860     * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
861     * </p>
862     * <p>
863     * This value is initialized when the class is loaded.
864     * </p>
865     */
866    public static final boolean IS_JAVA_1_4 = getJavaVersionMatches("1.4");
867
868    /**
869     * Is {@code true} if this is Java version 1.5 (also 1.5.x versions).
870     *
871     * <p>
872     * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
873     * </p>
874     * <p>
875     * This value is initialized when the class is loaded.
876     * </p>
877     */
878    public static final boolean IS_JAVA_1_5 = getJavaVersionMatches("1.5");
879
880    /**
881     * Is {@code true} if this is Java version 1.6 (also 1.6.x versions).
882     *
883     * <p>
884     * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
885     * </p>
886     * <p>
887     * This value is initialized when the class is loaded.
888     * </p>
889     */
890    public static final boolean IS_JAVA_1_6 = getJavaVersionMatches("1.6");
891
892    /**
893     * Is {@code true} if this is Java version 1.7 (also 1.7.x versions).
894     *
895     * <p>
896     * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
897     * </p>
898     * <p>
899     * This value is initialized when the class is loaded.
900     * </p>
901     *
902     * @since 3.0
903     */
904    public static final boolean IS_JAVA_1_7 = getJavaVersionMatches("1.7");
905
906    /**
907     * Is {@code true} if this is Java version 1.8 (also 1.8.x versions).
908     *
909     * <p>
910     * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
911     * </p>
912     * <p>
913     * This value is initialized when the class is loaded.
914     * </p>
915     *
916     * @since 3.3.2
917     */
918    public static final boolean IS_JAVA_1_8 = getJavaVersionMatches("1.8");
919
920    /**
921     * Is {@code true} if this is Java version 1.9 (also 1.9.x versions).
922     *
923     * <p>
924     * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
925     * </p>
926     * <p>
927     * This value is initialized when the class is loaded.
928     * </p>
929     *
930     * @since 3.4
931     *
932     * @deprecated As of release 3.5, replaced by {@link #IS_JAVA_9}
933     */
934    @Deprecated
935    public static final boolean IS_JAVA_1_9 = getJavaVersionMatches("9");
936
937    /**
938     * Is {@code true} if this is Java version 9 (also 9.x versions).
939     *
940     * <p>
941     * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
942     * </p>
943     * <p>
944     * This value is initialized when the class is loaded.
945     * </p>
946     *
947     * @since 3.5
948     */
949    public static final boolean IS_JAVA_9 = getJavaVersionMatches("9");
950
951    /**
952     * Is {@code true} if this is Java version 10 (also 10.x versions).
953     *
954     * <p>
955     * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
956     * </p>
957     * <p>
958     * This value is initialized when the class is loaded.
959     * </p>
960     *
961     * @since 3.7
962     */
963    public static final boolean IS_JAVA_10 = getJavaVersionMatches("10");
964
965    /**
966     * Is {@code true} if this is Java version 11 (also 11.x versions).
967     *
968     * <p>
969     * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
970     * </p>
971     * <p>
972     * This value is initialized when the class is loaded.
973     * </p>
974     *
975     * @since 3.8
976     */
977    public static final boolean IS_JAVA_11 = getJavaVersionMatches("11");
978
979    /**
980     * Is {@code true} if this is Java version 12 (also 12.x versions).
981     *
982     * <p>
983     * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
984     * </p>
985     * <p>
986     * This value is initialized when the class is loaded.
987     * </p>
988     *
989     * @since 3.9
990     */
991    public static final boolean IS_JAVA_12 = getJavaVersionMatches("12");
992
993    /**
994     * Is {@code true} if this is Java version 13 (also 13.x versions).
995     *
996     * <p>
997     * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
998     * </p>
999     * <p>
1000     * This value is initialized when the class is loaded.
1001     * </p>
1002     *
1003     * @since 3.9
1004     */
1005    public static final boolean IS_JAVA_13 = getJavaVersionMatches("13");
1006
1007    /**
1008     * Is {@code true} if this is Java version 14 (also 14.x versions).
1009     *
1010     * <p>
1011     * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
1012     * </p>
1013     * <p>
1014     * This value is initialized when the class is loaded.
1015     * </p>
1016     *
1017     * @since 3.10
1018     */
1019    public static final boolean IS_JAVA_14 = getJavaVersionMatches("14");
1020
1021    /**
1022     * Is {@code true} if this is Java version 15 (also 15.x versions).
1023     *
1024     * <p>
1025     * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
1026     * </p>
1027     * <p>
1028     * This value is initialized when the class is loaded.
1029     * </p>
1030     *
1031     * @since 3.10
1032     */
1033    public static final boolean IS_JAVA_15 = getJavaVersionMatches("15");
1034
1035    /**
1036     * Is {@code true} if this is Java version 16 (also 16.x versions).
1037     * <p>
1038     * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
1039     * </p>
1040     * <p>
1041     * This value is initialized when the class is loaded.
1042     * </p>
1043     *
1044     * @since 3.13.0
1045     */
1046    public static final boolean IS_JAVA_16 = getJavaVersionMatches("16");
1047
1048    /**
1049     * Is {@code true} if this is Java version 17 (also 17.x versions).
1050     * <p>
1051     * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
1052     * </p>
1053     * <p>
1054     * This value is initialized when the class is loaded.
1055     * </p>
1056     *
1057     * @since 3.13.0
1058     */
1059    public static final boolean IS_JAVA_17 = getJavaVersionMatches("17");
1060
1061    /**
1062     * Is {@code true} if this is Java version 18 (also 18.x versions).
1063     * <p>
1064     * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
1065     * </p>
1066     * <p>
1067     * This value is initialized when the class is loaded.
1068     * </p>
1069     *
1070     * @since 3.13.0
1071     */
1072    public static final boolean IS_JAVA_18 = getJavaVersionMatches("18");
1073
1074    /**
1075     * Is {@code true} if this is Java version 19 (also 19.x versions).
1076     * <p>
1077     * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
1078     * </p>
1079     * <p>
1080     * This value is initialized when the class is loaded.
1081     * </p>
1082     *
1083     * @since 3.13.0
1084     */
1085    public static final boolean IS_JAVA_19 = getJavaVersionMatches("19");
1086
1087    /**
1088     * Is {@code true} if this is Java version 20 (also 20.x versions).
1089     * <p>
1090     * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
1091     * </p>
1092     * <p>
1093     * This value is initialized when the class is loaded.
1094     * </p>
1095     *
1096     * @since 3.13.0
1097     */
1098    public static final boolean IS_JAVA_20 = getJavaVersionMatches("20");
1099
1100    /**
1101     * Is {@code true} if this is Java version 21 (also 21.x versions).
1102     * <p>
1103     * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
1104     * </p>
1105     * <p>
1106     * This value is initialized when the class is loaded.
1107     * </p>
1108     *
1109     * @since 3.13.0
1110     */
1111    public static final boolean IS_JAVA_21 = getJavaVersionMatches("21");
1112
1113    // Operating system checks
1114    // -----------------------------------------------------------------------
1115    // These MUST be declared after those above as they depend on the
1116    // values being set up
1117    // Please advise dev@commons.apache.org if you want another added
1118    // or a mistake corrected
1119
1120    /**
1121     * Is {@code true} if this is AIX.
1122     *
1123     * <p>
1124     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1125     * </p>
1126     * <p>
1127     * This value is initialized when the class is loaded.
1128     * </p>
1129     *
1130     * @since 2.0
1131     */
1132    public static final boolean IS_OS_AIX = getOsMatchesName("AIX");
1133
1134    /**
1135     * Is {@code true} if this is HP-UX.
1136     *
1137     * <p>
1138     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1139     * </p>
1140     * <p>
1141     * This value is initialized when the class is loaded.
1142     * </p>
1143     *
1144     * @since 2.0
1145     */
1146    public static final boolean IS_OS_HP_UX = getOsMatchesName("HP-UX");
1147
1148    /**
1149     * Is {@code true} if this is IBM OS/400.
1150     *
1151     * <p>
1152     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1153     * </p>
1154     * <p>
1155     * This value is initialized when the class is loaded.
1156     * </p>
1157     *
1158     * @since 3.3
1159     */
1160    public static final boolean IS_OS_400 = getOsMatchesName("OS/400");
1161
1162    /**
1163     * Is {@code true} if this is Irix.
1164     *
1165     * <p>
1166     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1167     * </p>
1168     * <p>
1169     * This value is initialized when the class is loaded.
1170     * </p>
1171     *
1172     * @since 2.0
1173     */
1174    public static final boolean IS_OS_IRIX = getOsMatchesName("Irix");
1175
1176    /**
1177     * Is {@code true} if this is Linux.
1178     *
1179     * <p>
1180     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1181     * </p>
1182     * <p>
1183     * This value is initialized when the class is loaded.
1184     * </p>
1185     *
1186     * @since 2.0
1187     */
1188    public static final boolean IS_OS_LINUX = getOsMatchesName("Linux") || getOsMatchesName("LINUX");
1189
1190    /**
1191     * Is {@code true} if this is Mac.
1192     *
1193     * <p>
1194     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1195     * </p>
1196     * <p>
1197     * This value is initialized when the class is loaded.
1198     * </p>
1199     *
1200     * @since 2.0
1201     */
1202    public static final boolean IS_OS_MAC = getOsMatchesName("Mac");
1203
1204    /**
1205     * Is {@code true} if this is Mac.
1206     *
1207     * <p>
1208     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1209     * </p>
1210     * <p>
1211     * This value is initialized when the class is loaded.
1212     * </p>
1213     *
1214     * @since 2.0
1215     */
1216    public static final boolean IS_OS_MAC_OSX = getOsMatchesName("Mac OS X");
1217
1218    /**
1219     * Is {@code true} if this is Mac OS X Cheetah.
1220     *
1221     * <p>
1222     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1223     * </p>
1224     * <p>
1225     * This value is initialized when the class is loaded.
1226     * </p>
1227     *
1228     * @since 3.4
1229     */
1230    public static final boolean IS_OS_MAC_OSX_CHEETAH = getOsMatches("Mac OS X", "10.0");
1231
1232    /**
1233     * Is {@code true} if this is Mac OS X Puma.
1234     *
1235     * <p>
1236     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1237     * </p>
1238     * <p>
1239     * This value is initialized when the class is loaded.
1240     * </p>
1241     *
1242     * @since 3.4
1243     */
1244    public static final boolean IS_OS_MAC_OSX_PUMA = getOsMatches("Mac OS X", "10.1");
1245
1246    /**
1247     * Is {@code true} if this is Mac OS X Jaguar.
1248     *
1249     * <p>
1250     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1251     * </p>
1252     * <p>
1253     * This value is initialized when the class is loaded.
1254     * </p>
1255     *
1256     * @since 3.4
1257     */
1258    public static final boolean IS_OS_MAC_OSX_JAGUAR = getOsMatches("Mac OS X", "10.2");
1259
1260    /**
1261     * Is {@code true} if this is Mac OS X Panther.
1262     *
1263     * <p>
1264     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1265     * </p>
1266     * <p>
1267     * This value is initialized when the class is loaded.
1268     * </p>
1269     *
1270     * @since 3.4
1271     */
1272    public static final boolean IS_OS_MAC_OSX_PANTHER = getOsMatches("Mac OS X", "10.3");
1273
1274    /**
1275     * Is {@code true} if this is Mac OS X Tiger.
1276     *
1277     * <p>
1278     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1279     * </p>
1280     * <p>
1281     * This value is initialized when the class is loaded.
1282     * </p>
1283     *
1284     * @since 3.4
1285     */
1286    public static final boolean IS_OS_MAC_OSX_TIGER = getOsMatches("Mac OS X", "10.4");
1287
1288    /**
1289     * Is {@code true} if this is Mac OS X Leopard.
1290     *
1291     * <p>
1292     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1293     * </p>
1294     * <p>
1295     * This value is initialized when the class is loaded.
1296     * </p>
1297     *
1298     * @since 3.4
1299     */
1300    public static final boolean IS_OS_MAC_OSX_LEOPARD = getOsMatches("Mac OS X", "10.5");
1301
1302    /**
1303     * Is {@code true} if this is Mac OS X Snow Leopard.
1304     *
1305     * <p>
1306     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1307     * </p>
1308     * <p>
1309     * This value is initialized when the class is loaded.
1310     * </p>
1311     *
1312     * @since 3.4
1313     */
1314    public static final boolean IS_OS_MAC_OSX_SNOW_LEOPARD = getOsMatches("Mac OS X", "10.6");
1315
1316    /**
1317     * Is {@code true} if this is Mac OS X Lion.
1318     *
1319     * <p>
1320     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1321     * </p>
1322     * <p>
1323     * This value is initialized when the class is loaded.
1324     * </p>
1325     *
1326     * @since 3.4
1327     */
1328    public static final boolean IS_OS_MAC_OSX_LION = getOsMatches("Mac OS X", "10.7");
1329
1330    /**
1331     * Is {@code true} if this is Mac OS X Mountain Lion.
1332     *
1333     * <p>
1334     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1335     * </p>
1336     * <p>
1337     * This value is initialized when the class is loaded.
1338     * </p>
1339     *
1340     * @since 3.4
1341     */
1342    public static final boolean IS_OS_MAC_OSX_MOUNTAIN_LION = getOsMatches("Mac OS X", "10.8");
1343
1344    /**
1345     * Is {@code true} if this is Mac OS X Mavericks.
1346     *
1347     * <p>
1348     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1349     * </p>
1350     * <p>
1351     * This value is initialized when the class is loaded.
1352     * </p>
1353     *
1354     * @since 3.4
1355     */
1356    public static final boolean IS_OS_MAC_OSX_MAVERICKS = getOsMatches("Mac OS X", "10.9");
1357
1358    /**
1359     * Is {@code true} if this is Mac OS X Yosemite.
1360     *
1361     * <p>
1362     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1363     * </p>
1364     * <p>
1365     * This value is initialized when the class is loaded.
1366     * </p>
1367     *
1368     * @since 3.4
1369     */
1370    public static final boolean IS_OS_MAC_OSX_YOSEMITE = getOsMatches("Mac OS X", "10.10");
1371
1372    /**
1373     * Is {@code true} if this is Mac OS X El Capitan.
1374     *
1375     * <p>
1376     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1377     * </p>
1378     * <p>
1379     * This value is initialized when the class is loaded.
1380     * </p>
1381     *
1382     * @since 3.5
1383     */
1384    public static final boolean IS_OS_MAC_OSX_EL_CAPITAN = getOsMatches("Mac OS X", "10.11");
1385
1386    /**
1387     * Is {@code true} if this is Mac OS X Sierra.
1388     *
1389     * <p>
1390     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1391     * </p>
1392     * <p>
1393     * This value is initialized when the class is loaded.
1394     * </p>
1395     *
1396     * @since 3.12.0
1397     */
1398    public static final boolean IS_OS_MAC_OSX_SIERRA = getOsMatches("Mac OS X", "10.12");
1399
1400    /**
1401     * Is {@code true} if this is Mac OS X High Sierra.
1402     *
1403     * <p>
1404     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1405     * </p>
1406     * <p>
1407     * This value is initialized when the class is loaded.
1408     * </p>
1409     *
1410     * @since 3.12.0
1411     */
1412    public static final boolean IS_OS_MAC_OSX_HIGH_SIERRA = getOsMatches("Mac OS X", "10.13");
1413
1414    /**
1415     * Is {@code true} if this is Mac OS X Mojave.
1416     *
1417     * <p>
1418     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1419     * </p>
1420     * <p>
1421     * This value is initialized when the class is loaded.
1422     * </p>
1423     *
1424     * @since 3.12.0
1425     */
1426    public static final boolean IS_OS_MAC_OSX_MOJAVE = getOsMatches("Mac OS X", "10.14");
1427
1428    /**
1429     * Is {@code true} if this is Mac OS X Catalina.
1430     *
1431     * <p>
1432     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1433     * </p>
1434     * <p>
1435     * This value is initialized when the class is loaded.
1436     * </p>
1437     *
1438     * @since 3.12.0
1439     */
1440    public static final boolean IS_OS_MAC_OSX_CATALINA = getOsMatches("Mac OS X", "10.15");
1441
1442    /**
1443     * Is {@code true} if this is Mac OS X Big Sur.
1444     *
1445     * <p>
1446     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1447     * </p>
1448     * <p>
1449     * This value is initialized when the class is loaded.
1450     * </p>
1451     *
1452     * @since 3.12.0
1453     */
1454    public static final boolean IS_OS_MAC_OSX_BIG_SUR = getOsMatches("Mac OS X", "11");
1455
1456    /**
1457     * Is {@code true} if this is Mac OS X Monterey.
1458     *
1459     * <p>
1460     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1461     * </p>
1462     * <p>
1463     * This value is initialized when the class is loaded.
1464     * </p>
1465     * @since 3.13.0
1466     */
1467    public static final boolean IS_OS_MAC_OSX_MONTEREY = getOsMatches("Mac OS X", "12");
1468
1469    /**
1470     * Is {@code true} if this is Mac OS X Ventura.
1471     *
1472     * <p>
1473     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1474     * </p>
1475     * <p>
1476     * This value is initialized when the class is loaded.
1477     * </p>
1478     * @since 3.13.0
1479     */
1480    public static final boolean IS_OS_MAC_OSX_VENTURA = getOsMatches("Mac OS X", "13");
1481
1482    /**
1483     * Is {@code true} if this is FreeBSD.
1484     *
1485     * <p>
1486     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1487     * </p>
1488     * <p>
1489     * This value is initialized when the class is loaded.
1490     * </p>
1491     *
1492     * @since 3.1
1493     */
1494    public static final boolean IS_OS_FREE_BSD = getOsMatchesName("FreeBSD");
1495
1496    /**
1497     * Is {@code true} if this is OpenBSD.
1498     *
1499     * <p>
1500     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1501     * </p>
1502     * <p>
1503     * This value is initialized when the class is loaded.
1504     * </p>
1505     *
1506     * @since 3.1
1507     */
1508    public static final boolean IS_OS_OPEN_BSD = getOsMatchesName("OpenBSD");
1509
1510    /**
1511     * Is {@code true} if this is NetBSD.
1512     *
1513     * <p>
1514     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1515     * </p>
1516     * <p>
1517     * This value is initialized when the class is loaded.
1518     * </p>
1519     *
1520     * @since 3.1
1521     */
1522    public static final boolean IS_OS_NET_BSD = getOsMatchesName("NetBSD");
1523
1524    /**
1525     * Is {@code true} if this is OS/2.
1526     *
1527     * <p>
1528     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1529     * </p>
1530     * <p>
1531     * This value is initialized when the class is loaded.
1532     * </p>
1533     *
1534     * @since 2.0
1535     */
1536    public static final boolean IS_OS_OS2 = getOsMatchesName("OS/2");
1537
1538    /**
1539     * Is {@code true} if this is Solaris.
1540     *
1541     * <p>
1542     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1543     * </p>
1544     * <p>
1545     * This value is initialized when the class is loaded.
1546     * </p>
1547     *
1548     * @since 2.0
1549     */
1550    public static final boolean IS_OS_SOLARIS = getOsMatchesName("Solaris");
1551
1552    /**
1553     * Is {@code true} if this is SunOS.
1554     *
1555     * <p>
1556     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1557     * </p>
1558     * <p>
1559     * This value is initialized when the class is loaded.
1560     * </p>
1561     *
1562     * @since 2.0
1563     */
1564    public static final boolean IS_OS_SUN_OS = getOsMatchesName("SunOS");
1565
1566    /**
1567     * Is {@code true} if this is a UNIX like system, as in any of AIX, HP-UX, Irix, Linux, MacOSX, Solaris or SUN OS.
1568     *
1569     * <p>
1570     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1571     * </p>
1572     * <p>
1573     * This value is initialized when the class is loaded.
1574     * </p>
1575     *
1576     * @since 2.1
1577     */
1578    public static final boolean IS_OS_UNIX = IS_OS_AIX || IS_OS_HP_UX || IS_OS_IRIX || IS_OS_LINUX || IS_OS_MAC_OSX
1579            || IS_OS_SOLARIS || IS_OS_SUN_OS || IS_OS_FREE_BSD || IS_OS_OPEN_BSD || IS_OS_NET_BSD;
1580
1581    /**
1582     * Is {@code true} if this is Windows.
1583     *
1584     * <p>
1585     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1586     * </p>
1587     * <p>
1588     * This value is initialized when the class is loaded.
1589     * </p>
1590     *
1591     * @since 2.0
1592     */
1593    public static final boolean IS_OS_WINDOWS = getOsMatchesName(OS_NAME_WINDOWS_PREFIX);
1594
1595    /**
1596     * Is {@code true} if this is Windows 2000.
1597     *
1598     * <p>
1599     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1600     * </p>
1601     * <p>
1602     * This value is initialized when the class is loaded.
1603     * </p>
1604     *
1605     * @since 2.0
1606     */
1607    public static final boolean IS_OS_WINDOWS_2000 = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " 2000");
1608
1609    /**
1610     * Is {@code true} if this is Windows 2003.
1611     *
1612     * <p>
1613     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1614     * </p>
1615     * <p>
1616     * This value is initialized when the class is loaded.
1617     * </p>
1618     *
1619     * @since 3.1
1620     */
1621    public static final boolean IS_OS_WINDOWS_2003 = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " 2003");
1622
1623    /**
1624     * Is {@code true} if this is Windows Server 2008.
1625     *
1626     * <p>
1627     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1628     * </p>
1629     * <p>
1630     * This value is initialized when the class is loaded.
1631     * </p>
1632     *
1633     * @since 3.1
1634     */
1635    public static final boolean IS_OS_WINDOWS_2008 = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " Server 2008");
1636
1637    /**
1638     * Is {@code true} if this is Windows Server 2012.
1639     *
1640     * <p>
1641     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1642     * </p>
1643     * <p>
1644     * This value is initialized when the class is loaded.
1645     * </p>
1646     *
1647     * @since 3.4
1648     */
1649    public static final boolean IS_OS_WINDOWS_2012 = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " Server 2012");
1650
1651    /**
1652     * Is {@code true} if this is Windows 95.
1653     *
1654     * <p>
1655     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1656     * </p>
1657     * <p>
1658     * This value is initialized when the class is loaded.
1659     * </p>
1660     *
1661     * @since 2.0
1662     */
1663    public static final boolean IS_OS_WINDOWS_95 = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " 95");
1664
1665    /**
1666     * Is {@code true} if this is Windows 98.
1667     *
1668     * <p>
1669     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1670     * </p>
1671     * <p>
1672     * This value is initialized when the class is loaded.
1673     * </p>
1674     *
1675     * @since 2.0
1676     */
1677    public static final boolean IS_OS_WINDOWS_98 = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " 98");
1678
1679    /**
1680     * Is {@code true} if this is Windows ME.
1681     *
1682     * <p>
1683     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1684     * </p>
1685     * <p>
1686     * This value is initialized when the class is loaded.
1687     * </p>
1688     *
1689     * @since 2.0
1690     */
1691    public static final boolean IS_OS_WINDOWS_ME = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " Me");
1692
1693    /**
1694     * Is {@code true} if this is Windows NT.
1695     *
1696     * <p>
1697     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1698     * </p>
1699     * <p>
1700     * This value is initialized when the class is loaded.
1701     * </p>
1702     *
1703     * @since 2.0
1704     */
1705    public static final boolean IS_OS_WINDOWS_NT = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " NT");
1706
1707    /**
1708     * Is {@code true} if this is Windows XP.
1709     *
1710     * <p>
1711     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1712     * </p>
1713     * <p>
1714     * This value is initialized when the class is loaded.
1715     * </p>
1716     *
1717     * @since 2.0
1718     */
1719    public static final boolean IS_OS_WINDOWS_XP = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " XP");
1720
1721    /**
1722     * Is {@code true} if this is Windows Vista.
1723     *
1724     * <p>
1725     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1726     * </p>
1727     * <p>
1728     * This value is initialized when the class is loaded.
1729     * </p>
1730     *
1731     * @since 2.4
1732     */
1733    public static final boolean IS_OS_WINDOWS_VISTA = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " Vista");
1734
1735    /**
1736     * Is {@code true} if this is Windows 7.
1737     *
1738     * <p>
1739     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1740     * </p>
1741     * <p>
1742     * This value is initialized when the class is loaded.
1743     * </p>
1744     *
1745     * @since 3.0
1746     */
1747    public static final boolean IS_OS_WINDOWS_7 = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " 7");
1748
1749    /**
1750     * Is {@code true} if this is Windows 8.
1751     *
1752     * <p>
1753     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1754     * </p>
1755     * <p>
1756     * This value is initialized when the class is loaded.
1757     * </p>
1758     *
1759     * @since 3.2
1760     */
1761    public static final boolean IS_OS_WINDOWS_8 = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " 8");
1762
1763    /**
1764     * Is {@code true} if this is Windows 10.
1765     *
1766     * <p>
1767     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1768     * </p>
1769     * <p>
1770     * This value is initialized when the class is loaded.
1771     * </p>
1772     *
1773     * @since 3.5
1774     */
1775    public static final boolean IS_OS_WINDOWS_10 = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " 10");
1776
1777    /**
1778     * Is {@code true} if this is Windows 11.
1779     *
1780     * <p>
1781     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1782     * </p>
1783     * <p>
1784     * OpenJDK fixed the return value for {@code os.name} on Windows 11 to versions 8, 11, and 17:
1785     * </p>
1786     * <ul>
1787     * <li>Affects Java versions 7u321, 8u311, 11.0.13-oracle, 17.0.1: https://bugs.openjdk.org/browse/JDK-8274737</li>
1788     * <li>Fixed in OpenJDK commit https://github.com/openjdk/jdk/commit/97ea9dd2f24f9f1fb9b9345a4202a825ee28e014</li>
1789     * </ul>
1790     * <p>
1791     * This value is initialized when the class is loaded.
1792     * </p>
1793     *
1794     * @since 3.13.0
1795     */
1796    public static final boolean IS_OS_WINDOWS_11 = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " 11");
1797
1798    /**
1799     * Is {@code true} if this is z/OS.
1800     *
1801     * <p>
1802     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1803     * </p>
1804     * <p>
1805     * This value is initialized when the class is loaded.
1806     * </p>
1807     *
1808     * @since 3.5
1809     */
1810    // Values on a z/OS system I tested (Gary Gregory - 2016-03-12)
1811    // os.arch = s390x
1812    // os.encoding = ISO8859_1
1813    // os.name = z/OS
1814    // os.version = 02.02.00
1815    public static final boolean IS_OS_ZOS = getOsMatchesName("z/OS");
1816
1817    /**
1818     * The System property key for the user home directory.
1819     */
1820    public static final String USER_HOME_KEY = "user.home";
1821
1822    /**
1823     * The System property key for the user name.
1824     *
1825     * @deprecated Use {@link SystemProperties#USER_NAME}.
1826     */
1827    @Deprecated
1828    public static final String USER_NAME_KEY = "user.name";
1829
1830    /**
1831     * The System property key for the user directory.
1832     *
1833     * @deprecated Use {@link SystemProperties#USER_DIR}.
1834     */
1835    @Deprecated
1836    public static final String USER_DIR_KEY = "user.dir";
1837
1838    /**
1839     * The System property key for the Java IO temporary directory.
1840     *
1841     * @deprecated Use {@link SystemProperties#JAVA_IO_TMPDIR}.
1842     */
1843    @Deprecated
1844    public static final String JAVA_IO_TMPDIR_KEY = "java.io.tmpdir";
1845
1846    /**
1847     * The System property key for the Java home directory.
1848     *
1849     * @deprecated Use {@link SystemProperties#JAVA_HOME}.
1850     */
1851    @Deprecated
1852    public static final String JAVA_HOME_KEY = "java.home";
1853
1854    /**
1855     * The {@code awt.toolkit} System Property.
1856     *
1857     * <p>
1858     * Holds a class name, on Windows XP this is {@code sun.awt.windows.WToolkit}.
1859     * </p>
1860     * <p>
1861     * <b>On platforms without a GUI, this value is {@code null}.</b>
1862     * </p>
1863     * <p>
1864     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
1865     * not exist.
1866     * </p>
1867     * <p>
1868     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
1869     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
1870     * sync with that System property.
1871     * </p>
1872     *
1873     * @since 2.1
1874     * @see SystemProperties#getAwtToolkit()
1875     */
1876    public static final String AWT_TOOLKIT = SystemProperties.getAwtToolkit();
1877
1878    /**
1879     * Gets an environment variable, defaulting to {@code defaultValue} if the variable cannot be read.
1880     *
1881     * <p>
1882     * If a {@link SecurityException} is caught, the return value is {@code defaultValue} and a message is written to
1883     * {@code System.err}.
1884     * </p>
1885     *
1886     * @param name
1887     *            the environment variable name
1888     * @param defaultValue
1889     *            the default value
1890     * @return the environment variable value or {@code defaultValue} if a security problem occurs
1891     * @since 3.8
1892     */
1893    public static String getEnvironmentVariable(final String name, final String defaultValue) {
1894        try {
1895            final String value = System.getenv(name);
1896            return value == null ? defaultValue : value;
1897        } catch (final SecurityException ex) {
1898            // we are not allowed to look at this property
1899            // System.err.println("Caught a SecurityException reading the environment variable '" + name + "'.");
1900            return defaultValue;
1901        }
1902    }
1903
1904    /**
1905     * Gets the host name from an environment variable
1906     * (COMPUTERNAME on Windows, HOSTNAME elsewhere).
1907     *
1908     * <p>
1909     * If you want to know what the network stack says is the host name, you should use {@code InetAddress.getLocalHost().getHostName()}.
1910     * </p>
1911     *
1912     * @return the host name. Will be {@code null} if the environment variable is not defined.
1913     * @since 3.6
1914     */
1915    public static String getHostName() {
1916        return IS_OS_WINDOWS ? System.getenv("COMPUTERNAME") : System.getenv("HOSTNAME");
1917    }
1918
1919    /**
1920     * Gets the current Java home directory as a {@link File}.
1921     *
1922     * @return a directory
1923     * @throws SecurityException if a security manager exists and its {@code checkPropertyAccess} method doesn't allow
1924     * access to the specified system property.
1925     * @see SystemProperties#getJavaHome()
1926     * @since 2.1
1927     */
1928    public static File getJavaHome() {
1929        return new File(SystemProperties.getJavaHome());
1930    }
1931
1932    /**
1933     * Gets the current Java IO temporary directory as a {@link File}.
1934     *
1935     * @return a directory
1936     * @throws SecurityException if a security manager exists and its {@code checkPropertyAccess} method doesn't allow
1937     * access to the specified system property.
1938     * @see SystemProperties#getJavaIoTmpdir()
1939     * @since 2.1
1940     */
1941    public static File getJavaIoTmpDir() {
1942        return new File(SystemProperties.getJavaIoTmpdir());
1943    }
1944
1945    /**
1946     * Decides if the Java version matches.
1947     *
1948     * @param versionPrefix the prefix for the java version
1949     * @return true if matches, or false if not or can't determine
1950     */
1951    private static boolean getJavaVersionMatches(final String versionPrefix) {
1952        return isJavaVersionMatch(JAVA_SPECIFICATION_VERSION, versionPrefix);
1953    }
1954
1955    /**
1956     * Decides if the operating system matches.
1957     *
1958     * @param osNamePrefix the prefix for the OS name
1959     * @param osVersionPrefix the prefix for the version
1960     * @return true if matches, or false if not or can't determine
1961     */
1962    private static boolean getOsMatches(final String osNamePrefix, final String osVersionPrefix) {
1963        return isOSMatch(OS_NAME, OS_VERSION, osNamePrefix, osVersionPrefix);
1964    }
1965
1966    /**
1967     * Decides if the operating system matches.
1968     *
1969     * @param osNamePrefix the prefix for the OS name
1970     * @return true if matches, or false if not or can't determine
1971     */
1972    private static boolean getOsMatchesName(final String osNamePrefix) {
1973        return isOSNameMatch(OS_NAME, osNamePrefix);
1974    }
1975
1976    /**
1977     * Gets the current user directory as a {@link File}.
1978     *
1979     * @return a directory
1980     * @throws SecurityException if a security manager exists and its {@code checkPropertyAccess} method doesn't allow
1981     * access to the specified system property.
1982     * @see SystemProperties#getUserDir()
1983     * @since 2.1
1984     */
1985    public static File getUserDir() {
1986        return new File(SystemProperties.getUserDir());
1987    }
1988
1989    /**
1990     * Gets the current user home directory as a {@link File}.
1991     *
1992     * @return a directory
1993     * @throws SecurityException if a security manager exists and its {@code checkPropertyAccess} method doesn't allow
1994     * access to the specified system property.
1995     * @see SystemProperties#getUserHome()
1996     * @since 2.1
1997     */
1998    public static File getUserHome() {
1999        return new File(SystemProperties.getUserHome());
2000    }
2001
2002    /**
2003     * Gets the current user name.
2004     *
2005     * @return a name
2006     * @throws SecurityException if a security manager exists and its {@code checkPropertyAccess} method doesn't allow
2007     * access to the specified system property.
2008     * @see SystemProperties#getUserName()
2009     * @since 3.10
2010     * @deprecated Use {@link SystemProperties#getUserName()}.
2011     */
2012    @Deprecated
2013    public static String getUserName() {
2014        return SystemProperties.getUserName();
2015    }
2016
2017    /**
2018     * Gets the user name.
2019     *
2020     * @param defaultValue A default value.
2021     * @return a name
2022     * @throws SecurityException if a security manager exists and its {@code checkPropertyAccess} method doesn't allow
2023     * access to the specified system property.
2024     * @see SystemProperties#getUserName()
2025     * @since 3.10
2026     */
2027    public static String getUserName(final String defaultValue) {
2028        return System.getProperty(SystemProperties.USER_NAME, defaultValue);
2029    }
2030
2031    /**
2032     * Returns whether the {@link #JAVA_AWT_HEADLESS} value is {@code true}.
2033     *
2034     * @return {@code true} if {@code JAVA_AWT_HEADLESS} is {@code "true"}, {@code false} otherwise.
2035     * @see #JAVA_AWT_HEADLESS
2036     * @since 2.1
2037     * @since Java 1.4
2038     */
2039    public static boolean isJavaAwtHeadless() {
2040        return Boolean.TRUE.toString().equals(JAVA_AWT_HEADLESS);
2041    }
2042
2043    /**
2044     * Is the Java version at least the requested version.
2045     *
2046     * @param requiredVersion the required version, for example 1.31f
2047     * @return {@code true} if the actual version is equal or greater than the required version
2048     */
2049    public static boolean isJavaVersionAtLeast(final JavaVersion requiredVersion) {
2050        return JAVA_SPECIFICATION_VERSION_AS_ENUM.atLeast(requiredVersion);
2051    }
2052
2053    /**
2054     * Is the Java version at most the requested version.
2055     *
2056     * <p>
2057     * Example input:
2058     * </p>
2059     *
2060     * @param requiredVersion the required version, for example 1.31f
2061     * @return {@code true} if the actual version is equal or less than the required version
2062     * @since 3.9
2063     */
2064    public static boolean isJavaVersionAtMost(final JavaVersion requiredVersion) {
2065        return JAVA_SPECIFICATION_VERSION_AS_ENUM.atMost(requiredVersion);
2066    }
2067
2068    /**
2069     * Decides if the Java version matches.
2070     *
2071     * <p>
2072     * This method is package private instead of private to support unit test invocation.
2073     * </p>
2074     *
2075     * @param version the actual Java version
2076     * @param versionPrefix the prefix for the expected Java version
2077     * @return true if matches, or false if not or can't determine
2078     */
2079    static boolean isJavaVersionMatch(final String version, final String versionPrefix) {
2080        if (version == null) {
2081            return false;
2082        }
2083        return version.startsWith(versionPrefix);
2084    }
2085
2086    /**
2087     * Decides if the operating system matches.
2088     * <p>
2089     * This method is package private instead of private to support unit test invocation.
2090     * </p>
2091     *
2092     * @param osName the actual OS name
2093     * @param osVersion the actual OS version
2094     * @param osNamePrefix the prefix for the expected OS name
2095     * @param osVersionPrefix the prefix for the expected OS version
2096     * @return true if matches, or false if not or can't determine
2097     */
2098    static boolean isOSMatch(final String osName, final String osVersion, final String osNamePrefix, final String osVersionPrefix) {
2099        if (osName == null || osVersion == null) {
2100            return false;
2101        }
2102        return isOSNameMatch(osName, osNamePrefix) && isOSVersionMatch(osVersion, osVersionPrefix);
2103    }
2104
2105    /**
2106     * Decides if the operating system matches.
2107     * <p>
2108     * This method is package private instead of private to support unit test invocation.
2109     * </p>
2110     *
2111     * @param osName the actual OS name
2112     * @param osNamePrefix the prefix for the expected OS name
2113     * @return true if matches, or false if not or can't determine
2114     */
2115    static boolean isOSNameMatch(final String osName, final String osNamePrefix) {
2116        if (osName == null) {
2117            return false;
2118        }
2119        return osName.startsWith(osNamePrefix);
2120    }
2121
2122    /**
2123     * Decides if the operating system version matches.
2124     * <p>
2125     * This method is package private instead of private to support unit test invocation.
2126     * </p>
2127     *
2128     * @param osVersion the actual OS version
2129     * @param osVersionPrefix the prefix for the expected OS version
2130     * @return true if matches, or false if not or can't determine
2131     */
2132    static boolean isOSVersionMatch(final String osVersion, final String osVersionPrefix) {
2133        if (StringUtils.isEmpty(osVersion)) {
2134            return false;
2135        }
2136        // Compare parts of the version string instead of using String.startsWith(String) because otherwise
2137        // osVersionPrefix 10.1 would also match osVersion 10.10
2138        final String[] versionPrefixParts = osVersionPrefix.split("\\.");
2139        final String[] versionParts = osVersion.split("\\.");
2140        for (int i = 0; i < Math.min(versionPrefixParts.length, versionParts.length); i++) {
2141            if (!versionPrefixParts[i].equals(versionParts[i])) {
2142                return false;
2143            }
2144        }
2145        return true;
2146    }
2147
2148    /**
2149     * SystemUtils instances should NOT be constructed in standard programming. Instead, the class should be used as
2150     * {@code SystemUtils.FILE_SEPARATOR}.
2151     *
2152     * <p>
2153     * This constructor is public to permit tools that require a JavaBean instance to operate.
2154     * </p>
2155     */
2156    public SystemUtils() {
2157    }
2158
2159}