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 {@link 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    /**
1114     * Is {@code true} if this is Java version 22 (also 22.x versions).
1115     * <p>
1116     * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
1117     * </p>
1118     * <p>
1119     * This value is initialized when the class is loaded.
1120     * </p>
1121     *
1122     * @since 3.15.0
1123     */
1124    public static final boolean IS_JAVA_22 = getJavaVersionMatches("22");
1125
1126    // Operating system checks
1127    // -----------------------------------------------------------------------
1128    // These MUST be declared after those above as they depend on the
1129    // values being set up
1130    // Please advise dev@commons.apache.org if you want another added
1131    // or a mistake corrected
1132
1133    /**
1134     * Is {@code true} if this is AIX.
1135     *
1136     * <p>
1137     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1138     * </p>
1139     * <p>
1140     * This value is initialized when the class is loaded.
1141     * </p>
1142     *
1143     * @since 2.0
1144     */
1145    public static final boolean IS_OS_AIX = getOsMatchesName("AIX");
1146
1147    /**
1148     * Is {@code true} if this is Android.
1149     *
1150     * <p>
1151     * See https://developer.android.com/reference/java/lang/System#getProperties().
1152     * </p>
1153     * <p>
1154     * This value is initialized when the class is loaded.
1155     * </p>
1156     *
1157     * @since 3.15.0
1158     */
1159    public static final boolean IS_OS_ANDROID = SystemProperties.getJavaVendor().contains("Android");
1160
1161    /**
1162     * Is {@code true} if this is HP-UX.
1163     *
1164     * <p>
1165     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1166     * </p>
1167     * <p>
1168     * This value is initialized when the class is loaded.
1169     * </p>
1170     *
1171     * @since 2.0
1172     */
1173    public static final boolean IS_OS_HP_UX = getOsMatchesName("HP-UX");
1174
1175    /**
1176     * Is {@code true} if this is IBM OS/400.
1177     *
1178     * <p>
1179     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1180     * </p>
1181     * <p>
1182     * This value is initialized when the class is loaded.
1183     * </p>
1184     *
1185     * @since 3.3
1186     */
1187    public static final boolean IS_OS_400 = getOsMatchesName("OS/400");
1188
1189    /**
1190     * Is {@code true} if this is Irix.
1191     *
1192     * <p>
1193     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1194     * </p>
1195     * <p>
1196     * This value is initialized when the class is loaded.
1197     * </p>
1198     *
1199     * @since 2.0
1200     */
1201    public static final boolean IS_OS_IRIX = getOsMatchesName("Irix");
1202
1203    /**
1204     * Is {@code true} if this is Linux.
1205     *
1206     * <p>
1207     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1208     * </p>
1209     * <p>
1210     * This value is initialized when the class is loaded.
1211     * </p>
1212     *
1213     * @since 2.0
1214     */
1215    public static final boolean IS_OS_LINUX = getOsMatchesName("Linux") || getOsMatchesName("LINUX");
1216
1217    /**
1218     * Is {@code true} if this is Mac.
1219     *
1220     * <p>
1221     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1222     * </p>
1223     * <p>
1224     * This value is initialized when the class is loaded.
1225     * </p>
1226     *
1227     * @since 2.0
1228     */
1229    public static final boolean IS_OS_MAC = getOsMatchesName("Mac");
1230
1231    /**
1232     * Is {@code true} if this is Mac.
1233     *
1234     * <p>
1235     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1236     * </p>
1237     * <p>
1238     * This value is initialized when the class is loaded.
1239     * </p>
1240     *
1241     * @since 2.0
1242     */
1243    public static final boolean IS_OS_MAC_OSX = getOsMatchesName("Mac OS X");
1244
1245    /**
1246     * Is {@code true} if this is macOS X Cheetah.
1247     *
1248     * <p>
1249     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1250     * </p>
1251     * <p>
1252     * This value is initialized when the class is loaded.
1253     * </p>
1254     *
1255     * @since 3.4
1256     */
1257    public static final boolean IS_OS_MAC_OSX_CHEETAH = getOsMatches("Mac OS X", "10.0");
1258
1259    /**
1260     * Is {@code true} if this is macOS X Puma.
1261     *
1262     * <p>
1263     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1264     * </p>
1265     * <p>
1266     * This value is initialized when the class is loaded.
1267     * </p>
1268     *
1269     * @since 3.4
1270     */
1271    public static final boolean IS_OS_MAC_OSX_PUMA = getOsMatches("Mac OS X", "10.1");
1272
1273    /**
1274     * Is {@code true} if this is macOS X Jaguar.
1275     *
1276     * <p>
1277     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1278     * </p>
1279     * <p>
1280     * This value is initialized when the class is loaded.
1281     * </p>
1282     *
1283     * @since 3.4
1284     */
1285    public static final boolean IS_OS_MAC_OSX_JAGUAR = getOsMatches("Mac OS X", "10.2");
1286
1287    /**
1288     * Is {@code true} if this is macOS X Panther.
1289     *
1290     * <p>
1291     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1292     * </p>
1293     * <p>
1294     * This value is initialized when the class is loaded.
1295     * </p>
1296     *
1297     * @since 3.4
1298     */
1299    public static final boolean IS_OS_MAC_OSX_PANTHER = getOsMatches("Mac OS X", "10.3");
1300
1301    /**
1302     * Is {@code true} if this is macOS X Tiger.
1303     *
1304     * <p>
1305     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1306     * </p>
1307     * <p>
1308     * This value is initialized when the class is loaded.
1309     * </p>
1310     *
1311     * @since 3.4
1312     */
1313    public static final boolean IS_OS_MAC_OSX_TIGER = getOsMatches("Mac OS X", "10.4");
1314
1315    /**
1316     * Is {@code true} if this is macOS X Leopard.
1317     *
1318     * <p>
1319     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1320     * </p>
1321     * <p>
1322     * This value is initialized when the class is loaded.
1323     * </p>
1324     *
1325     * @since 3.4
1326     */
1327    public static final boolean IS_OS_MAC_OSX_LEOPARD = getOsMatches("Mac OS X", "10.5");
1328
1329    /**
1330     * Is {@code true} if this is macOS X Snow Leopard.
1331     *
1332     * <p>
1333     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1334     * </p>
1335     * <p>
1336     * This value is initialized when the class is loaded.
1337     * </p>
1338     *
1339     * @since 3.4
1340     */
1341    public static final boolean IS_OS_MAC_OSX_SNOW_LEOPARD = getOsMatches("Mac OS X", "10.6");
1342
1343    /**
1344     * Is {@code true} if this is macOS X Lion.
1345     *
1346     * <p>
1347     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1348     * </p>
1349     * <p>
1350     * This value is initialized when the class is loaded.
1351     * </p>
1352     *
1353     * @since 3.4
1354     */
1355    public static final boolean IS_OS_MAC_OSX_LION = getOsMatches("Mac OS X", "10.7");
1356
1357    /**
1358     * Is {@code true} if this is macOS X Mountain Lion.
1359     *
1360     * <p>
1361     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1362     * </p>
1363     * <p>
1364     * This value is initialized when the class is loaded.
1365     * </p>
1366     *
1367     * @since 3.4
1368     */
1369    public static final boolean IS_OS_MAC_OSX_MOUNTAIN_LION = getOsMatches("Mac OS X", "10.8");
1370
1371    /**
1372     * Is {@code true} if this is macOS X Mavericks.
1373     *
1374     * <p>
1375     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1376     * </p>
1377     * <p>
1378     * This value is initialized when the class is loaded.
1379     * </p>
1380     *
1381     * @since 3.4
1382     */
1383    public static final boolean IS_OS_MAC_OSX_MAVERICKS = getOsMatches("Mac OS X", "10.9");
1384
1385    /**
1386     * Is {@code true} if this is macOS X Yosemite.
1387     *
1388     * <p>
1389     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1390     * </p>
1391     * <p>
1392     * This value is initialized when the class is loaded.
1393     * </p>
1394     *
1395     * @since 3.4
1396     */
1397    public static final boolean IS_OS_MAC_OSX_YOSEMITE = getOsMatches("Mac OS X", "10.10");
1398
1399    /**
1400     * Is {@code true} if this is macOS X El Capitan.
1401     *
1402     * <p>
1403     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1404     * </p>
1405     * <p>
1406     * This value is initialized when the class is loaded.
1407     * </p>
1408     *
1409     * @since 3.5
1410     */
1411    public static final boolean IS_OS_MAC_OSX_EL_CAPITAN = getOsMatches("Mac OS X", "10.11");
1412
1413    /**
1414     * Is {@code true} if this is macOS X Sierra.
1415     *
1416     * <p>
1417     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1418     * </p>
1419     * <p>
1420     * This value is initialized when the class is loaded.
1421     * </p>
1422     *
1423     * @since 3.12.0
1424     */
1425    public static final boolean IS_OS_MAC_OSX_SIERRA = getOsMatches("Mac OS X", "10.12");
1426
1427    /**
1428     * Is {@code true} if this is macOS X High Sierra.
1429     *
1430     * <p>
1431     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1432     * </p>
1433     * <p>
1434     * This value is initialized when the class is loaded.
1435     * </p>
1436     *
1437     * @since 3.12.0
1438     */
1439    public static final boolean IS_OS_MAC_OSX_HIGH_SIERRA = getOsMatches("Mac OS X", "10.13");
1440
1441    /**
1442     * Is {@code true} if this is macOS X Mojave.
1443     *
1444     * <p>
1445     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1446     * </p>
1447     * <p>
1448     * This value is initialized when the class is loaded.
1449     * </p>
1450     *
1451     * @since 3.12.0
1452     */
1453    public static final boolean IS_OS_MAC_OSX_MOJAVE = getOsMatches("Mac OS X", "10.14");
1454
1455    /**
1456     * Is {@code true} if this is macOS X Catalina.
1457     *
1458     * <p>
1459     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1460     * </p>
1461     * <p>
1462     * This value is initialized when the class is loaded.
1463     * </p>
1464     *
1465     * @since 3.12.0
1466     */
1467    public static final boolean IS_OS_MAC_OSX_CATALINA = getOsMatches("Mac OS X", "10.15");
1468
1469    /**
1470     * Is {@code true} if this is macOS X Big Sur.
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     *
1479     * @since 3.12.0
1480     */
1481    public static final boolean IS_OS_MAC_OSX_BIG_SUR = getOsMatches("Mac OS X", "11");
1482
1483    /**
1484     * Is {@code true} if this is macOS X Monterey.
1485     *
1486     * <p>
1487     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1488     * </p>
1489     * <p>
1490     * This value is initialized when the class is loaded.
1491     * </p>
1492     * @since 3.13.0
1493     */
1494    public static final boolean IS_OS_MAC_OSX_MONTEREY = getOsMatches("Mac OS X", "12");
1495
1496    /**
1497     * Is {@code true} if this is macOS X Ventura.
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     * @since 3.13.0
1506     */
1507    public static final boolean IS_OS_MAC_OSX_VENTURA = getOsMatches("Mac OS X", "13");
1508
1509    /**
1510     * Is {@code true} if this is macOS X Sonoma.
1511     *
1512     * <p>
1513     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1514     * </p>
1515     * <p>
1516     * This value is initialized when the class is loaded.
1517     * </p>
1518     * @since 3.15.0
1519     */
1520    public static final boolean IS_OS_MAC_OSX_SONOMA = getOsMatches("Mac OS X", "14");
1521
1522    /**
1523     * Is {@code true} if this is FreeBSD.
1524     *
1525     * <p>
1526     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1527     * </p>
1528     * <p>
1529     * This value is initialized when the class is loaded.
1530     * </p>
1531     *
1532     * @since 3.1
1533     */
1534    public static final boolean IS_OS_FREE_BSD = getOsMatchesName("FreeBSD");
1535
1536    /**
1537     * Is {@code true} if this is OpenBSD.
1538     *
1539     * <p>
1540     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1541     * </p>
1542     * <p>
1543     * This value is initialized when the class is loaded.
1544     * </p>
1545     *
1546     * @since 3.1
1547     */
1548    public static final boolean IS_OS_OPEN_BSD = getOsMatchesName("OpenBSD");
1549
1550    /**
1551     * Is {@code true} if this is NetBSD.
1552     *
1553     * <p>
1554     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1555     * </p>
1556     * <p>
1557     * This value is initialized when the class is loaded.
1558     * </p>
1559     *
1560     * @since 3.1
1561     */
1562    public static final boolean IS_OS_NET_BSD = getOsMatchesName("NetBSD");
1563
1564    /**
1565     * Is {@code true} if this is OS/2.
1566     *
1567     * <p>
1568     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1569     * </p>
1570     * <p>
1571     * This value is initialized when the class is loaded.
1572     * </p>
1573     *
1574     * @since 2.0
1575     */
1576    public static final boolean IS_OS_OS2 = getOsMatchesName("OS/2");
1577
1578    /**
1579     * Is {@code true} if this is Solaris.
1580     *
1581     * <p>
1582     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1583     * </p>
1584     * <p>
1585     * This value is initialized when the class is loaded.
1586     * </p>
1587     *
1588     * @since 2.0
1589     */
1590    public static final boolean IS_OS_SOLARIS = getOsMatchesName("Solaris");
1591
1592    /**
1593     * Is {@code true} if this is SunOS.
1594     *
1595     * <p>
1596     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1597     * </p>
1598     * <p>
1599     * This value is initialized when the class is loaded.
1600     * </p>
1601     *
1602     * @since 2.0
1603     */
1604    public static final boolean IS_OS_SUN_OS = getOsMatchesName("SunOS");
1605
1606    /**
1607     * Is {@code true} if this is a UNIX like system, as in any of AIX, HP-UX, Irix, Linux, MacOSX, Solaris or SUN OS.
1608     *
1609     * <p>
1610     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1611     * </p>
1612     * <p>
1613     * This value is initialized when the class is loaded.
1614     * </p>
1615     *
1616     * @since 2.1
1617     */
1618    public static final boolean IS_OS_UNIX = IS_OS_AIX || IS_OS_HP_UX || IS_OS_IRIX || IS_OS_LINUX || IS_OS_MAC_OSX
1619            || IS_OS_SOLARIS || IS_OS_SUN_OS || IS_OS_FREE_BSD || IS_OS_OPEN_BSD || IS_OS_NET_BSD;
1620
1621    /**
1622     * Is {@code true} if this is Windows.
1623     *
1624     * <p>
1625     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1626     * </p>
1627     * <p>
1628     * This value is initialized when the class is loaded.
1629     * </p>
1630     *
1631     * @since 2.0
1632     */
1633    public static final boolean IS_OS_WINDOWS = getOsMatchesName(OS_NAME_WINDOWS_PREFIX);
1634
1635    /**
1636     * Is {@code true} if this is Windows 2000.
1637     *
1638     * <p>
1639     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1640     * </p>
1641     * <p>
1642     * This value is initialized when the class is loaded.
1643     * </p>
1644     *
1645     * @since 2.0
1646     */
1647    public static final boolean IS_OS_WINDOWS_2000 = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " 2000");
1648
1649    /**
1650     * Is {@code true} if this is Windows 2003.
1651     *
1652     * <p>
1653     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1654     * </p>
1655     * <p>
1656     * This value is initialized when the class is loaded.
1657     * </p>
1658     *
1659     * @since 3.1
1660     */
1661    public static final boolean IS_OS_WINDOWS_2003 = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " 2003");
1662
1663    /**
1664     * Is {@code true} if this is Windows Server 2008.
1665     *
1666     * <p>
1667     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1668     * </p>
1669     * <p>
1670     * This value is initialized when the class is loaded.
1671     * </p>
1672     *
1673     * @since 3.1
1674     */
1675    public static final boolean IS_OS_WINDOWS_2008 = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " Server 2008");
1676
1677    /**
1678     * Is {@code true} if this is Windows Server 2012.
1679     *
1680     * <p>
1681     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1682     * </p>
1683     * <p>
1684     * This value is initialized when the class is loaded.
1685     * </p>
1686     *
1687     * @since 3.4
1688     */
1689    public static final boolean IS_OS_WINDOWS_2012 = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " Server 2012");
1690
1691    /**
1692     * Is {@code true} if this is Windows 95.
1693     *
1694     * <p>
1695     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1696     * </p>
1697     * <p>
1698     * This value is initialized when the class is loaded.
1699     * </p>
1700     *
1701     * @since 2.0
1702     */
1703    public static final boolean IS_OS_WINDOWS_95 = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " 95");
1704
1705    /**
1706     * Is {@code true} if this is Windows 98.
1707     *
1708     * <p>
1709     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1710     * </p>
1711     * <p>
1712     * This value is initialized when the class is loaded.
1713     * </p>
1714     *
1715     * @since 2.0
1716     */
1717    public static final boolean IS_OS_WINDOWS_98 = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " 98");
1718
1719    /**
1720     * Is {@code true} if this is Windows ME.
1721     *
1722     * <p>
1723     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1724     * </p>
1725     * <p>
1726     * This value is initialized when the class is loaded.
1727     * </p>
1728     *
1729     * @since 2.0
1730     */
1731    public static final boolean IS_OS_WINDOWS_ME = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " Me");
1732
1733    /**
1734     * Is {@code true} if this is Windows NT.
1735     *
1736     * <p>
1737     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1738     * </p>
1739     * <p>
1740     * This value is initialized when the class is loaded.
1741     * </p>
1742     *
1743     * @since 2.0
1744     */
1745    public static final boolean IS_OS_WINDOWS_NT = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " NT");
1746
1747    /**
1748     * Is {@code true} if this is Windows XP.
1749     *
1750     * <p>
1751     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1752     * </p>
1753     * <p>
1754     * This value is initialized when the class is loaded.
1755     * </p>
1756     *
1757     * @since 2.0
1758     */
1759    public static final boolean IS_OS_WINDOWS_XP = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " XP");
1760
1761    /**
1762     * Is {@code true} if this is Windows Vista.
1763     *
1764     * <p>
1765     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1766     * </p>
1767     * <p>
1768     * This value is initialized when the class is loaded.
1769     * </p>
1770     *
1771     * @since 2.4
1772     */
1773    public static final boolean IS_OS_WINDOWS_VISTA = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " Vista");
1774
1775    /**
1776     * Is {@code true} if this is Windows 7.
1777     *
1778     * <p>
1779     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1780     * </p>
1781     * <p>
1782     * This value is initialized when the class is loaded.
1783     * </p>
1784     *
1785     * @since 3.0
1786     */
1787    public static final boolean IS_OS_WINDOWS_7 = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " 7");
1788
1789    /**
1790     * Is {@code true} if this is Windows 8.
1791     *
1792     * <p>
1793     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1794     * </p>
1795     * <p>
1796     * This value is initialized when the class is loaded.
1797     * </p>
1798     *
1799     * @since 3.2
1800     */
1801    public static final boolean IS_OS_WINDOWS_8 = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " 8");
1802
1803    /**
1804     * Is {@code true} if this is Windows 10.
1805     *
1806     * <p>
1807     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1808     * </p>
1809     * <p>
1810     * This value is initialized when the class is loaded.
1811     * </p>
1812     *
1813     * @since 3.5
1814     */
1815    public static final boolean IS_OS_WINDOWS_10 = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " 10");
1816
1817    /**
1818     * Is {@code true} if this is Windows 11.
1819     *
1820     * <p>
1821     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1822     * </p>
1823     * <p>
1824     * OpenJDK fixed the return value for {@code os.name} on Windows 11 to versions 8, 11, and 17:
1825     * </p>
1826     * <ul>
1827     * <li>Affects Java versions 7u321, 8u311, 11.0.13-oracle, 17.0.1: https://bugs.openjdk.org/browse/JDK-8274737</li>
1828     * <li>Fixed in OpenJDK commit https://github.com/openjdk/jdk/commit/97ea9dd2f24f9f1fb9b9345a4202a825ee28e014</li>
1829     * </ul>
1830     * <p>
1831     * This value is initialized when the class is loaded.
1832     * </p>
1833     *
1834     * @since 3.13.0
1835     */
1836    public static final boolean IS_OS_WINDOWS_11 = getOsMatchesName(OS_NAME_WINDOWS_PREFIX + " 11");
1837
1838    /**
1839     * Is {@code true} if this is z/OS.
1840     *
1841     * <p>
1842     * The field will return {@code false} if {@code OS_NAME} is {@code null}.
1843     * </p>
1844     * <p>
1845     * This value is initialized when the class is loaded.
1846     * </p>
1847     *
1848     * @since 3.5
1849     */
1850    // Values on a z/OS system I tested (Gary Gregory - 2016-03-12)
1851    // os.arch = s390x
1852    // os.encoding = ISO8859_1
1853    // os.name = z/OS
1854    // os.version = 02.02.00
1855    public static final boolean IS_OS_ZOS = getOsMatchesName("z/OS");
1856
1857    /**
1858     * The System property key for the user home directory.
1859     */
1860    public static final String USER_HOME_KEY = "user.home";
1861
1862    /**
1863     * The System property key for the user name.
1864     *
1865     * @deprecated Use {@link SystemProperties#USER_NAME}.
1866     */
1867    @Deprecated
1868    public static final String USER_NAME_KEY = "user.name";
1869
1870    /**
1871     * The System property key for the user directory.
1872     *
1873     * @deprecated Use {@link SystemProperties#USER_DIR}.
1874     */
1875    @Deprecated
1876    public static final String USER_DIR_KEY = "user.dir";
1877
1878    /**
1879     * The System property key for the Java IO temporary directory.
1880     *
1881     * @deprecated Use {@link SystemProperties#JAVA_IO_TMPDIR}.
1882     */
1883    @Deprecated
1884    public static final String JAVA_IO_TMPDIR_KEY = "java.io.tmpdir";
1885
1886    /**
1887     * The System property key for the Java home directory.
1888     *
1889     * @deprecated Use {@link SystemProperties#JAVA_HOME}.
1890     */
1891    @Deprecated
1892    public static final String JAVA_HOME_KEY = "java.home";
1893
1894    /**
1895     * The {@code awt.toolkit} System Property.
1896     *
1897     * <p>
1898     * Holds a class name, on Windows XP this is {@code sun.awt.windows.WToolkit}.
1899     * </p>
1900     * <p>
1901     * <b>On platforms without a GUI, this value is {@code null}.</b>
1902     * </p>
1903     * <p>
1904     * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
1905     * not exist.
1906     * </p>
1907     * <p>
1908     * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
1909     * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
1910     * sync with that System property.
1911     * </p>
1912     *
1913     * @since 2.1
1914     * @see SystemProperties#getAwtToolkit()
1915     */
1916    public static final String AWT_TOOLKIT = SystemProperties.getAwtToolkit();
1917
1918    /**
1919     * Gets an environment variable, defaulting to {@code defaultValue} if the variable cannot be read.
1920     *
1921     * <p>
1922     * If a {@link SecurityException} is caught, the return value is {@code defaultValue} and a message is written to
1923     * {@code System.err}.
1924     * </p>
1925     *
1926     * @param name
1927     *            the environment variable name
1928     * @param defaultValue
1929     *            the default value
1930     * @return the environment variable value or {@code defaultValue} if a security problem occurs
1931     * @since 3.8
1932     */
1933    public static String getEnvironmentVariable(final String name, final String defaultValue) {
1934        try {
1935            final String value = System.getenv(name);
1936            return value == null ? defaultValue : value;
1937        } catch (final SecurityException ex) {
1938            // we are not allowed to look at this property
1939            // System.err.println("Caught a SecurityException reading the environment variable '" + name + "'.");
1940            return defaultValue;
1941        }
1942    }
1943
1944    /**
1945     * Gets the host name from an environment variable
1946     * (COMPUTERNAME on Windows, HOSTNAME elsewhere).
1947     *
1948     * <p>
1949     * If you want to know what the network stack says is the host name, you should use {@code InetAddress.getLocalHost().getHostName()}.
1950     * </p>
1951     *
1952     * @return the host name. Will be {@code null} if the environment variable is not defined.
1953     * @since 3.6
1954     */
1955    public static String getHostName() {
1956        return IS_OS_WINDOWS ? System.getenv("COMPUTERNAME") : System.getenv("HOSTNAME");
1957    }
1958
1959    /**
1960     * Gets the current Java home directory as a {@link File}.
1961     *
1962     * @return a directory
1963     * @throws SecurityException if a security manager exists and its {@code checkPropertyAccess} method doesn't allow
1964     * access to the specified system property.
1965     * @see SystemProperties#getJavaHome()
1966     * @since 2.1
1967     */
1968    public static File getJavaHome() {
1969        return new File(SystemProperties.getJavaHome());
1970    }
1971
1972    /**
1973     * Gets the current Java IO temporary directory as a {@link File}.
1974     *
1975     * @return a directory
1976     * @throws SecurityException if a security manager exists and its {@code checkPropertyAccess} method doesn't allow
1977     * access to the specified system property.
1978     * @see SystemProperties#getJavaIoTmpdir()
1979     * @since 2.1
1980     */
1981    public static File getJavaIoTmpDir() {
1982        return new File(SystemProperties.getJavaIoTmpdir());
1983    }
1984
1985    /**
1986     * Decides if the Java version matches.
1987     *
1988     * @param versionPrefix the prefix for the Java version
1989     * @return true if matches, or false if not or can't determine
1990     */
1991    private static boolean getJavaVersionMatches(final String versionPrefix) {
1992        return isJavaVersionMatch(JAVA_SPECIFICATION_VERSION, versionPrefix);
1993    }
1994
1995    /**
1996     * Decides if the operating system matches.
1997     *
1998     * @param osNamePrefix the prefix for the OS name
1999     * @param osVersionPrefix the prefix for the version
2000     * @return true if matches, or false if not or can't determine
2001     */
2002    private static boolean getOsMatches(final String osNamePrefix, final String osVersionPrefix) {
2003        return isOsMatch(OS_NAME, OS_VERSION, osNamePrefix, osVersionPrefix);
2004    }
2005
2006    /**
2007     * Decides if the operating system matches.
2008     *
2009     * @param osNamePrefix the prefix for the OS name
2010     * @return true if matches, or false if not or can't determine
2011     */
2012    private static boolean getOsMatchesName(final String osNamePrefix) {
2013        return isOsNameMatch(OS_NAME, osNamePrefix);
2014    }
2015
2016    /**
2017     * Gets the current user directory as a {@link File}.
2018     *
2019     * @return a directory
2020     * @throws SecurityException if a security manager exists and its {@code checkPropertyAccess} method doesn't allow
2021     * access to the specified system property.
2022     * @see SystemProperties#getUserDir()
2023     * @since 2.1
2024     */
2025    public static File getUserDir() {
2026        return new File(SystemProperties.getUserDir());
2027    }
2028
2029    /**
2030     * Gets the current user home directory as a {@link File}.
2031     *
2032     * @return a directory
2033     * @throws SecurityException if a security manager exists and its {@code checkPropertyAccess} method doesn't allow
2034     * access to the specified system property.
2035     * @see SystemProperties#getUserHome()
2036     * @since 2.1
2037     */
2038    public static File getUserHome() {
2039        return new File(SystemProperties.getUserHome());
2040    }
2041
2042    /**
2043     * Gets the current user name.
2044     *
2045     * @return a name
2046     * @throws SecurityException if a security manager exists and its {@code checkPropertyAccess} method doesn't allow
2047     * access to the specified system property.
2048     * @see SystemProperties#getUserName()
2049     * @since 3.10
2050     * @deprecated Use {@link SystemProperties#getUserName()}.
2051     */
2052    @Deprecated
2053    public static String getUserName() {
2054        return SystemProperties.getUserName();
2055    }
2056
2057    /**
2058     * Gets the user name.
2059     *
2060     * @param defaultValue A default value.
2061     * @return a name
2062     * @throws SecurityException if a security manager exists and its {@code checkPropertyAccess} method doesn't allow
2063     * access to the specified system property.
2064     * @see SystemProperties#getUserName()
2065     * @since 3.10
2066     * @deprecated Use {@link SystemProperties#getUserName(String)}.
2067     */
2068    @Deprecated
2069    public static String getUserName(final String defaultValue) {
2070        return SystemProperties.getUserName(defaultValue);
2071    }
2072
2073    /**
2074     * Returns whether the {@link #JAVA_AWT_HEADLESS} value is {@code true}.
2075     *
2076     * @return {@code true} if {@code JAVA_AWT_HEADLESS} is {@code "true"}, {@code false} otherwise.
2077     * @see #JAVA_AWT_HEADLESS
2078     * @since 2.1
2079     * @since Java 1.4
2080     */
2081    public static boolean isJavaAwtHeadless() {
2082        return Boolean.TRUE.toString().equals(JAVA_AWT_HEADLESS);
2083    }
2084
2085    /**
2086     * Is the Java version at least the requested version.
2087     *
2088     * @param requiredVersion the required version, for example 1.31f
2089     * @return {@code true} if the actual version is equal or greater than the required version
2090     */
2091    public static boolean isJavaVersionAtLeast(final JavaVersion requiredVersion) {
2092        return JAVA_SPECIFICATION_VERSION_AS_ENUM.atLeast(requiredVersion);
2093    }
2094
2095    /**
2096     * Is the Java version at most the requested version.
2097     *
2098     * <p>
2099     * Example input:
2100     * </p>
2101     *
2102     * @param requiredVersion the required version, for example 1.31f
2103     * @return {@code true} if the actual version is equal or less than the required version
2104     * @since 3.9
2105     */
2106    public static boolean isJavaVersionAtMost(final JavaVersion requiredVersion) {
2107        return JAVA_SPECIFICATION_VERSION_AS_ENUM.atMost(requiredVersion);
2108    }
2109
2110    /**
2111     * Decides if the Java version matches.
2112     *
2113     * <p>
2114     * This method is package private instead of private to support unit test invocation.
2115     * </p>
2116     *
2117     * @param version the actual Java version
2118     * @param versionPrefix the prefix for the expected Java version
2119     * @return true if matches, or false if not or can't determine
2120     */
2121    static boolean isJavaVersionMatch(final String version, final String versionPrefix) {
2122        if (version == null) {
2123            return false;
2124        }
2125        return version.startsWith(versionPrefix);
2126    }
2127
2128    /**
2129     * Decides if the operating system matches.
2130     * <p>
2131     * This method is package private instead of private to support unit test invocation.
2132     * </p>
2133     *
2134     * @param osName the actual OS name
2135     * @param osVersion the actual OS version
2136     * @param osNamePrefix the prefix for the expected OS name
2137     * @param osVersionPrefix the prefix for the expected OS version
2138     * @return true if matches, or false if not or can't determine
2139     */
2140    static boolean isOsMatch(final String osName, final String osVersion, final String osNamePrefix, final String osVersionPrefix) {
2141        if (osName == null || osVersion == null) {
2142            return false;
2143        }
2144        return isOsNameMatch(osName, osNamePrefix) && isOsVersionMatch(osVersion, osVersionPrefix);
2145    }
2146
2147    /**
2148     * Decides if the operating system matches.
2149     * <p>
2150     * This method is package private instead of private to support unit test invocation.
2151     * </p>
2152     *
2153     * @param osName the actual OS name
2154     * @param osNamePrefix the prefix for the expected OS name
2155     * @return true if matches, or false if not or can't determine
2156     */
2157    static boolean isOsNameMatch(final String osName, final String osNamePrefix) {
2158        if (osName == null) {
2159            return false;
2160        }
2161        return osName.startsWith(osNamePrefix);
2162    }
2163
2164    /**
2165     * Decides if the operating system version matches.
2166     * <p>
2167     * This method is package private instead of private to support unit test invocation.
2168     * </p>
2169     *
2170     * @param osVersion the actual OS version
2171     * @param osVersionPrefix the prefix for the expected OS version
2172     * @return true if matches, or false if not or can't determine
2173     */
2174    static boolean isOsVersionMatch(final String osVersion, final String osVersionPrefix) {
2175        if (StringUtils.isEmpty(osVersion)) {
2176            return false;
2177        }
2178        // Compare parts of the version string instead of using String.startsWith(String) because otherwise
2179        // osVersionPrefix 10.1 would also match osVersion 10.10
2180        final String[] versionPrefixParts = JavaVersion.split(osVersionPrefix);
2181        final String[] versionParts = JavaVersion.split(osVersion);
2182        for (int i = 0; i < Math.min(versionPrefixParts.length, versionParts.length); i++) {
2183            if (!versionPrefixParts[i].equals(versionParts[i])) {
2184                return false;
2185            }
2186        }
2187        return true;
2188    }
2189
2190    /**
2191     * SystemUtils instances should NOT be constructed in standard programming. Instead, the class should be used as
2192     * {@code SystemUtils.FILE_SEPARATOR}.
2193     *
2194     * <p>
2195     * This constructor is public to permit tools that require a JavaBean instance to operate.
2196     * </p>
2197     */
2198    public SystemUtils() {
2199    }
2200
2201}