1 package org.codehaus.plexus.util;
2
3 /*
4 * The Apache Software License, Version 1.1
5 *
6 * Copyright (c) 2001-2003 The Apache Software Foundation. All rights
7 * reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. The end-user documentation included with the redistribution, if
22 * any, must include the following acknowledgement:
23 * "This product includes software developed by the
24 * Apache Software Foundation (http://www.apache.org/)."
25 * Alternately, this acknowledgement may appear in the software itself,
26 * if and wherever such third-party acknowledgements normally appear.
27 *
28 * 4. The names "Ant" and "Apache Software
29 * Foundation" must not be used to endorse or promote products derived
30 * from this software without prior written permission. For written
31 * permission, please contact apache@apache.org.
32 *
33 * 5. Products derived from this software may not be called "Apache"
34 * nor may "Apache" appear in their names without prior written
35 * permission of the Apache Group.
36 *
37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 * ====================================================================
50 *
51 * This software consists of voluntary contributions made by many
52 * individuals on behalf of the Apache Software Foundation. For more
53 * information on the Apache Software Foundation, please see
54 * <http://www.apache.org/>.
55 */
56
57 import java.util.HashSet;
58 import java.util.Locale;
59 import java.util.Set;
60
61 /**
62 * Condition that tests the OS type.
63 *
64 * @author Stefan Bodewig
65 * @author Magesh Umasankar
66 * @author Brian Fox
67 * @since 1.0
68 *
69 */
70 public class Os
71 {
72 // define the families for easier reference
73 public static final String FAMILY_DOS = "dos";
74
75 public static final String FAMILY_MAC = "mac";
76
77 public static final String FAMILY_NETWARE = "netware";
78
79 public static final String FAMILY_OS2 = "os/2";
80
81 public static final String FAMILY_TANDEM = "tandem";
82
83 public static final String FAMILY_UNIX = "unix";
84
85 public static final String FAMILY_WINDOWS = "windows";
86
87 public static final String FAMILY_WIN9X = "win9x";
88
89 public static final String FAMILY_ZOS = "z/os";
90
91 public static final String FAMILY_OS400 = "os/400";
92
93 public static final String FAMILY_OPENVMS = "openvms";
94
95 // store the valid families
96 private static final Set<String> validFamilies = setValidFamilies();
97
98 // get the current info
99 private static final String PATH_SEP = System.getProperty( "path.separator" );
100
101 public static final String OS_NAME = System.getProperty( "os.name" ).toLowerCase( Locale.US );
102
103 public static final String OS_ARCH = System.getProperty( "os.arch" ).toLowerCase( Locale.US );
104
105 public static final String OS_VERSION = System.getProperty( "os.version" ).toLowerCase( Locale.US );
106
107 // Make sure this method is called after static fields it depends on have been set!
108 public static final String OS_FAMILY = getOsFamily();
109
110 private String family;
111
112 private String name;
113
114 private String version;
115
116 private String arch;
117
118 /**
119 * Default constructor
120 */
121 public Os()
122 {
123 }
124
125 /**
126 * Constructor that sets the family attribute
127 *
128 * @param family a String value
129 */
130 public Os( String family )
131 {
132 setFamily( family );
133 }
134
135 /**
136 * Initializes the set of valid families.
137 */
138 private static Set<String> setValidFamilies()
139 {
140 Set<String> valid = new HashSet<String>();
141 valid.add( FAMILY_DOS );
142 valid.add( FAMILY_MAC );
143 valid.add( FAMILY_NETWARE );
144 valid.add( FAMILY_OS2 );
145 valid.add( FAMILY_TANDEM );
146 valid.add( FAMILY_UNIX );
147 valid.add( FAMILY_WINDOWS );
148 valid.add( FAMILY_WIN9X );
149 valid.add( FAMILY_ZOS );
150 valid.add( FAMILY_OS400 );
151 valid.add( FAMILY_OPENVMS );
152
153 return valid;
154 }
155
156 /**
157 * Sets the desired OS family type
158 *
159 * @param f The OS family type desired<br>
160 * Possible values:
161 * <ul>
162 * <li>dos</li>
163 * <li>mac</li>
164 * <li>netware</li>
165 * <li>os/2</li>
166 * <li>tandem</li>
167 * <li>unix</li>
168 * <li>windows</li>
169 * <li>win9x</li>
170 * <li>z/os</li>
171 * <li>os/400</li>
172 * <li>openvms</li>
173 * </ul>
174 */
175 public void setFamily( String f )
176 {
177 family = f.toLowerCase( Locale.US );
178 }
179
180 /**
181 * Sets the desired OS name
182 *
183 * @param name The OS name
184 */
185 public void setName( String name )
186 {
187 this.name = name.toLowerCase( Locale.US );
188 }
189
190 /**
191 * Sets the desired OS architecture
192 *
193 * @param arch The OS architecture
194 */
195 public void setArch( String arch )
196 {
197 this.arch = arch.toLowerCase( Locale.US );
198 }
199
200 /**
201 * Sets the desired OS version
202 *
203 * @param version The OS version
204 */
205 public void setVersion( String version )
206 {
207 this.version = version.toLowerCase( Locale.US );
208 }
209
210 /**
211 * @return Determines if the current OS matches the type of that set in setFamily.
212 *
213 * @see Os#setFamily(String)
214 * @throws Exception any errir
215 */
216 public boolean eval()
217 throws Exception
218 {
219 return isOs( family, name, arch, version );
220 }
221
222 /**
223 * Determines if the current OS matches the given OS family.
224 *
225 * @param family the family to check for
226 * @return true if the OS matches
227 * @since 1.0
228 */
229 public static boolean isFamily( String family )
230 {
231 return isOs( family, null, null, null );
232 }
233
234 /**
235 * Determines if the current OS matches the given OS name.
236 *
237 * @param name the OS name to check for
238 * @return true if the OS matches
239 * @since 1.0
240 */
241 public static boolean isName( String name )
242 {
243 return isOs( null, name, null, null );
244 }
245
246 /**
247 * Determines if the current OS matches the given OS architecture.
248 *
249 * @param arch the OS architecture to check for
250 * @return true if the OS matches
251 * @since 1.0
252 */
253 public static boolean isArch( String arch )
254 {
255 return isOs( null, null, arch, null );
256 }
257
258 /**
259 * Determines if the current OS matches the given OS version.
260 *
261 * @param version the OS version to check for
262 * @return true if the OS matches
263 * @since 1.0
264 */
265 public static boolean isVersion( String version )
266 {
267 return isOs( null, null, null, version );
268 }
269
270 /**
271 * Determines if the current OS matches the given OS family, name, architecture and version. The name, architecture
272 * and version are compared to the System properties os.name, os.version and os.arch in a case-independent way.
273 *
274 * @param family The OS family
275 * @param name The OS name
276 * @param arch The OS architecture
277 * @param version The OS version
278 * @return true if the OS matches
279 * @since 1.0
280 */
281 public static boolean isOs( String family, String name, String arch, String version )
282 {
283 boolean retValue = false;
284
285 if ( family != null || name != null || arch != null || version != null )
286 {
287
288 boolean isFamily = true;
289 boolean isName = true;
290 boolean isArch = true;
291 boolean isVersion = true;
292
293 if ( family != null )
294 {
295 if ( family.equalsIgnoreCase( FAMILY_WINDOWS ) )
296 {
297 isFamily = OS_NAME.contains( FAMILY_WINDOWS );
298 }
299 else if ( family.equalsIgnoreCase( FAMILY_OS2 ) )
300 {
301 isFamily = OS_NAME.contains( FAMILY_OS2 );
302 }
303 else if ( family.equalsIgnoreCase( FAMILY_NETWARE ) )
304 {
305 isFamily = OS_NAME.contains( FAMILY_NETWARE );
306 }
307 else if ( family.equalsIgnoreCase( FAMILY_DOS ) )
308 {
309 isFamily = PATH_SEP.equals( ";" ) && !isFamily( FAMILY_NETWARE ) && !isFamily( FAMILY_WINDOWS )
310 && !isFamily( FAMILY_WIN9X );
311
312 }
313 else if ( family.equalsIgnoreCase( FAMILY_MAC ) )
314 {
315 isFamily = OS_NAME.contains( FAMILY_MAC );
316 }
317 else if ( family.equalsIgnoreCase( FAMILY_TANDEM ) )
318 {
319 isFamily = OS_NAME.contains( "nonstop_kernel" );
320 }
321 else if ( family.equalsIgnoreCase( FAMILY_UNIX ) )
322 {
323 isFamily = PATH_SEP.equals( ":" ) && !isFamily( FAMILY_OPENVMS )
324 && ( !isFamily( FAMILY_MAC ) || OS_NAME.endsWith( "x" ) );
325 }
326 else if ( family.equalsIgnoreCase( FAMILY_WIN9X ) )
327 {
328 isFamily = isFamily( FAMILY_WINDOWS ) && ( OS_NAME.contains( "95" ) || OS_NAME.contains( "98" )
329 || OS_NAME.contains( "me" ) || OS_NAME.contains( "ce" ) );
330 }
331 else if ( family.equalsIgnoreCase( FAMILY_ZOS ) )
332 {
333 isFamily = OS_NAME.contains( FAMILY_ZOS ) || OS_NAME.contains( "os/390" );
334 }
335 else if ( family.equalsIgnoreCase( FAMILY_OS400 ) )
336 {
337 isFamily = OS_NAME.contains( FAMILY_OS400 );
338 }
339 else if ( family.equalsIgnoreCase( FAMILY_OPENVMS ) )
340 {
341 isFamily = OS_NAME.contains( FAMILY_OPENVMS );
342 }
343 else
344 {
345 isFamily = OS_NAME.contains( family.toLowerCase( Locale.US ) );
346 }
347 }
348 if ( name != null )
349 {
350 isName = name.toLowerCase( Locale.US ).equals( OS_NAME );
351 }
352 if ( arch != null )
353 {
354 isArch = arch.toLowerCase( Locale.US ).equals( OS_ARCH );
355 }
356 if ( version != null )
357 {
358 isVersion = version.toLowerCase( Locale.US ).equals( OS_VERSION );
359 }
360 retValue = isFamily && isName && isArch && isVersion;
361 }
362 return retValue;
363 }
364
365 /**
366 * Helper method to determine the current OS family.
367 *
368 * @return name of current OS family.
369 * @since 1.4.2
370 */
371 private static String getOsFamily()
372 {
373 // in case the order of static initialization is
374 // wrong, get the list
375 // safely.
376 Set<String> families = null;
377 if ( !validFamilies.isEmpty() )
378 {
379 families = validFamilies;
380 }
381 else
382 {
383 families = setValidFamilies();
384 }
385 for ( String fam : families )
386 {
387 if ( Os.isFamily( fam ) )
388 {
389 return fam;
390 }
391 }
392 return null;
393 }
394
395 /**
396 * Helper method to check if the given family is in the following list:
397 * <ul>
398 * <li>dos</li>
399 * <li>mac</li>
400 * <li>netware</li>
401 * <li>os/2</li>
402 * <li>tandem</li>
403 * <li>unix</li>
404 * <li>windows</li>
405 * <li>win9x</li>
406 * <li>z/os</li>
407 * <li>os/400</li>
408 * <li>openvms</li>
409 * </ul>
410 *
411 * @param theFamily the family to check.
412 * @return true if one of the valid families.
413 * @since 1.4.2
414 */
415 public static boolean isValidFamily( String theFamily )
416 {
417 return ( validFamilies.contains( theFamily ) );
418 }
419
420 /**
421 * @return a copy of the valid families
422 * @since 1.4.2
423 */
424 public static Set<String> getValidFamilies()
425 {
426 return new HashSet<String>( validFamilies );
427 }
428 }