1 package net.myvietnam.mvncore.configuration; 2 3 56 57 import java.util.ArrayList ; 58 import java.util.Collection ; 59 import java.util.Iterator ; 60 import java.util.List ; 61 import java.util.NoSuchElementException ; 62 import java.util.Properties ; 63 import java.util.StringTokenizer ; 64 import java.util.Vector ; 65 import org.apache.commons.logging.Log; 66 import org.apache.commons.logging.LogFactory; 67 68 77 public abstract class AbstractConfiguration implements Configuration 78 { 79 80 private static final int INITIAL_LIST_SIZE = 2; 81 82 private static Log log = LogFactory.getLog(AbstractConfiguration.class); 83 86 protected Configuration defaults = null; 87 88 89 protected static final String START_TOKEN = "${"; 90 91 protected static final String END_TOKEN = "}"; 92 93 96 public AbstractConfiguration() 97 { 98 } 99 100 106 public AbstractConfiguration(Configuration defaults) 107 { 108 this(); 109 this.defaults = defaults; 110 } 111 112 129 public void addProperty(String key, Object token) 130 { 131 if (token instanceof String ) 132 { 133 for(Iterator it = processString((String ) token).iterator(); 134 it.hasNext();) 135 { 136 addPropertyDirect(key, it.next()); 137 } 138 } 139 else if (token instanceof Collection ) 140 { 141 for (Iterator it = ((Collection ) token).iterator(); it.hasNext();) 142 { 143 addProperty(key, it.next()); 144 } 145 } 146 else 147 { 148 addPropertyDirect(key, token); 149 } 150 } 151 152 160 protected abstract Object getPropertyDirect(String key); 161 162 169 protected abstract void addPropertyDirect(String key, Object obj); 170 171 178 protected String interpolate(String base) 179 { 180 return (interpolateHelper(base, null)); 181 } 182 183 197 protected String interpolateHelper(String base, List priorVariables) 198 { 199 if (base == null) 200 { 201 return null; 202 } 203 204 if (priorVariables == null) 207 { 208 priorVariables = new ArrayList (); 209 priorVariables.add(base); 210 } 211 212 int begin = -1; 213 int end = -1; 214 int prec = 0 - END_TOKEN.length(); 215 String variable = null; 216 StringBuffer result = new StringBuffer (); 217 218 while (((begin = base.indexOf(START_TOKEN, prec + END_TOKEN.length())) 220 > -1) 221 && ((end = base.indexOf(END_TOKEN, begin)) > -1)) 222 { 223 result.append(base.substring(prec + END_TOKEN.length(), begin)); 224 variable = base.substring(begin + START_TOKEN.length(), end); 225 226 if (priorVariables.contains(variable)) 228 { 229 String initialBase = priorVariables.remove(0).toString(); 230 priorVariables.add(variable); 231 StringBuffer priorVariableSb = new StringBuffer (); 232 233 for (Iterator it = priorVariables.iterator(); it.hasNext();) 236 { 237 priorVariableSb.append(it.next()); 238 if (it.hasNext()) 239 { 240 priorVariableSb.append("->"); 241 } 242 } 243 244 throw new IllegalStateException ( 245 "infinite loop in property interpolation of " 246 + initialBase 247 + ": " 248 + priorVariableSb.toString()); 249 } 250 else 252 { 253 priorVariables.add(variable); 254 } 255 256 Object value = getProperty(variable); 258 if (value != null) 259 { 260 result.append(interpolateHelper(value.toString(), 261 priorVariables)); 262 263 priorVariables.remove(priorVariables.size() - 1); 268 } 269 else if (defaults != null && defaults.getString(variable, 270 null) != null) 271 { 272 result.append(defaults.getString(variable)); 273 } 274 else 275 { 276 result.append(START_TOKEN).append(variable).append(END_TOKEN); 278 } 279 prec = end; 280 } 281 result.append(base.substring(prec + END_TOKEN.length(), base.length())); 282 283 return result.toString(); 284 } 285 286 296 protected List processString(String token) 297 { 298 List retList = new ArrayList (INITIAL_LIST_SIZE); 299 300 if (token.indexOf(PropertiesTokenizer.DELIMITER) > 0) 301 { 302 PropertiesTokenizer tokenizer = 303 new PropertiesTokenizer(token); 304 305 while (tokenizer.hasMoreTokens()) 306 { 307 String value = tokenizer.nextToken(); 308 retList.add(value); 309 } 310 } 311 else 312 { 313 retList.add(token); 314 } 315 316 return retList; 322 } 323 324 325 337 protected final Boolean testBoolean(String value) 338 { 339 String s = value.toLowerCase(); 340 341 if (s.equals("true") || s.equals("on") || s.equals("yes")) 342 { 343 return Boolean.TRUE; 344 } 345 else if (s.equals("false") || s.equals("off") || s.equals("no")) 346 { 347 return Boolean.FALSE; 348 } 349 else 350 { 351 return null; 352 } 353 } 354 355 364 public Configuration subset(String prefix) 365 { 366 BaseConfiguration c = new BaseConfiguration(); 367 Iterator keys = this.getKeys(); 368 boolean validSubset = false; 369 370 while (keys.hasNext()) 371 { 372 Object key = keys.next(); 373 374 if (key instanceof String && ((String ) key).startsWith(prefix)) 375 { 376 if (!validSubset) 377 { 378 validSubset = true; 379 } 380 381 String newKey = null; 382 383 388 if (((String ) key).length() == prefix.length()) 389 { 390 newKey = prefix; 391 } 392 else 393 { 394 newKey = ((String ) key).substring(prefix.length() + 1); 395 } 396 397 403 Object value = getProperty((String ) key); 404 if (value instanceof String ) 405 { 406 c.addPropertyDirect(newKey, interpolate((String ) value)); 407 } 408 else 409 { 410 c.addProperty(newKey, value); 411 } 412 } 413 } 414 415 if (validSubset) 416 { 417 return c; 418 } 419 else 420 { 421 return null; 422 } 423 } 424 425 431 public abstract boolean isEmpty(); 432 433 441 public abstract boolean containsKey(String key); 442 443 451 public void setProperty(String key, Object value) 452 { 453 clearProperty(key); 454 addProperty(key, value); } 456 457 462 public abstract void clearProperty(String key); 463 464 470 public abstract Iterator getKeys(); 471 472 480 public Iterator getKeys(String prefix) 481 { 482 Iterator keys = getKeys(); 483 ArrayList matchingKeys = new ArrayList (); 484 485 while (keys.hasNext()) 486 { 487 Object key = keys.next(); 488 489 if (key instanceof String && ((String ) key).startsWith(prefix)) 490 { 491 matchingKeys.add(key); 492 } 493 } 494 return matchingKeys.iterator(); 495 } 496 497 512 public Properties getProperties(String key) 513 { 514 return getProperties(key, null); 515 } 516 517 532 public Properties getProperties(String key, Properties defaults) 533 { 534 537 String [] tokens = getStringArray(key); 538 539 542 Properties props = 543 (defaults == null ? new Properties () : new Properties (defaults)); 544 for (int i = 0; i < tokens.length; i++) 545 { 546 String token = tokens[i]; 547 int equalSign = token.indexOf('='); 548 if (equalSign > 0) 549 { 550 String pkey = token.substring(0, equalSign).trim(); 551 String pvalue = token.substring(equalSign + 1).trim(); 552 props.put(pkey, pvalue); 553 } 554 else if (tokens.length == 1 && "".equals(token)) 555 { 556 break; 559 } 560 else 561 { 562 throw new IllegalArgumentException ( 563 '\'' + token + "' does not contain an equals sign"); 564 } 565 } 566 return props; 567 } 568 569 576 public Object getProperty(String key) 577 { 578 Object o = getPropertyDirect(key); 580 581 if (o == null) 582 { 583 if (defaults != null) 586 { 587 o = defaults.getProperty(key); 588 } 589 } 590 591 if (o instanceof Container) 597 { 598 o = ((Container) o).asVector(); 599 } 600 return o; 601 } 602 603 615 public boolean getBoolean(String key) 616 { 617 Boolean b = getBoolean(key, (Boolean ) null); 618 if (b != null) 619 { 620 return b.booleanValue(); 621 } 622 else 623 { 624 throw new NoSuchElementException ( 625 '\'' + key + "' doesn't map to an existing object"); 626 } 627 } 628 629 640 public boolean getBoolean(String key, boolean defaultValue) 641 { 642 return getBoolean(key, new Boolean (defaultValue)).booleanValue(); 643 } 644 645 657 public Boolean getBoolean(String key, Boolean defaultValue) 658 { 659 Object value = resolveContainerStore(key); 660 661 if (value instanceof Boolean ) 662 { 663 return (Boolean ) value; 664 } 665 else if (value instanceof String ) 666 { 667 return testBoolean((String ) value); 668 } 669 else if (value == null) 670 { 671 if (defaults != null) 672 { 673 return defaults.getBoolean(key, defaultValue); 674 } 675 else 676 { 677 log.warn("Use Boolean default value for key '" + key + "' (" + defaultValue + ")"); 678 return defaultValue; 679 } 680 } 681 else 682 { 683 throw new ClassCastException ( 684 '\'' + key + "' doesn't map to a Boolean object"); 685 } 686 } 687 688 702 public byte getByte(String key) 703 { 704 Byte b = getByte(key, null); 705 if (b != null) 706 { 707 return b.byteValue(); 708 } 709 else 710 { 711 throw new NoSuchElementException ( 712 '\'' + key + " doesn't map to an existing object"); 713 } 714 } 715 716 729 public byte getByte(String key, byte defaultValue) 730 { 731 return getByte(key, new Byte (defaultValue)).byteValue(); 732 } 733 734 748 public Byte getByte(String key, Byte defaultValue) 749 { 750 Object value = resolveContainerStore(key); 751 752 if (value instanceof Byte ) 753 { 754 return (Byte ) value; 755 } 756 else if (value instanceof String ) 757 { 758 Byte b = new Byte ((String ) value); 759 return b; 760 } 761 else if (value == null) 762 { 763 if (defaults != null) 764 { 765 return defaults.getByte(key, defaultValue); 766 } 767 else 768 { 769 log.warn("Use Byte default value for key '" + key + "' (" + defaultValue + ")"); 770 return defaultValue; 771 } 772 } 773 else 774 { 775 throw new ClassCastException ( 776 '\'' + key + "' doesn't map to a Byte object"); 777 } 778 } 779 780 794 public double getDouble(String key) 795 { 796 Double d = getDouble(key, null); 797 if (d != null) 798 { 799 return d.doubleValue(); 800 } 801 else 802 { 803 throw new NoSuchElementException ( 804 '\'' + key + "' doesn't map to an existing object"); 805 } 806 } 807 808 821 public double getDouble(String key, double defaultValue) 822 { 823 return getDouble(key, new Double (defaultValue)).doubleValue(); 824 } 825 826 840 public Double getDouble(String key, Double defaultValue) 841 { 842 Object value = resolveContainerStore(key); 843 844 if (value instanceof Double ) 845 { 846 return (Double ) value; 847 } 848 else if (value instanceof String ) 849 { 850 Double d = new Double ((String ) value); 851 return d; 852 } 853 else if (value == null) 854 { 855 if (defaults != null) 856 { 857 return defaults.getDouble(key, defaultValue); 858 } 859 else 860 { 861 log.warn("Use Double default value for key '" + key + "' (" + defaultValue + ")"); 862 return defaultValue; 863 } 864 } 865 else 866 { 867 throw new ClassCastException ( 868 '\'' + key + "' doesn't map to a Double object"); 869 } 870 } 871 872 886 public float getFloat(String key) 887 { 888 Float f = getFloat(key, null); 889 if (f != null) 890 { 891 return f.floatValue(); 892 } 893 else 894 { 895 throw new NoSuchElementException ( 896 '\'' + key + "' doesn't map to an existing object"); 897 } 898 } 899 900 913 public float getFloat(String key, float defaultValue) 914 { 915 return getFloat(key, new Float (defaultValue)).floatValue(); 916 } 917 918 932 public Float getFloat(String key, Float defaultValue) 933 { 934 Object value = resolveContainerStore(key); 935 936 if (value instanceof Float ) 937 { 938 return (Float ) value; 939 } 940 else if (value instanceof String ) 941 { 942 Float f = new Float ((String ) value); 943 return f; 944 } 945 else if (value == null) 946 { 947 if (defaults != null) 948 { 949 return defaults.getFloat(key, defaultValue); 950 } 951 else 952 { 953 log.warn("Use Float default value for key '" + key + "' (" + defaultValue + ")"); 954 return defaultValue; 955 } 956 } 957 else 958 { 959 throw new ClassCastException ( 960 '\'' + key + "' doesn't map to a Float object"); 961 } 962 } 963 964 978 public int getInt(String key) 979 { 980 Integer i = getInteger(key, null); 981 if (i != null) 982 { 983 return i.intValue(); 984 } 985 else 986 { 987 throw new NoSuchElementException ( 988 '\'' + key + "' doesn't map to an existing object"); 989 } 990 } 991 992 1005 public int getInt(String key, int defaultValue) 1006 { 1007 Integer i = getInteger(key, null); 1008 1009 if (i == null) 1010 { 1011 return defaultValue; 1012 } 1013 1014 return i.intValue(); 1015 } 1016 1017 1031 public Integer getInteger(String key, Integer defaultValue) 1032 { 1033 Object value = resolveContainerStore(key); 1034 1035 if (value instanceof Integer ) 1036 { 1037 return (Integer ) value; 1038 } 1039 else if (value instanceof String ) 1040 { 1041 Integer i = new Integer ((String ) value); 1042 return i; 1043 } 1044 else if (value == null) 1045 { 1046 if (defaults != null) 1047 { 1048 return defaults.getInteger(key, defaultValue); 1049 } 1050 else 1051 { 1052 log.warn("Use Integer default value for key '" + key + "' (" + defaultValue + ")"); 1053 return defaultValue; 1054 } 1055 } 1056 else 1057 { 1058 throw new ClassCastException ( 1059 '\'' + key + "' doesn't map to a Integer object"); 1060 } 1061 } 1062 1063 1077 public long getLong(String key) 1078 { 1079 Long l = getLong(key, null); 1080 if (l != null) 1081 { 1082 return l.longValue(); 1083 } 1084 else 1085 { 1086 throw new NoSuchElementException ( 1087 '\'' + key + "' doesn't map to an existing object"); 1088 } 1089 } 1090 1091 1104 public long getLong(String key, long defaultValue) 1105 { 1106 return getLong(key, new Long (defaultValue)).longValue(); 1107 } 1108 1109 1123 public Long getLong(String key, Long defaultValue) 1124 { 1125 Object value = resolveContainerStore(key); 1126 1127 if (value instanceof Long ) 1128 { 1129 return (Long ) value; 1130 } 1131 else if (value instanceof String ) 1132 { 1133 Long l = new Long ((String ) value); 1134 return l; 1135 } 1136 else if (value == null) 1137 { 1138 if (defaults != null) 1139 { 1140 return defaults.getLong(key, defaultValue); 1141 } 1142 else 1143 { 1144 log.warn("Use Long default value for key '" + key + "' (" + defaultValue + ")"); 1145 return defaultValue; 1146 } 1147 } 1148 else 1149 { 1150 throw new ClassCastException ( 1151 '\'' + key + "' doesn't map to a Long object"); 1152 } 1153 } 1154 1155 1169 public short getShort(String key) 1170 { 1171 Short s = getShort(key, null); 1172 if (s != null) 1173 { 1174 return s.shortValue(); 1175 } 1176 else 1177 { 1178 throw new NoSuchElementException ( 1179 '\'' + key + "' doesn't map to an existing object"); 1180 } 1181 } 1182 1183 1196 public short getShort(String key, short defaultValue) 1197 { 1198 return getShort(key, new Short (defaultValue)).shortValue(); 1199 } 1200 1201 1215 public Short getShort(String key, Short defaultValue) 1216 { 1217 Object value = resolveContainerStore(key); 1218 1219 if (value instanceof Short ) 1220 { 1221 return (Short ) value; 1222 } 1223 else if (value instanceof String ) 1224 { 1225 Short s = new Short ((String ) value); 1226 return s; 1227 } 1228 else if (value == null) 1229 { 1230 if (defaults != null) 1231 { 1232 return defaults.getShort(key, defaultValue); 1233 } 1234 else 1235 { 1236 log.warn("Use Short default value for key '" + key + "' (" + defaultValue + ")"); 1237 return defaultValue; 1238 } 1239 } 1240 else 1241 { 1242 throw new ClassCastException ( 1243 '\'' + key + "' doesn't map to a Short object"); 1244 } 1245 } 1246 1247 1259 public String getString(String key) 1260 { 1261 String s = getString(key, null); 1262 if (s != null) 1263 { 1264 return s; 1265 } 1266 else 1267 { 1268 throw new NoSuchElementException ( 1269 '\'' + key + "' doesn't map to an existing object"); 1270 } 1271 } 1272 1273 1284 public String getString(String key, String defaultValue) 1285 { 1286 Object value = resolveContainerStore(key); 1287 1288 if (value instanceof String ) 1289 { 1290 return interpolate((String ) value); 1291 } 1292 else if (value == null) 1293 { 1294 if (defaults != null) 1295 { 1296 return interpolate(defaults.getString(key, defaultValue)); 1297 } 1298 else 1299 { 1300 log.warn("Use String default value for key '" + key + "' (" + defaultValue + ")"); 1301 return interpolate(defaultValue); 1302 } 1303 } 1304 else 1305 { 1306 throw new ClassCastException ( 1307 '\'' + key + "' doesn't map to a String object"); 1308 } 1309 } 1310 1311 1322 public String [] getStringArray(String key) 1323 { 1324 Object value = getPropertyDirect(key); 1325 1326 String [] tokens; 1327 1328 if (value instanceof String ) 1329 { 1330 tokens = new String [1]; 1331 1332 tokens[0] = interpolate((String ) value); 1333 } 1334 else if (value instanceof Container) 1335 { 1336 tokens = new String [((Container) value).size()]; 1337 1338 for (int i = 0; i < tokens.length; i++) 1339 { 1340 tokens[i] = interpolate((String ) ((Container) value).get(i)); 1341 } 1342 } 1343 else if (value == null) 1344 { 1345 if (defaults != null) 1346 { 1347 tokens = defaults.getStringArray(key); 1348 } 1349 else 1350 { 1351 tokens = new String [0]; 1352 } 1353 } 1354 else 1355 { 1356 throw new ClassCastException ( 1357 '\'' + key + "' doesn't map to a String/Vector object"); 1358 } 1359 return tokens; 1360 } 1361 1362 1374 public Vector getVector(String key) 1375 { 1376 Vector v = getVector(key, null); 1377 if (v != null) 1378 { 1379 return v; 1380 } 1381 else 1382 { 1383 throw new NoSuchElementException ( 1384 '\'' + key + "' doesn't map to an existing object"); 1385 } 1386 } 1387 1388 1399 public Vector getVector(String key, Vector defaultValue) 1400 { 1401 Object value = getPropertyDirect(key); 1402 Vector v = null; 1403 1404 if (value instanceof String ) 1405 { 1406 v = new Vector (1); 1407 v.addElement(value); 1408 } 1409 else if (value instanceof Container) 1410 { 1411 v = ((Container) value).asVector(); 1412 } 1413 else if (value == null) 1414 { 1415 if (defaults != null) 1416 { 1417 v = defaults.getVector(key, defaultValue); 1418 } 1419 else 1420 { 1421 v = ((defaultValue == null) ? new Vector () : defaultValue); 1422 } 1423 } 1424 else 1425 { 1426 throw new ClassCastException ( 1427 '\'' 1428 + key 1429 + "' doesn't map to a Vector object: " 1430 + value 1431 + ", a " 1432 + value.getClass().getName()); 1433 } 1434 return v; 1435 } 1436 1437 1447 private Object resolveContainerStore(String key) 1448 { 1449 Object value = getPropertyDirect(key); 1450 if (value != null && value instanceof Container) 1451 { 1452 value = ((Container) value).get(0); 1453 } 1454 return value; 1455 } 1456 1457 1462 class PropertiesTokenizer extends StringTokenizer 1463 { 1464 1465 static final String DELIMITER = ","; 1466 1467 1472 public PropertiesTokenizer(String string) 1473 { 1474 super(string, DELIMITER); 1475 } 1476 1477 1482 public boolean hasMoreTokens() 1483 { 1484 return super.hasMoreTokens(); 1485 } 1486 1487 1492 public String nextToken() 1493 { 1494 StringBuffer buffer = new StringBuffer (); 1495 1496 while (hasMoreTokens()) 1497 { 1498 String token = super.nextToken(); 1499 if (token.endsWith("\\")) 1500 { 1501 buffer.append(token.substring(0, token.length() - 1)); 1502 buffer.append(DELIMITER); 1503 } 1504 else 1505 { 1506 buffer.append(token); 1507 break; 1508 } 1509 } 1510 return buffer.toString().trim(); 1511 } 1512 } 1514 1518 static class Container 1519 { 1520 1521 private List l = null; 1522 1523 1526 public Container() 1527 { 1528 l = new Vector (INITIAL_LIST_SIZE); 1529 } 1530 1531 1536 public void add(Object o) 1537 { 1538 l.add(o); 1539 } 1540 1541 1546 public int size() 1547 { 1548 return l.size(); 1549 } 1550 1551 1557 public Object get(int index) 1558 { 1559 return l.get(index); 1560 } 1561 1562 1567 public Iterator iterator() 1568 { 1569 return l.iterator(); 1570 } 1571 1572 1581 public Vector asVector() 1582 { 1583 Vector v = new Vector (l.size()); 1584 1585 for (Iterator it = l.iterator(); it.hasNext();) 1586 { 1587 v.add(it.next()); 1588 } 1589 return v; 1590 } 1591 } 1592} 1593 | Popular Tags |