001: /*
002: * $Id: SystemUtils.java 10802 2008-02-14 11:39:16Z holger $
003: * --------------------------------------------------------------------------------------
004: * Copyright (c) MuleSource, Inc. All rights reserved. http://www.mulesource.com
005: *
006: * The software in this package is published under the terms of the CPAL v1.0
007: * license, a copy of which has been included with this distribution in the
008: * LICENSE.txt file.
009: */
010:
011: package org.mule.util;
012:
013: import org.mule.api.DefaultMuleException;
014:
015: import java.io.BufferedReader;
016: import java.io.InputStreamReader;
017: import java.lang.reflect.Method;
018: import java.util.Collections;
019: import java.util.HashMap;
020: import java.util.Map;
021:
022: import org.apache.commons.cli.BasicParser;
023: import org.apache.commons.cli.CommandLine;
024: import org.apache.commons.cli.Option;
025: import org.apache.commons.cli.Options;
026: import org.apache.commons.cli.ParseException;
027: import org.apache.commons.logging.Log;
028: import org.apache.commons.logging.LogFactory;
029:
030: // @ThreadSafe
031: public class SystemUtils extends org.apache.commons.lang.SystemUtils {
032: // class logger
033: protected static final Log logger = LogFactory
034: .getLog(SystemUtils.class);
035:
036: // bash prepends: declare -x
037: // zsh prepends: typeset -x
038: private static final String[] UNIX_ENV_PREFIXES = new String[] {
039: "declare -", "typeset -" };
040:
041: // the environment of the VM process
042: private static Map environment = null;
043:
044: /**
045: * Get the operating system environment variables. This should work for Windows
046: * and Linux.
047: *
048: * @return Map<String, String> or an empty map if there was an error.
049: */
050: public static synchronized Map getenv() {
051: if (environment == null) {
052: try {
053: if (SystemUtils.IS_JAVA_1_4) {
054: // fallback to external process
055: environment = Collections
056: .unmodifiableMap(getenvJDK14());
057: } else {
058: // the following runaround is necessary since we still want to
059: // compile on JDK 1.4
060: Class target = System.class;
061: Method envMethod = target.getMethod("getenv",
062: ArrayUtils.EMPTY_CLASS_ARRAY);
063: environment = Collections
064: .unmodifiableMap((Map) envMethod.invoke(
065: target, (Object[]) null));
066: }
067: } catch (Exception ex) {
068: logger.error("Could not access OS environment: ", ex);
069: environment = Collections.EMPTY_MAP;
070: }
071: }
072:
073: return environment;
074: }
075:
076: private static Map getenvJDK14() throws Exception {
077: Map env = new HashMap();
078: Process process = null;
079:
080: try {
081: boolean isUnix = true;
082: String command;
083:
084: if (SystemUtils.IS_OS_WINDOWS) {
085: command = "cmd /c set";
086: isUnix = false;
087: } else {
088: command = "env";
089: }
090:
091: process = Runtime.getRuntime().exec(command);
092: BufferedReader br = new BufferedReader(
093: new InputStreamReader(process.getInputStream()));
094:
095: String line;
096: while ((line = br.readLine()) != null) {
097: for (int prefix = 0; prefix < UNIX_ENV_PREFIXES.length; prefix++) {
098: if (line.startsWith(UNIX_ENV_PREFIXES[prefix])) {
099: line = line.substring(UNIX_ENV_PREFIXES[prefix]
100: .length());
101: }
102: }
103:
104: int index = -1;
105: if ((index = line.indexOf('=')) > -1) {
106: String key = line.substring(0, index).trim();
107: String value = line.substring(index + 1).trim();
108: // remove quotes, if any
109: if (isUnix
110: && value.length() > 1
111: && (value.startsWith("\"") || value
112: .startsWith("'"))) {
113: value = value.substring(1, value.length() - 1);
114: }
115: env.put(key, value);
116: } else {
117: env.put(line, StringUtils.EMPTY);
118: }
119: }
120: } catch (Exception e) {
121: throw e; // bubble up
122: } finally {
123: if (process != null) {
124: process.destroy();
125: }
126: }
127:
128: return env;
129: }
130:
131: public static String getenv(String name) {
132: return (String) SystemUtils.getenv().get(name);
133: }
134:
135: public static boolean isSunJDK() {
136: return SystemUtils.JAVA_VM_VENDOR.toUpperCase().indexOf("SUN") != -1;
137: }
138:
139: public static boolean isIbmJDK() {
140: return SystemUtils.JAVA_VM_VENDOR.toUpperCase().indexOf("IBM") != -1;
141: }
142:
143: /**
144: * @deprecated MULE-1947 Command-line arguments will be handled exclusively by the bootloader in 2.0
145: */
146: private static CommandLine parseCommandLine(String args[],
147: String opts[][]) throws DefaultMuleException {
148: Options options = new Options();
149: for (int i = 0; i < opts.length; i++) {
150: options.addOption(opts[i][0],
151: opts[i][1].equals("true") ? true : false,
152: opts[i][2]);
153: }
154:
155: BasicParser parser = new BasicParser();
156:
157: try {
158: CommandLine line = parser.parse(options, args, true);
159: if (line == null) {
160: throw new DefaultMuleException(
161: "Unknown error parsing the Mule command line");
162: }
163:
164: return line;
165: } catch (ParseException p) {
166: throw new DefaultMuleException(
167: "Unable to parse the Mule command line because of: "
168: + p.toString(), p);
169: }
170: }
171:
172: /**
173: * Returns the value corresponding to the given option from the command line, for
174: * example if the options are "-config mule-config.xml"
175: * getCommandLineOption("config") would return "mule-config.xml"
176: *
177: * @deprecated MULE-1947 Command-line arguments will be handled exclusively by the bootloader in 2.0
178: */
179: public static String getCommandLineOption(String option,
180: String args[], String opts[][]) throws DefaultMuleException {
181: CommandLine line = parseCommandLine(args, opts);
182: return line.getOptionValue(option);
183: }
184:
185: /**
186: * Checks whether a command line option is set. This is useful for command line
187: * options that don't have an argument, like "-cluster", which means that this
188: * Mule instance is part of a cluster.
189: *
190: * @deprecated MULE-1947 Command-line arguments will be handled exclusively by the bootloader in 2.0
191: */
192: public static boolean hasCommandLineOption(String option,
193: String args[], String opts[][]) throws DefaultMuleException {
194: CommandLine line = parseCommandLine(args, opts);
195: return line.hasOption(option);
196: }
197:
198: /**
199: * Returns a Map of all options in the command line. The Map is keyed off the
200: * option name. The value will be whatever is present on the command line.
201: * Options that don't have an argument will have the String "true".
202: *
203: * @deprecated MULE-1947 Command-line arguments will be handled exclusively by the bootloader in 2.0
204: */
205: public static Map getCommandLineOptions(String args[],
206: String opts[][]) throws DefaultMuleException {
207: CommandLine line = parseCommandLine(args, opts);
208: Map ret = new HashMap();
209: Option[] options = line.getOptions();
210:
211: for (int i = 0; i < options.length; i++) {
212: Option option = options[i];
213: ret.put(option.getOpt(), option.getValue("true"));
214: }
215:
216: return ret;
217: }
218:
219: /**
220: * Returns a Map of all valid property definitions in <code>-Dkey=value</code>
221: * format. <code>-Dkey</code> is interpreted as <code>-Dkey=true</code>,
222: * everything else is ignored. Whitespace in values is properly handled but needs
223: * to be quoted properly: <code>-Dkey="some value"</code>.
224: *
225: * @param input String with property definitionn
226: * @return a {@link Map} of property String keys with their defined values
227: * (Strings). If no valid key-value pairs can be parsed, the map is
228: * empty.
229: */
230: public static Map parsePropertyDefinitions(String input) {
231: if (StringUtils.isEmpty(input)) {
232: return Collections.EMPTY_MAP;
233: }
234:
235: // the result map of property key/value pairs
236: final Map result = new HashMap();
237:
238: // where to begin looking for key/value tokens
239: int tokenStart = 0;
240:
241: // this is the main loop that scans for all tokens
242: findtoken: while (tokenStart < input.length()) {
243: // find first definition or bail
244: tokenStart = StringUtils.indexOf(input, "-D", tokenStart);
245: if (tokenStart == StringUtils.INDEX_NOT_FOUND) {
246: break findtoken;
247: } else {
248: // skip leading -D
249: tokenStart += 2;
250: }
251:
252: // find key
253: int keyStart = tokenStart;
254: int keyEnd = keyStart;
255:
256: if (keyStart == input.length()) {
257: // short input: '-D' only
258: break;
259: }
260:
261: // let's check out what we have next
262: char cursor = input.charAt(keyStart);
263:
264: // '-D xxx'
265: if (cursor == ' ') {
266: continue findtoken;
267: }
268:
269: // '-D='
270: if (cursor == '=') {
271: // skip over garbage to next potential definition
272: tokenStart = StringUtils
273: .indexOf(input, ' ', tokenStart);
274: if (tokenStart != StringUtils.INDEX_NOT_FOUND) {
275: // '-D= ..' - continue with next token
276: continue findtoken;
277: } else {
278: // '-D=' - get out of here
279: break findtoken;
280: }
281: }
282:
283: // apparently there's a key, so find the end
284: findkey: while (keyEnd < input.length()) {
285: cursor = input.charAt(keyEnd);
286:
287: // '-Dkey ..'
288: if (cursor == ' ') {
289: tokenStart = keyEnd;
290: break findkey;
291: }
292:
293: // '-Dkey=..'
294: if (cursor == '=') {
295: break findkey;
296: }
297:
298: // keep looking
299: keyEnd++;
300: }
301:
302: // yay, finally a key
303: String key = StringUtils.substring(input, keyStart, keyEnd);
304:
305: // assume that there is no value following
306: int valueStart = keyEnd;
307: int valueEnd = keyEnd;
308:
309: // default value
310: String value = "true";
311:
312: // now find the value, but only if the current cursor is not a space
313: if (keyEnd < input.length() && cursor != ' ') {
314: // bump value start/end
315: valueStart = keyEnd + 1;
316: valueEnd = valueStart;
317:
318: // '-Dkey="..'
319: cursor = input.charAt(valueStart);
320: if (cursor == '"') {
321: // opening "
322: valueEnd = StringUtils.indexOf(input, '"',
323: ++valueStart);
324: } else {
325: // unquoted value
326: valueEnd = StringUtils.indexOf(input, ' ',
327: valueStart);
328: }
329:
330: // no '"' or ' ' delimiter found - use the rest of the string
331: if (valueEnd == StringUtils.INDEX_NOT_FOUND) {
332: valueEnd = input.length();
333: }
334:
335: // create value
336: value = StringUtils.substring(input, valueStart,
337: valueEnd);
338: }
339:
340: // finally create key and value && loop again for next token
341: result.put(key, value);
342:
343: // start next search at end of value
344: tokenStart = valueEnd;
345: }
346:
347: return result;
348: }
349:
350: }
|