View Javadoc

1   /*
2    * $Id: SystemUtils.java 7976 2007-08-21 14:26:13Z 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                  // TODO MULE-863: Is this bad enough to fail?
72                  logger.error("Could not access OS environment: ", ex);
73                  environment = Collections.EMPTY_MAP;
74              }
75          }
76  
77          return environment;
78      }
79  
80      private static Map getenvJDK14() throws Exception
81      {
82          Map env = new HashMap();
83          Process process = null;
84  
85          try
86          {
87              boolean isUnix = true;
88              String command;
89  
90              if (SystemUtils.IS_OS_WINDOWS)
91              {
92                  command = "cmd /c set";
93                  isUnix = false;
94              }
95              else
96              {
97                  command = "env";
98              }
99  
100             process = Runtime.getRuntime().exec(command);
101             BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
102 
103             String line;
104             while ((line = br.readLine()) != null)
105             {
106                 for (int prefix = 0; prefix < UNIX_ENV_PREFIXES.length; prefix++)
107                 {
108                     if (line.startsWith(UNIX_ENV_PREFIXES[prefix]))
109                     {
110                         line = line.substring(UNIX_ENV_PREFIXES[prefix].length());
111                     }
112                 }
113 
114                 int index = -1;
115                 if ((index = line.indexOf('=')) > -1)
116                 {
117                     String key = line.substring(0, index).trim();
118                     String value = line.substring(index + 1).trim();
119                     // remove quotes, if any
120                     if (isUnix && value.length() > 1 && (value.startsWith("\"") || value.startsWith("'")))
121                     {
122                         value = value.substring(1, value.length() - 1);
123                     }
124                     env.put(key, value);
125                 }
126                 else
127                 {
128                     env.put(line, StringUtils.EMPTY);
129                 }
130             }
131         }
132         catch (Exception e)
133         {
134             throw e; // bubble up
135         }
136         finally
137         {
138             if (process != null)
139             {
140                 process.destroy();
141             }
142         }
143 
144         return env;
145     }
146 
147     public static String getenv(String name)
148     {
149         return (String) SystemUtils.getenv().get(name);
150     }
151 
152     public static boolean isSunJDK()
153     {
154         return SystemUtils.JAVA_VM_VENDOR.toUpperCase().indexOf("SUN") != -1;
155     }
156 
157     public static boolean isIbmJDK()
158     {
159         return SystemUtils.JAVA_VM_VENDOR.toUpperCase().indexOf("IBM") != -1;
160     }
161 
162     private static CommandLine parseCommandLine(String args[], String opts[][]) throws MuleException
163     {
164         Options options = new Options();
165         for (int i = 0; i < opts.length; i++)
166         {
167             options.addOption(opts[i][0], opts[i][1].equals("true") ? true : false, opts[i][2]);
168         }
169 
170         BasicParser parser = new BasicParser();
171 
172         try
173         {
174             CommandLine line = parser.parse(options, args, true);
175             if (line == null)
176             {
177                 throw new MuleException("Unknown error parsing the Mule command line");
178             }
179 
180             return line;
181         }
182         catch (ParseException p)
183         {
184             throw new MuleException("Unable to parse the Mule command line because of: " + p.toString(), p);
185         }
186     }
187 
188     /**
189      * Returns the value corresponding to the given option from the command line, for
190      * example if the options are "-config mule-config.xml"
191      * getCommandLineOption("config") would return "mule-config.xml"
192      */
193     public static String getCommandLineOption(String option, String args[], String opts[][])
194         throws MuleException
195     {
196         CommandLine line = parseCommandLine(args, opts);
197         return line.getOptionValue(option);
198     }
199 
200     /**
201      * Checks whether a command line option is set. This is useful for command line
202      * options that don't have an argument, like "-cluster", which means that this
203      * Mule instance is part of a cluster.
204      */
205     public static boolean hasCommandLineOption(String option, String args[], String opts[][])
206         throws MuleException
207     {
208         CommandLine line = parseCommandLine(args, opts);
209         return line.hasOption(option);
210     }
211 
212     /**
213      * Returns a Map of all options in the command line. The Map is keyed off the
214      * option name. The value will be whatever is present on the command line.
215      * Options that don't have an argument will have the String "true".
216      */
217     public static Map getCommandLineOptions(String args[], String opts[][]) throws MuleException
218     {
219         CommandLine line = parseCommandLine(args, opts);
220         Map ret = new HashMap();
221         Option[] options = line.getOptions();
222 
223         for (int i = 0; i < options.length; i++)
224         {
225             Option option = options[i];
226             ret.put(option.getOpt(), option.getValue("true"));
227         }
228 
229         return ret;
230     }
231 
232     /**
233      * Returns a Map of all valid property definitions in <code>-Dkey=value</code>
234      * format. <code>-Dkey</code> is interpreted as <code>-Dkey=true</code>,
235      * everything else is ignored. Whitespace in values is properly handled but needs
236      * to be quoted properly: <code>-Dkey="some value"</code>.
237      * 
238      * @param input String with property definitionn
239      * @return a {@link Map} of property String keys with their defined values
240      *         (Strings). If no valid key-value pairs can be parsed, the map is
241      *         empty.
242      */
243     public static Map parsePropertyDefinitions(String input)
244     {
245         if (StringUtils.isEmpty(input))
246         {
247             return Collections.EMPTY_MAP;
248         }
249 
250         // the result map of property key/value pairs
251         final Map result = new HashMap();
252 
253         // where to begin looking for key/value tokens
254         int tokenStart = 0;
255 
256         // this is the main loop that scans for all tokens
257         findtoken : while (tokenStart < input.length())
258         {
259             // find first definition or bail
260             tokenStart = StringUtils.indexOf(input, "-D", tokenStart);
261             if (tokenStart == StringUtils.INDEX_NOT_FOUND)
262             {
263                 break findtoken;
264             }
265             else
266             {
267                 // skip leading -D
268                 tokenStart += 2;
269             }
270 
271             // find key
272             int keyStart = tokenStart;
273             int keyEnd = keyStart;
274 
275             if (keyStart == input.length())
276             {
277                 // short input: '-D' only
278                 break;
279             }
280 
281             // let's check out what we have next
282             char cursor = input.charAt(keyStart);
283 
284             // '-D xxx'
285             if (cursor == ' ')
286             {
287                 continue findtoken;
288             }
289 
290             // '-D='
291             if (cursor == '=')
292             {
293                 // skip over garbage to next potential definition
294                 tokenStart = StringUtils.indexOf(input, ' ', tokenStart);
295                 if (tokenStart != StringUtils.INDEX_NOT_FOUND)
296                 {
297                     // '-D= ..' - continue with next token
298                     continue findtoken;
299                 }
300                 else
301                 {
302                     // '-D=' - get out of here
303                     break findtoken;
304                 }
305             }
306 
307             // apparently there's a key, so find the end
308             findkey : while (keyEnd < input.length())
309             {
310                 cursor = input.charAt(keyEnd);
311 
312                 // '-Dkey ..'
313                 if (cursor == ' ')
314                 {
315                     tokenStart = keyEnd;
316                     break findkey;
317                 }
318 
319                 // '-Dkey=..'
320                 if (cursor == '=')
321                 {
322                     break findkey;
323                 }
324 
325                 // keep looking
326                 keyEnd++;
327             }
328 
329             // yay, finally a key
330             String key = StringUtils.substring(input, keyStart, keyEnd);
331 
332             // assume that there is no value following
333             int valueStart = keyEnd;
334             int valueEnd = keyEnd;
335 
336             // default value
337             String value = "true";
338 
339             // now find the value, but only if the current cursor is not a space
340             if (keyEnd < input.length() && cursor != ' ')
341             {
342                 // bump value start/end
343                 valueStart = keyEnd + 1;
344                 valueEnd = valueStart;
345 
346                 // '-Dkey="..'
347                 cursor = input.charAt(valueStart);
348                 if (cursor == '"')
349                 {
350                     // opening "
351                     valueEnd = StringUtils.indexOf(input, '"', ++valueStart);
352                 }
353                 else
354                 {
355                     // unquoted value
356                     valueEnd = StringUtils.indexOf(input, ' ', valueStart);
357                 }
358 
359                 // no '"' or ' ' delimiter found - use the rest of the string
360                 if (valueEnd == StringUtils.INDEX_NOT_FOUND)
361                 {
362                     valueEnd = input.length();
363                 }
364 
365                 // create value
366                 value = StringUtils.substring(input, valueStart, valueEnd);
367             }
368 
369             // finally create key and value && loop again for next token
370             result.put(key, value);
371 
372             // start next search at end of value
373             tokenStart = valueEnd;
374         }
375 
376         return result;
377     }
378 
379 }