// ********************************************************************** // // Copyright (c) 2003-2010 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** package Ice; public final class PropertiesI implements Properties { static class PropertyValue { public PropertyValue(PropertyValue v) { value = v.value; used = v.used; } public PropertyValue(String v, boolean u) { value = v; used = u; } public String value; public boolean used; } public synchronized String getProperty(String key) { PropertyValue pv = _properties.get(key); if(pv != null) { pv.used = true; return pv.value; } else { return ""; } } public synchronized String getPropertyWithDefault(String key, String value) { PropertyValue pv = _properties.get(key); if(pv != null) { pv.used = true; return pv.value; } else { return value; } } public int getPropertyAsInt(String key) { return getPropertyAsIntWithDefault(key, 0); } public synchronized int getPropertyAsIntWithDefault(String key, int value) { PropertyValue pv = _properties.get(key); if(pv != null) { pv.used = true; try { return Integer.parseInt(pv.value); } catch(NumberFormatException ex) { Ice.Util.getProcessLogger().warning("numeric property " + key + " set to non-numeric value, defaulting to " + value); } } return value; } public String[] getPropertyAsList(String key) { return getPropertyAsListWithDefault(key, null); } public synchronized String[] getPropertyAsListWithDefault(String key, String[] value) { if(value == null) { value = new String[0]; } PropertyValue pv = _properties.get(key); if(pv != null) { pv.used = true; String[] result = IceUtilInternal.StringUtil.splitString(pv.value, ", \t\r\n"); if(result == null) { Ice.Util.getProcessLogger().warning("mismatched quotes in property " + key + "'s value, returning default value"); return value; } if(result.length == 0) { result = value; } return result; } else { return value; } } public synchronized java.util.Map<String, String> getPropertiesForPrefix(String prefix) { java.util.HashMap<String, String> result = new java.util.HashMap<String, String>(); for(java.util.Map.Entry<String, PropertyValue> p : _properties.entrySet()) { String key = p.getKey(); if(prefix.length() == 0 || key.startsWith(prefix)) { PropertyValue pv = p.getValue(); pv.used = true; result.put(key, pv.value); } } return result; } public void setProperty(String key, String value) { // // Trim whitespace // if(key != null) { key = key.trim(); } // // Check if the property is legal. // Logger logger = Ice.Util.getProcessLogger(); if(key == null || key.length() == 0) { throw new Ice.InitializationException("Attempt to set property with empty key"); } int dotPos = key.indexOf('.'); if(dotPos != -1) { String prefix = key.substring(0, dotPos); for(int i = 0; IceInternal.PropertyNames.validProps[i] != null; ++i) { String pattern = IceInternal.PropertyNames.validProps[i][0].pattern(); dotPos = pattern.indexOf('.'); // // Each top level prefix describes a non-empty namespace. Having a string without a // prefix followed by a dot is an error. // assert(dotPos != -1); String propPrefix = pattern.substring(0, dotPos - 1); if(!propPrefix.equals(prefix)) { continue; } boolean found = false; for(int j = 0; IceInternal.PropertyNames.validProps[i][j] != null && !found; ++j) { pattern = IceInternal.PropertyNames.validProps[i][j].pattern(); java.util.regex.Pattern pComp = java.util.regex.Pattern.compile(pattern); java.util.regex.Matcher m = pComp.matcher(key); found = m.matches(); if(found && IceInternal.PropertyNames.validProps[i][j].deprecated()) { logger.warning("deprecated property: " + key); if(IceInternal.PropertyNames.validProps[i][j].deprecatedBy() != null) { key = IceInternal.PropertyNames.validProps[i][j].deprecatedBy(); } } } if(!found) { logger.warning("unknown property: " + key); } } } synchronized(this) { // // Set or clear the property. // if(value != null && value.length() > 0) { PropertyValue pv = _properties.get(key); if(pv != null) { pv.value = value; } else { pv = new PropertyValue(value, false); } _properties.put(key, pv); } else { _properties.remove(key); } } } public synchronized String[] getCommandLineOptions() { String[] result = new String[_properties.size()]; int i = 0; for(java.util.Map.Entry<String, PropertyValue> p : _properties.entrySet()) { result[i++] = "--" + p.getKey() + "=" + p.getValue().value; } assert(i == result.length); return result; } public String[] parseCommandLineOptions(String pfx, String[] options) { if(pfx.length() > 0 && pfx.charAt(pfx.length() - 1) != '.') { pfx += '.'; } pfx = "--" + pfx; java.util.ArrayList<String> result = new java.util.ArrayList<String>(); for(String opt : options) { if(opt.startsWith(pfx)) { if(opt.indexOf('=') == -1) { opt += "=1"; } parseLine(opt.substring(2)); } else { result.add(opt); } } return result.toArray(new String[0]); } public String[] parseIceCommandLineOptions(String[] options) { String[] args = options; for(int i = 0; IceInternal.PropertyNames.clPropNames[i] != null; ++i) { args = parseCommandLineOptions(IceInternal.PropertyNames.clPropNames[i], args); } return args; } public void load(String file) { if(System.getProperty("os.name").startsWith("Windows") && file.startsWith("HKLM\\")) { String regQuery = "reg query " + file; try { java.lang.Process process = Runtime.getRuntime().exec(regQuery); process.waitFor(); if(process.exitValue() != 0) { InitializationException ie = new InitializationException(); ie.reason = "Could not read Windows registry key `" + file + "'"; throw ie; } java.io.InputStream is = process.getInputStream(); java.io.StringWriter sw = new java.io.StringWriter(); int c; while((c = is.read()) != -1) { sw.write(c); } String[] result = sw.toString().split("\n"); for(String line : result) { int pos = line.indexOf("REG_SZ"); if(pos != -1) { setProperty(line.substring(0, pos).trim(), line.substring(pos + 6, line.length()).trim()); continue; } pos = line.indexOf("REG_EXPAND_SZ"); if(pos != -1) { String name = line.substring(0, pos).trim(); line = line.substring(pos + 13, line.length()).trim(); while(true) { int start = line.indexOf("%", 0); int end = line.indexOf("%", start + 1); // // If there isn't more %var% break the loop // if(start == -1 || end == -1) { break; } String envKey = line.substring(start + 1, end); String envValue = System.getenv(envKey); if(envValue == null) { envValue = ""; } envKey = "%" + envKey + "%"; do { line = line.replace(envKey , envValue); } while(line.indexOf(envKey) != -1); } setProperty(name, line); continue; } } } catch(Ice.LocalException ex) { throw ex; } catch(Exception ex) { InitializationException ie = new InitializationException(); ie.reason = "Could not read Windows registry key `" + file + "'"; ie.initCause(ex); // Exception chaining throw ie; } } else { java.io.InputStream is = null; try { is = IceInternal.Util.openResource(getClass().getClassLoader(), file); if(is == null) { FileException fe = new FileException(); fe.path = file; throw fe; } java.io.InputStreamReader isr = new java.io.InputStreamReader(is, "UTF-8"); java.io.BufferedReader br = new java.io.BufferedReader(isr); parse(br); } catch(java.io.IOException ex) { FileException fe = new FileException(); fe.path = file; fe.initCause(ex); // Exception chaining throw fe; } finally { if(is != null) { try { is.close(); } catch(Throwable ex) { // Ignore. } } } } } public synchronized Properties _clone() { return new PropertiesI(this); } public synchronized java.util.List<String> getUnusedProperties() { java.util.List<String> unused = new java.util.ArrayList<String>(); for(java.util.Map.Entry<String, PropertyValue> p : _properties.entrySet()) { PropertyValue pv = p.getValue(); if(!pv.used) { unused.add(p.getKey()); } } return unused; } PropertiesI(PropertiesI props) { // // NOTE: we can't just do a shallow copy of the map as the map values // would otherwise be shared between the two PropertiesI object. // //_properties = new java.util.HashMap<String, PropertyValue>(props._properties); for(java.util.Map.Entry<String, PropertyValue> p : props._properties.entrySet()) { _properties.put(p.getKey(), new PropertyValue(p.getValue())); } } PropertiesI() { } PropertiesI(StringSeqHolder args, Properties defaults) { if(defaults != null) { _properties = new java.util.HashMap<String, PropertyValue>(((PropertiesI)defaults)._properties); } boolean loadConfigFiles = false; for(int i = 0; i < args.value.length; i++) { if(args.value[i].startsWith("--Ice.Config")) { String line = args.value[i]; if(line.indexOf('=') == -1) { line += "=1"; } parseLine(line.substring(2)); loadConfigFiles = true; String[] arr = new String[args.value.length - 1]; System.arraycopy(args.value, 0, arr, 0, i); if(i < args.value.length - 1) { System.arraycopy(args.value, i + 1, arr, i, args.value.length - i - 1); } args.value = arr; } } if(!loadConfigFiles) { // // If Ice.Config is not set, load from ICE_CONFIG (if set) // loadConfigFiles = !_properties.containsKey("Ice.Config"); } if(loadConfigFiles) { loadConfig(); } args.value = parseIceCommandLineOptions(args.value); } private void parse(java.io.BufferedReader in) { try { String line; while((line = in.readLine()) != null) { parseLine(line); } } catch(java.io.IOException ex) { SyscallException se = new SyscallException(); se.initCause(ex); // Exception chaining throw se; } } private static final int ParseStateKey = 0; private static final int ParseStateValue = 1; private void parseLine(String line) { String key = ""; String value = ""; int state = ParseStateKey; String whitespace = ""; String escapedspace = ""; boolean finished = false; for(int i = 0; i < line.length(); ++i) { char c = line.charAt(i); switch(state) { case ParseStateKey: { switch(c) { case '\\': if(i < line.length() - 1) { c = line.charAt(++i); switch(c) { case '\\': case '#': case '=': key += whitespace; whitespace = ""; key += c; break; case ' ': if(key.length() != 0) { whitespace += c; } break; default: key += whitespace; whitespace = ""; key += '\\'; key += c; break; } } else { key += whitespace; key += c; } break; case ' ': case '\t': case '\r': case '\n': if(key.length() != 0) { whitespace += c; } break; case '=': whitespace = ""; state = ParseStateValue; break; case '#': finished = true; break; default: key += whitespace; whitespace = ""; key += c; break; } break; } case ParseStateValue: { switch(c) { case '\\': if(i < line.length() - 1) { c = line.charAt(++i); switch(c) { case '\\': case '#': case '=': value += value.length() == 0 ? escapedspace : whitespace; whitespace = ""; escapedspace = ""; value += c; break; case ' ': whitespace += c; escapedspace += c; break; default: value += value.length() == 0 ? escapedspace : whitespace; whitespace = ""; escapedspace = ""; value += '\\'; value += c; break; } } else { value += value.length() == 0 ? escapedspace : whitespace; value += c; } break; case ' ': case '\t': case '\r': case '\n': if(value.length() != 0) { whitespace += c; } break; case '#': value += escapedspace; finished = true; break; default: value += value.length() == 0 ? escapedspace : whitespace; whitespace = ""; escapedspace = ""; value += c; break; } break; } } if(finished) { break; } } value += escapedspace; if((state == ParseStateKey && key.length() != 0) || (state == ParseStateValue && key.length() == 0)) { Ice.Util.getProcessLogger().warning("invalid config file entry: \"" + line + "\""); return; } else if(key.length() == 0) { return; } setProperty(key, value); } private void loadConfig() { String value = getProperty("Ice.Config"); if(value.length() == 0 || value.equals("1")) { try { value = System.getenv("ICE_CONFIG"); if(value == null) { value = ""; } } catch(java.lang.SecurityException ex) { value = ""; } } if(value.length() > 0) { for(String file : value.split(",")) { load(file); } } _properties.put("Ice.Config", new PropertyValue(value, true)); } private java.util.HashMap<String, PropertyValue> _properties = new java.util.HashMap<String, PropertyValue>(); }