View Javadoc

1   /*
2    * $Id: SystemUtils.java 10404 2008-01-18 17:06:25Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.util;
12  
13  import org.mule.MuleException;
14  
15  import java.io.BufferedReader;
16  import java.io.InputStreamReader;
17  import java.lang.reflect.Method;
18  import java.util.Collections;
19  import java.util.HashMap;
20  import java.util.Map;
21  
22  import org.apache.commons.cli.BasicParser;
23  import org.apache.commons.cli.CommandLine;
24  import org.apache.commons.cli.Option;
25  import org.apache.commons.cli.Options;
26  import org.apache.commons.cli.ParseException;
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  
30  // @ThreadSafe
31  public class SystemUtils extends org.apache.commons.lang.SystemUtils
32  {
33      // class logger
34      protected static final Log logger = LogFactory.getLog(SystemUtils.class);
35  
36      // bash prepends: declare -x
37      // zsh prepends: typeset -x
38      private static final String[] UNIX_ENV_PREFIXES = new String[]{"declare -", "typeset -"};
39  
40      // the environment of the VM process
41      private static Map environment = null;
42  
43      /**
44       * Get the operating system environment variables. This should work for Windows
45       * and Linux.
46       * 
47       * @return Map<String, String> or an empty map if there was an error.
48       */
49      public static synchronized Map getenv()
50      {
51          if (environment == null)
52          {
53              try
54              {
55                  if (SystemUtils.IS_JAVA_1_4)
56                  {
57                      // fallback to external process
58                      environment = Collections.unmodifiableMap(getenvJDK14());
59                  }
60                  else
61                  {
62                      // the following runaround is necessary since we still want to
63                      // compile on JDK 1.4
64                      Class target = System.class;
65                      Method envMethod = target.getMethod("getenv", ArrayUtils.EMPTY_CLASS_ARRAY);
66                      environment = Collections.unmodifiableMap((Map) envMethod.invoke(target, (Class[]) null));
67                  }
68              }
69              catch (Exception ex)
70              {
71                  logger.error("Could not access OS environment: ", ex);
72                  environment = Collections.EMPTY_MAP;
73              }
74          }
75  
76          return environment;
77      }
78  
79      private static Map getenvJDK14() throws Exception
80      {
81          Map env = new HashMap();
82          Process process = null;
83  
84          try
85          {
86              boolean isUnix = true;
87              String command;
88  
89              if (SystemUtils.IS_OS_WINDOWS)
90              {
91                  command = "cmd /c set";
92                  isUnix = false;
93              }
94              else
95              {
96                  command = "env";
97              }
98  
99              process = Runtime.getRuntime().exec(command);
100             BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
101 
102             String line;
103             while ((line = br.readLine()) != null)
104             {
105                 for (int prefix = 0; prefix < UNIX_ENV_PREFIXES.length; prefix++)
106                 {
107                     if (line.startsWith(UNIX_ENV_PREFIXES[prefix]))
108                     {
109                         line = line.substring(UNIX_ENV_PREFIXES[prefix].length());
110                     }
111                 }
112 
113                 int index = -1;
114                 if ((index = line.indexOf('=')) > -1)
115                 {
116                     String key = line.substring(0, index).trim();
117                     String value = line.substring(index + 1).trim();
118                     // remove quotes, if any
119                     if (isUnix && value.length() > 1 && (value.startsWith("\"") || value.startsWith("'")))
120                     {
121                         value = value.substring(1, value.length() - 1);
122                     }
123                     env.put(key, value);
124                 }
125                 else
126                 {
127                     env.put(line, StringUtils.EMPTY);
128                 }
129             }
130         }
131         catch (Exception e)
132         {
133             throw e; // bubble up
134         }
135         finally
136         {
137             if (process != null)
138             {
139                 process.destroy();
140             }
141         }
142 
143         return env;
144     }
145 
146     public static String getenv(String name)
147     {
148         return (String) SystemUtils.getenv().get(name);
149     }
150 
151     public static boolean isSunJDK()
152     {
153         return SystemUtils.JAVA_VM_VENDOR.toUpperCase().indexOf("SUN") != -1;
154     }
155 
156     public static boolean isIbmJDK()
157     {
158         return SystemUtils.JAVA_VM_VENDOR.toUpperCase().indexOf("IBM") != -1;
159     }
160 
161     private static CommandLine parseCommandLine(String args[], String opts[][]) throws MuleException
162     {
163         Options options = new Options();
164         for (int i = 0; i < opts.length; i++)
165         {
166             options.addOption(opts[i][0], opts[i][1].equals("true") ? true : false, opts[i][2]);
167         }
168 
169         BasicParser parser = new BasicParser();
170 
171         try
172         {
173             CommandLine line = parser.parse(options, args, true);
174             if (line == null)
175             {
176                 throw new MuleException("Unknown error parsing the Mule command line");
177             }
178 
179             return line;
180         }
181         catch (ParseException p)
182         {
183             throw new MuleException("Unable to parse the Mule command line because of: " + p.toString(), p);
184         }
185     }
186 
187     /**
188      * Returns the value corresponding to the given option from the command line, for
189      * example if the options are "-config mule-config.xml"
190      * getCommandLineOption("config") would return "mule-config.xml"
191      */
192     public static String getCommandLineOption(String option, String args[], String opts[][])
193         throws MuleException
194     {
195         CommandLine line = parseCommandLine(args, opts);
196         return line.getOptionValue(option);
197     }
198 
199     /**
200      * Checks whether a command line option is set. This is useful for command line
201      * options that don't have an argument, like "-cluster", which means that this
202      * Mule instance is part of a cluster.
203      */
204     public static boolean hasCommandLineOption(String option, String args[], String opts[][])
205         throws MuleException
206     {
207         CommandLine line = parseCommandLine(args, opts);
208         return line.hasOption(option);
209     }
210 
211     /**
212      * Returns a Map of all options in the command line. The Map is keyed off the
213      * option name. The value will be whatever is present on the command line.
214      * Options that don't have an argument will have the String "true".
215      */
216     public static Map getCommandLineOptions(String args[], String opts[][]) throws MuleException
217     {
218         CommandLine line = parseCommandLine(args, opts);
219         Map ret = new HashMap();
220         Option[] options = line.getOptions();
221 
222         for (int i = 0; i < options.length; i++)
223         {
224             Option option = options[i];
225             ret.put(option.getOpt(), option.getValue("true"));
226         }
227 
228         return ret;
229     }
230 
231     /**
232      * Returns a Map of all valid property definitions in <code>-Dkey=value</code>
233      * format. <code>-Dkey</code> is interpreted as <code>-Dkey=true</code>,
234      * everything else is ignored. Whitespace in values is properly handled but needs
235      * to be quoted properly: <code>-Dkey="some value"</code>.
236      * 
237      * @param input String with property definitionn
238      * @return a {@link Map} of property String keys with their defined values
239      *         (Strings). If no valid key-value pairs can be parsed, the map is
240      *         empty.
241      */
242     public static Map parsePropertyDefinitions(String input)
243     {
244         if (StringUtils.isEmpty(input))
245         {
246             return Collections.EMPTY_MAP;
247         }
248 
249         // the result map of property key/value pairs
250         final Map result = new HashMap();
251 
252         // where to begin looking for key/value tokens
253         int tokenStart = 0;
254 
255         // this is the main loop that scans for all tokens
256         findtoken : while (tokenStart < input.length())
257         {
258             // find first definition or bail
259             tokenStart = StringUtils.indexOf(input, "-D", tokenStart);
260             if (tokenStart == StringUtils.INDEX_NOT_FOUND)
261             {
262                 break findtoken;
263             }
264             else
265             {
266                 // skip leading -D
267                 tokenStart += 2;
268             }
269 
270             // find key
271             int keyStart = tokenStart;
272             int keyEnd = keyStart;
273 
274             if (keyStart == input.length())
275             {
276                 // short input: '-D' only
277                 break;
278             }
279 
280             // let's check out what we have next
281             char cursor = input.charAt(keyStart);
282 
283             // '-D xxx'
284             if (cursor == ' ')
285             {
286                 continue findtoken;
287             }
288 
289             // '-D='
290             if (cursor == '=')
291             {
292                 // skip over garbage to next potential definition
293                 tokenStart = StringUtils.indexOf(input, ' ', tokenStart);
294                 if (tokenStart != StringUtils.INDEX_NOT_FOUND)
295                 {
296                     // '-D= ..' - continue with next token
297                     continue findtoken;
298                 }
299                 else
300                 {
301                     // '-D=' - get out of here
302                     break findtoken;
303                 }
304             }
305 
306             // apparently there's a key, so find the end
307             findkey : while (keyEnd < input.length())
308             {
309                 cursor = input.charAt(keyEnd);
310 
311                 // '-Dkey ..'
312                 if (cursor == ' ')
313                 {
314                     tokenStart = keyEnd;
315                     break findkey;
316                 }
317 
318                 // '-Dkey=..'
319                 if (cursor == '=')
320                 {
321                     break findkey;
322                 }
323 
324                 // keep looking
325                 keyEnd++;
326             }
327 
328             // yay, finally a key
329             String key = StringUtils.substring(input, keyStart, keyEnd);
330 
331             // assume that there is no value following
332             int valueStart = keyEnd;
333             int valueEnd = keyEnd;
334 
335             // default value
336             String value = "true";
337 
338             // now find the value, but only if the current cursor is not a space
339             if (keyEnd < input.length() && cursor != ' ')
340             {
341                 // bump value start/end
342                 valueStart = keyEnd + 1;
343                 valueEnd = valueStart;
344 
345                 // '-Dkey="..'
346                 cursor = input.charAt(valueStart);
347                 if (cursor == '"')
348                 {
349                     // opening "
350                     valueEnd = StringUtils.indexOf(input, '"', ++valueStart);
351                 }
352                 else
353                 {
354                     // unquoted value
355                     valueEnd = StringUtils.indexOf(input, ' ', valueStart);
356                 }
357 
358                 // no '"' or ' ' delimiter found - use the rest of the string
359                 if (valueEnd == StringUtils.INDEX_NOT_FOUND)
360                 {
361                     valueEnd = input.length();
362                 }
363 
364                 // create value
365                 value = StringUtils.substring(input, valueStart, valueEnd);
366             }
367 
368             // finally create key and value && loop again for next token
369             result.put(key, value);
370 
371             // start next search at end of value
372             tokenStart = valueEnd;
373         }
374 
375         return result;
376     }
377 
378 }