/src/ibis/smartsockets/util/TypedProperties.java

https://github.com/interdroid/smartsockets · Java · 506 lines · 266 code · 78 blank · 162 comment · 67 complexity · fcd9d98e6a5b1bb7f2f028f39d83b800 MD5 · raw file

  1. /* $Id$ */
  2. package ibis.smartsockets.util;
  3. import java.io.PrintStream;
  4. import java.util.Enumeration;
  5. import java.util.Iterator;
  6. import java.util.Map;
  7. import java.util.Properties;
  8. /**
  9. * Utility to extract and check typed properties
  10. */
  11. public class TypedProperties extends Properties {
  12. private static final long serialVersionUID = 1L;
  13. public TypedProperties(Map<String,?> initialValues) {
  14. if (initialValues != null) {
  15. putAll(initialValues);
  16. }
  17. }
  18. public TypedProperties() {
  19. super();
  20. }
  21. public TypedProperties(Properties defaults) {
  22. super(defaults);
  23. }
  24. /**
  25. * Adds all properties to the current property set, possibly overwriting the
  26. * current ones. Unlike the default putAll method, this one also looks in
  27. * the nested property sets of the parameter.
  28. *
  29. * @param p
  30. * the properties to add.
  31. */
  32. public void putAll(Properties p) {
  33. for (Enumeration<?> e = p.propertyNames(); e.hasMoreElements();) {
  34. String key = (String) e.nextElement();
  35. String value = p.getProperty(key);
  36. setProperty(key, value);
  37. }
  38. }
  39. /**
  40. * Returns true if property <code>name</code> is defined and has a value
  41. * that is conventionally associated with 'true' (as in Ant): any of 1, on,
  42. * true, yes.
  43. *
  44. * @return true if property is defined and set
  45. * @param name
  46. * property name
  47. */
  48. public boolean booleanProperty(String name) {
  49. return booleanProperty(name, false);
  50. }
  51. /**
  52. * Returns true if property <code>name</code> has a value that is
  53. * conventionally associated with 'true' (as in Ant): any of 1, on, true,
  54. * yes. If the property is not defined, return the specified default value.
  55. *
  56. * @return true if property is defined and set
  57. * @param key
  58. * property name
  59. * @param defaultValue
  60. * the value that is returned if the property is absent
  61. */
  62. public boolean booleanProperty(String key, boolean defaultValue) {
  63. String value = getProperty(key);
  64. if (value != null) {
  65. return value.equals("1") || value.equals("on") || value.equals("")
  66. || value.equals("true") || value.equals("yes");
  67. }
  68. return defaultValue;
  69. }
  70. /**
  71. * Returns the integer value of property
  72. *
  73. * @return the integer value of property
  74. * @param key
  75. * property name
  76. * @throws NumberFormatException
  77. * if the property is undefined or not an integer
  78. */
  79. public int getIntProperty(String key) {
  80. String value = getProperty(key);
  81. if (value == null) {
  82. throw new NumberFormatException("property undefined: " + key);
  83. }
  84. try {
  85. return Integer.parseInt(value);
  86. } catch (NumberFormatException e) {
  87. throw new NumberFormatException("Integer expected for property "
  88. + key + ", not \"" + value + "\"");
  89. }
  90. }
  91. /**
  92. * Returns the integer value of property
  93. *
  94. * @return the integer value of property
  95. * @param key
  96. * property name
  97. * @param defaultValue
  98. * default value if the property is undefined
  99. * @throws NumberFormatException
  100. * if the property defined and not an integer
  101. */
  102. public int getIntProperty(String key, int defaultValue) {
  103. String value = getProperty(key);
  104. if (value == null) {
  105. return defaultValue;
  106. }
  107. try {
  108. return Integer.parseInt(value);
  109. } catch (NumberFormatException e) {
  110. throw new NumberFormatException("Integer expected for property "
  111. + key + ", not \"" + value + "\"");
  112. }
  113. }
  114. /**
  115. * Returns the long value of property
  116. *
  117. * @return the long value of property
  118. * @param key
  119. * property name
  120. * @throws NumberFormatException
  121. * if the property is undefined or not an long
  122. */
  123. public long getLongProperty(String key) {
  124. String value = getProperty(key);
  125. if (value == null) {
  126. throw new NumberFormatException("property undefined: " + key);
  127. }
  128. try {
  129. return Long.parseLong(value);
  130. } catch (NumberFormatException e) {
  131. throw new NumberFormatException("Long expected for property " + key
  132. + ", not \"" + value + "\"");
  133. }
  134. }
  135. /**
  136. * Returns the long value of property
  137. *
  138. * @return the long value of property
  139. * @param key
  140. * property name
  141. * @param defaultValue
  142. * default value if the property is undefined
  143. * @throws NumberFormatException
  144. * if the property defined and not an Long
  145. */
  146. public long getLongProperty(String key, long defaultValue) {
  147. String value = getProperty(key);
  148. if (value == null) {
  149. return defaultValue;
  150. }
  151. try {
  152. return Long.parseLong(value);
  153. } catch (NumberFormatException e) {
  154. throw new NumberFormatException("Long expected for property " + key
  155. + ", not \"" + value + "\"");
  156. }
  157. }
  158. /**
  159. * Returns the short value of property
  160. *
  161. * @return the short value of property
  162. * @param key
  163. * property name
  164. * @throws NumberFormatException
  165. * if the property is undefined or not an short
  166. */
  167. public short getShortProperty(String key) {
  168. String value = getProperty(key);
  169. if (value == null) {
  170. throw new NumberFormatException("property undefined: " + key);
  171. }
  172. try {
  173. return Short.parseShort(value);
  174. } catch (NumberFormatException e) {
  175. throw new NumberFormatException("Short expected for property "
  176. + key + ", not \"" + value + "\"");
  177. }
  178. }
  179. /**
  180. * Returns the short value of property
  181. *
  182. * @return the short value of property
  183. * @param key
  184. * property name
  185. * @param defaultValue
  186. * default value if the property is undefined
  187. * @throws NumberFormatException
  188. * if the property defined and not an Short
  189. */
  190. public short getShortProperty(String key, short defaultValue) {
  191. String value = getProperty(key);
  192. if (value == null) {
  193. return defaultValue;
  194. }
  195. try {
  196. return Short.parseShort(value);
  197. } catch (NumberFormatException e) {
  198. throw new NumberFormatException("Short expected for property "
  199. + key + ", not \"" + value + "\"");
  200. }
  201. }
  202. /**
  203. * Returns the long value of a size property. Valid values for the property
  204. * are a long, a long followed by K, a long followed by M or a long followed
  205. * by G. Size modifiers multiply the value by 1024, 1024^2 and 1024^3
  206. * respectively.
  207. *
  208. * @return the size value of property
  209. * @param key
  210. * property name
  211. * @throws NumberFormatException
  212. * if the property is undefined or not a valid size
  213. */
  214. public long getSizeProperty(String key) {
  215. String value = getProperty(key);
  216. if (value == null) {
  217. throw new NumberFormatException("property undefined: " + key);
  218. }
  219. return getSizeProperty(key, 0);
  220. }
  221. /**
  222. * Returns the long value of a size property. Valid values for the property
  223. * are a long, a long followed by K, a long followed by M or a long followed
  224. * by G. Size modifiers multiply the value by 1024, 1024^2 and 1024^3
  225. * respectively. returns the default value if the property is undefined
  226. *
  227. * @return the size value of property
  228. * @param key
  229. * property name
  230. * @throws NumberFormatException
  231. * if the property is not a valid size
  232. */
  233. public long getSizeProperty(String key, long defaultValue) {
  234. String value = getProperty(key);
  235. if (value == null) {
  236. return defaultValue;
  237. }
  238. try {
  239. if (value.endsWith("G") || value.endsWith("g")) {
  240. return Long.parseLong(value.substring(0, value.length() - 1)) * 1024 * 1024 * 1024;
  241. }
  242. if (value.endsWith("M") || value.endsWith("m")) {
  243. return Long.parseLong(value.substring(0, value.length() - 1)) * 1024 * 1024;
  244. }
  245. if (value.endsWith("K") || value.endsWith("k")) {
  246. return Long.parseLong(value.substring(0, value.length() - 1)) * 1024;
  247. }
  248. return Long.parseLong(value);
  249. } catch (NumberFormatException e) {
  250. throw new NumberFormatException(
  251. "Long[G|g|M|m|K|k] expected for property " + key
  252. + ", not \"" + value + "\"");
  253. }
  254. }
  255. public String[] getStringList(String key) {
  256. return getStringList(key, ",", new String[0]);
  257. }
  258. public String[] getStringList(String key, String delim) {
  259. return getStringList(key, delim, new String[0]);
  260. }
  261. public String[] getStringList(String key, String delim,
  262. String[] defaultValue) {
  263. String value = getProperty(key);
  264. if (value == null) {
  265. return defaultValue;
  266. }
  267. return value.split(delim);
  268. }
  269. /**
  270. * Returns true if property name is defined and has a string value that
  271. * equals match.
  272. *
  273. * @return true if property is defined and equals match
  274. * @param key
  275. * property name
  276. * @param match
  277. * value to be matched
  278. */
  279. public boolean stringPropertyMatch(String key, String match) {
  280. String value = getProperty(key);
  281. return value != null && value.equals(match);
  282. }
  283. private static boolean contains(String[] list, String element) {
  284. if (list == null) {
  285. return false;
  286. }
  287. for (int i = 0; i < list.length; i++) {
  288. if (element.equalsIgnoreCase(list[i])) {
  289. return true;
  290. }
  291. }
  292. return false;
  293. }
  294. /**
  295. * Returns true if the given string starts with one of the given prefixes
  296. */
  297. private static boolean startsWith(String string, String[] prefixes) {
  298. if (prefixes == null) {
  299. return false;
  300. }
  301. for (int i = 0; i < prefixes.length; i++) {
  302. if (string.startsWith(prefixes[i])) {
  303. return true;
  304. }
  305. }
  306. return false;
  307. }
  308. /**
  309. * Checks all properties with the given prefix for validity.
  310. *
  311. * @return a Property object containing all unrecognized properties.
  312. * @param prefix
  313. * the prefix that should be checked
  314. * @param validKeys
  315. * the set of valid keys within the given prefix
  316. * @param validPrefixes
  317. * if a propery starts with one of these prefixes, it is declared
  318. * valid
  319. * @param printWarning
  320. * if true, a warning is printed to standard error for each
  321. * unknown property
  322. */
  323. public TypedProperties checkProperties(String prefix, String[] validKeys,
  324. String[] validPrefixes, boolean printWarning) {
  325. TypedProperties result = new TypedProperties();
  326. if (prefix == null) {
  327. prefix = "";
  328. }
  329. Iterator<Map.Entry<Object,Object>> iterator = entrySet().iterator();
  330. while (iterator.hasNext()) {
  331. Map.Entry<Object,Object> entry = iterator.next();
  332. String key = (String) entry.getKey();
  333. String value = (String) entry.getValue();
  334. if (key.startsWith(prefix)) {
  335. String suffix = key.substring(prefix.length());
  336. if (!startsWith(suffix, validPrefixes)
  337. && !contains(validKeys, suffix)) {
  338. if (printWarning) {
  339. System.err.println("Warning, unknown property: " + key
  340. + " with value: " + value);
  341. }
  342. result.put(key, value);
  343. }
  344. }
  345. }
  346. return result;
  347. }
  348. /**
  349. * Returns all properties who's key start with a certain prefix.
  350. *
  351. * @return a Property object containing all matching properties.
  352. * @param prefix
  353. * the desired prefix
  354. * @param removePrefix
  355. * should the prefix be removed from the property name ?
  356. */
  357. public TypedProperties filter(String prefix, boolean removePrefix,
  358. boolean removeProperties) {
  359. TypedProperties result = new TypedProperties();
  360. if (prefix == null) {
  361. prefix = "";
  362. }
  363. for (Enumeration<?> e = propertyNames(); e.hasMoreElements();) {
  364. String key = (String) e.nextElement();
  365. if (key.startsWith(prefix)) {
  366. String value = getProperty(key);
  367. if (removePrefix) {
  368. result.put(key.substring(prefix.length()), value);
  369. } else {
  370. result.put(key, value);
  371. }
  372. if (removeProperties) {
  373. remove(key);
  374. }
  375. }
  376. }
  377. return result;
  378. }
  379. public TypedProperties filter(String prefix) {
  380. return filter(prefix, false, false);
  381. }
  382. /**
  383. * Prints properties (including default properties) to a stream.
  384. *
  385. * @param out
  386. * The stream to write output to.
  387. * @param prefix
  388. * Only print properties which start with the given prefix. If
  389. * null, will print all properties
  390. */
  391. public void printProperties(PrintStream out, String prefix) {
  392. if (prefix == null) {
  393. prefix = "";
  394. }
  395. for (Enumeration<?> e = propertyNames(); e.hasMoreElements();) {
  396. String key = (String) e.nextElement();
  397. String value = getProperty(key);
  398. if (key.toLowerCase().startsWith(prefix.toLowerCase())) {
  399. out.println(key + " = " + value);
  400. }
  401. }
  402. }
  403. public String toVerboseString() {
  404. String result = "";
  405. for (Enumeration<?> e = propertyNames(); e.hasMoreElements();) {
  406. String key = (String) e.nextElement();
  407. String value = getProperty(key);
  408. result += key + " = " + value + "\n";
  409. }
  410. return result;
  411. }
  412. @Override
  413. public boolean equals(Object object) {
  414. if (!(object instanceof TypedProperties)) {
  415. return false;
  416. }
  417. TypedProperties other = (TypedProperties) object;
  418. for (Enumeration<?> e = propertyNames(); e.hasMoreElements();) {
  419. String key = (String) e.nextElement();
  420. String value = getProperty(key);
  421. String otherValue = other.getProperty(key);
  422. if (otherValue == null || !otherValue.equals(value)) {
  423. return false;
  424. }
  425. }
  426. return true;
  427. }
  428. }