1 /*
2  *  Licensed to the Apache Software Foundation (ASF) under one or more
3  *  contributor license agreements.  See the NOTICE file distributed with
4  *  this work for additional information regarding copyright ownership.
5  *  The ASF licenses this file to You under the Apache License, Version 2.0
6  *  (the "License"); you may not use this file except in compliance with
7  *  the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  */
18 
19 package org.apache.tools.ant.taskdefs.condition;
20 
21 import org.apache.tools.ant.BuildException;
22 
23 import java.util.Locale;
24 
25 /**
26  * Condition that tests the OS type.
27  *
28  * @since Ant 1.4
29  */
30 public class Os implements Condition {
31     private static final String OS_NAME =
32         System.getProperty("os.name").toLowerCase(Locale.ENGLISH);
33     private static final String OS_ARCH =
34         System.getProperty("os.arch").toLowerCase(Locale.ENGLISH);
35     private static final String OS_VERSION =
36         System.getProperty("os.version").toLowerCase(Locale.ENGLISH);
37     private static final String PATH_SEP =
38         System.getProperty("path.separator");
39 
40     /**
41      * OS family to look for
42      */
43     private String family;
44     /**
45      * Name of OS
46      */
47     private String name;
48     /**
49      * version of OS
50      */
51     private String version;
52     /**
53      * OS architecture
54      */
55     private String arch;
56     /**
57      * OS family that can be tested for. {@value}
58      */
59     public static final String FAMILY_WINDOWS = "windows";
60     /**
61      * OS family that can be tested for. {@value}
62      */
63     public static final String FAMILY_9X = "win9x";
64     /**
65      * OS family that can be tested for. {@value}
66      */
67     public static final String FAMILY_NT = "winnt";
68     /**
69      * OS family that can be tested for. {@value}
70      */
71     public static final String FAMILY_OS2 = "os/2";
72     /**
73      * OS family that can be tested for. {@value}
74      */
75     public static final String FAMILY_NETWARE = "netware";
76     /**
77      * OS family that can be tested for. {@value}
78      */
79     public static final String FAMILY_DOS = "dos";
80     /**
81      * OS family that can be tested for. {@value}
82      */
83     public static final String FAMILY_MAC = "mac";
84     /**
85      * OS family that can be tested for. {@value}
86      */
87     public static final String FAMILY_TANDEM = "tandem";
88     /**
89      * OS family that can be tested for. {@value}
90      */
91     public static final String FAMILY_UNIX = "unix";
92     /**
93      * OS family that can be tested for. {@value}
94      */
95     public static final String FAMILY_VMS = "openvms";
96     /**
97      * OS family that can be tested for. {@value}
98      */
99     public static final String FAMILY_ZOS = "z/os";
100     /** OS family that can be tested for. {@value} */
101     public static final String FAMILY_OS400 = "os/400";
102 
103     /**
104      * OpenJDK is reported to call MacOS X "Darwin"
105      * @see https://issues.apache.org/bugzilla/show_bug.cgi?id=44889
106      * @see https://issues.apache.org/jira/browse/HADOOP-3318
107      */
108     private static final String DARWIN = "darwin";
109 
110     /**
111      * Default constructor
112      *
113      */
Os()114     public Os() {
115         //default
116     }
117 
118     /**
119      * Constructor that sets the family attribute
120      * @param family a String value
121      */
Os(String family)122     public Os(String family) {
123         setFamily(family);
124     }
125 
126     /**
127      * Sets the desired OS family type
128      *
129      * @param f      The OS family type desired<br />
130      *               Possible values:<br />
131      *               <ul>
132      *               <li>dos</li>
133      *               <li>mac</li>
134      *               <li>netware</li>
135      *               <li>os/2</li>
136      *               <li>tandem</li>
137      *               <li>unix</li>
138      *               <li>windows</li>
139      *               <li>win9x</li>
140      *               <li>z/os</li>
141      *               <li>os/400</li>
142      *               </ul>
143      */
setFamily(String f)144     public void setFamily(String f) {
145         family = f.toLowerCase(Locale.ENGLISH);
146     }
147 
148     /**
149      * Sets the desired OS name
150      *
151      * @param name   The OS name
152      */
setName(String name)153     public void setName(String name) {
154         this.name = name.toLowerCase(Locale.ENGLISH);
155     }
156 
157     /**
158      * Sets the desired OS architecture
159      *
160      * @param arch   The OS architecture
161      */
setArch(String arch)162     public void setArch(String arch) {
163         this.arch = arch.toLowerCase(Locale.ENGLISH);
164     }
165 
166     /**
167      * Sets the desired OS version
168      *
169      * @param version   The OS version
170      */
setVersion(String version)171     public void setVersion(String version) {
172         this.version = version.toLowerCase(Locale.ENGLISH);
173     }
174 
175     /**
176      * Determines if the OS on which Ant is executing matches the type of
177      * that set in setFamily.
178      * @return true if the os matches.
179      * @throws BuildException if there is an error.
180      * @see Os#setFamily(String)
181      */
182     @Override
eval()183     public boolean eval() throws BuildException {
184         return isOs(family, name, arch, version);
185     }
186 
187     /**
188      * Determines if the OS on which Ant is executing matches the
189      * given OS family.
190      * @param family the family to check for
191      * @return true if the OS matches
192      * @since 1.5
193      */
isFamily(String family)194     public static boolean isFamily(String family) {
195         return isOs(family, null, null, null);
196     }
197 
198     /**
199      * Determines if the OS on which Ant is executing matches the
200      * given OS name.
201      *
202      * @param name the OS name to check for
203      * @return true if the OS matches
204      * @since 1.7
205      */
isName(String name)206     public static boolean isName(String name) {
207         return isOs(null, name, null, null);
208     }
209 
210     /**
211      * Determines if the OS on which Ant is executing matches the
212      * given OS architecture.
213      *
214      * @param arch the OS architecture to check for
215      * @return true if the OS matches
216      * @since 1.7
217      */
isArch(String arch)218     public static boolean isArch(String arch) {
219         return isOs(null, null, arch, null);
220     }
221 
222     /**
223      * Determines if the OS on which Ant is executing matches the
224      * given OS version.
225      *
226      * @param version the OS version to check for
227      * @return true if the OS matches
228      * @since 1.7
229      */
isVersion(String version)230     public static boolean isVersion(String version) {
231         return isOs(null, null, null, version);
232     }
233 
234     /**
235      * Determines if the OS on which Ant is executing matches the
236      * given OS family, name, architecture and version
237      *
238      * @param family   The OS family
239      * @param name   The OS name
240      * @param arch   The OS architecture
241      * @param version   The OS version
242      * @return true if the OS matches
243      * @since 1.7
244      */
isOs(String family, String name, String arch, String version)245     public static boolean isOs(String family, String name, String arch,
246                                String version) {
247         boolean retValue = false;
248 
249         if (family != null || name != null || arch != null
250             || version != null) {
251 
252             boolean isFamily = true;
253             boolean isName = true;
254             boolean isArch = true;
255             boolean isVersion = true;
256 
257             if (family != null) {
258 
259                 //windows probing logic relies on the word 'windows' in
260                 //the OS
261                 boolean isWindows = OS_NAME.indexOf(FAMILY_WINDOWS) > -1;
262                 boolean is9x = false;
263                 boolean isNT = false;
264                 if (isWindows) {
265                     //there are only four 9x platforms that we look for
266                     is9x = (OS_NAME.indexOf("95") >= 0
267                             || OS_NAME.indexOf("98") >= 0
268                             || OS_NAME.indexOf("me") >= 0
269                             //wince isn't really 9x, but crippled enough to
270                             //be a muchness. Ant doesnt run on CE, anyway.
271                             || OS_NAME.indexOf("ce") >= 0);
272                     isNT = !is9x;
273                 }
274                 if (family.equals(FAMILY_WINDOWS)) {
275                     isFamily = isWindows;
276                 } else if (family.equals(FAMILY_9X)) {
277                     isFamily = isWindows && is9x;
278                 } else if (family.equals(FAMILY_NT)) {
279                     isFamily = isWindows && isNT;
280                 } else if (family.equals(FAMILY_OS2)) {
281                     isFamily = OS_NAME.indexOf(FAMILY_OS2) > -1;
282                 } else if (family.equals(FAMILY_NETWARE)) {
283                     isFamily = OS_NAME.indexOf(FAMILY_NETWARE) > -1;
284                 } else if (family.equals(FAMILY_DOS)) {
285                     isFamily = PATH_SEP.equals(";") && !isFamily(FAMILY_NETWARE);
286                 } else if (family.equals(FAMILY_MAC)) {
287                     isFamily = OS_NAME.indexOf(FAMILY_MAC) > -1
288                         || OS_NAME.indexOf(DARWIN) > -1;
289                 } else if (family.equals(FAMILY_TANDEM)) {
290                     isFamily = OS_NAME.indexOf("nonstop_kernel") > -1;
291                 } else if (family.equals(FAMILY_UNIX)) {
292                     isFamily = PATH_SEP.equals(":")
293                         && !isFamily(FAMILY_VMS)
294                         && (!isFamily(FAMILY_MAC) || OS_NAME.endsWith("x")
295                             || OS_NAME.indexOf(DARWIN) > -1);
296                 } else if (family.equals(FAMILY_ZOS)) {
297                     isFamily = OS_NAME.indexOf(FAMILY_ZOS) > -1
298                         || OS_NAME.indexOf("os/390") > -1;
299                 } else if (family.equals(FAMILY_OS400)) {
300                     isFamily = OS_NAME.indexOf(FAMILY_OS400) > -1;
301                 } else if (family.equals(FAMILY_VMS)) {
302                     isFamily = OS_NAME.indexOf(FAMILY_VMS) > -1;
303                 } else {
304                     throw new BuildException(
305                         "Don\'t know how to detect os family \""
306                         + family + "\"");
307                 }
308             }
309             if (name != null) {
310                 isName = name.equals(OS_NAME);
311             }
312             if (arch != null) {
313                 isArch = arch.equals(OS_ARCH);
314             }
315             if (version != null) {
316                 isVersion = version.equals(OS_VERSION);
317             }
318             retValue = isFamily && isName && isArch && isVersion;
319         }
320         return retValue;
321     }
322 }
323