1 30 31 package com.nightlabs.config; 32 33 import java.beans.XMLDecoder ; 34 import java.beans.XMLEncoder ; 35 import java.io.File ; 36 import java.io.FileInputStream ; 37 import java.io.FileOutputStream ; 38 import java.io.IOException ; 39 import java.io.InputStream ; 40 import java.net.URL ; 41 import java.util.ArrayList ; 42 import java.util.HashMap ; 43 import java.util.HashSet ; 44 import java.util.Iterator ; 45 import java.util.List ; 46 import java.util.Map ; 47 48 import org.apache.log4j.Level; 49 import org.apache.log4j.Logger; 50 51 import com.nightlabs.util.Utils; 52 53 54 67 public class Config 68 { 69 public static Logger LOGGER = Logger.getLogger(Config.class.getName()); 70 71 75 79 public static final char beforeIdentifier = '-'; 80 81 85 public static final char beforeMidfix = '-'; 86 87 91 public static final char beforeClassName = '-'; 92 93 96 private static Config sharedInstance; 97 98 103 private boolean multiFileMode; 104 105 109 public static final String ENCODING = "UTF-8"; 110 111 112 116 120 public static boolean isConfigExisting() 121 { 122 return sharedInstance != null; 123 } 124 125 142 public static Config createSharedInstance(String configFile, boolean loadConfFile, String configDir, boolean multiFileMode) 143 throws ConfigException 144 { 145 sharedInstance = new Config(configFile, loadConfFile, configDir, multiFileMode); 146 147 return sharedInstance; 148 } 149 150 162 public static Config createSharedInstance(String configFile, boolean loadConfFile, String configDir) 163 throws ConfigException 164 { 165 sharedInstance = new Config(configFile, loadConfFile, configDir); 166 167 return sharedInstance; 168 } 169 170 180 public static Config sharedInstance(boolean throwExceptionIfNotExisting) 181 { 182 if (sharedInstance==null && throwExceptionIfNotExisting) 183 throw new IllegalStateException ("Shared instance if Config was not yet created! You have to execute createSharedInstance() before using sharedInstance()!"); 184 185 return sharedInstance; 186 } 187 188 195 public static Config sharedInstance() 196 { 197 return sharedInstance(true); 198 } 199 200 201 205 206 209 private String configDir; 210 211 215 private String configFilename; 216 217 221 private HashMap configModules = new HashMap (); 222 223 227 private HashMap includedCfModsByFileName = new HashMap (); 228 229 233 private HashMap includedCfModsByCfMod = new HashMap (); 234 235 246 private HashSet _lazyConfigModules = null; 247 248 protected boolean isLazyConfigModule(ConfigModule cfMod) 249 { 250 if (_lazyConfigModules == null) 251 return false; 252 253 boolean res = _lazyConfigModules.contains(getConfigModuleIdentifyingName(cfMod)); 254 return res; 255 } 256 257 protected void registerLazyConfigModule(ConfigModule cfMod) 258 { 259 if (_lazyConfigModules == null) 260 _lazyConfigModules = new HashSet (); 261 262 _lazyConfigModules.add(getConfigModuleIdentifyingName(cfMod)); 263 } 264 265 269 275 public Config(InputStream configStream) 276 throws ConfigException 277 { 278 this.multiFileMode = false; 279 this.readFromInputStream(configStream); 280 } 281 282 public Config(String configFile, boolean loadConfFile, String configDir) 283 throws ConfigException 284 { 285 this(configFile, loadConfFile, configDir, true); 286 } 287 288 305 public Config(String configFile, boolean loadConfFile, String configDir, boolean multiFileMode) 306 throws ConfigException 307 { 308 try { 309 this.multiFileMode = multiFileMode; 310 311 316 this.setConfigDir(configDir); 317 configDir = this.configDir; 318 319 LOGGER.log(Level.INFO, "ProgRootDir = \""+this.configDir+"\""); 320 321 if (configFile == null || "".equals(configFile)) 322 configFile = configDir + "config.xml"; 323 else { 324 327 File cf = new File (configFile); 328 if (! cf.isAbsolute()) 329 cf = new File (configDir + configFile); 330 331 configFile = cf.getCanonicalPath(); 332 } 333 334 this.configFilename = configFile; 335 336 LOGGER.log(Level.INFO, "ConfigFile = \""+this.configFilename+"\""); 337 338 if (loadConfFile) 339 this.loadConfFile(); 340 } catch (ConfigException x) { 341 throw x; 342 } catch (Exception x) { 343 throw new ConfigException(x); 344 } 345 } 346 347 348 352 358 public String getConfigFilename() 359 { 360 return configFilename; 361 } 362 363 369 public void setConfigFilename(String configFilename) 370 { 371 this.configFilename = configFilename; 372 } 373 374 public String getConfigDir() 375 { 376 return this.configDir; 377 } 378 379 public void setConfigDir(String _configDir) 380 throws ConfigException 381 { 382 File fcfdir = new File (_configDir); 383 try { 384 this.configDir = Utils.addFinalSlash(fcfdir.getCanonicalPath()); 385 } catch (IOException e) { 386 throw new ConfigException(e); 387 } 388 } 389 390 395 396 400 406 public void loadConfFile() 407 throws ConfigException 408 { 409 loadConfFile(null); 410 } 411 412 424 public void loadConfFile(String includeFileMidfix) 425 throws ConfigException 426 { 427 try { 428 File cf = new File (configFilename); 429 if (!cf.exists()) { 430 this.configModules.clear(); 431 return; 432 } 433 434 FileInputStream fin = new FileInputStream (cf); 435 436 readFromInputStream(fin); 437 438 if (multiFileMode) { 439 ConfigIncludes configIncludes = (ConfigIncludes)getConfigModule(ConfigIncludes.class, false); 440 441 if (configIncludes == null) { 442 configIncludes = new ConfigIncludes(); 443 configIncludes._setConfig(this); 444 configIncludes.init(); 445 putConfigModule(configIncludes); 446 } 448 for (Iterator iterator = configIncludes.getConfigIncludes().iterator(); iterator.hasNext(); ) { 450 ConfigInclude configInclude = (ConfigInclude)iterator.next(); 451 String relativeIncludeFileNameOrg = configInclude.getIncludeFile(); 452 String relativeIncludeFileNameWithMidfix = createIncludeFileName( 453 relativeIncludeFileNameOrg, 454 null, 455 includeFileMidfix); 456 457 try { 458 459 File includeFile = new File (configDir, relativeIncludeFileNameWithMidfix); 461 462 if(!includeFile.exists()) { 463 URL url = null; 464 if(configInclude.getSearchClass() != null) { 466 url = Class.forName(configInclude.getSearchClass()). 467 getResource( 468 relativeIncludeFileNameWithMidfix); 469 } 470 if(url == null) { 471 url = Class.forName(configInclude.getIncludeClass()). 473 getResource( 474 relativeIncludeFileNameWithMidfix); 475 if (url == null) { 476 throw new ConfigException("Configuration file " 479 + relativeIncludeFileNameWithMidfix + " cannot be found. File does not exist in ConfigDir or class resource directory."); 480 } 481 } 482 includeFile = new File (url.getFile()); 483 } 484 485 fin = new FileInputStream (includeFile); 487 try { 488 490 ConfigModule cfMod; 493 XMLDecoder d = new XMLDecoder (fin); 494 try { 495 cfMod = (ConfigModule)d.readObject(); 496 cfMod.setChanged(false); 497 } finally { 498 d.close(); 499 } 500 501 cfMod._setConfig(this); 504 cfMod.init(); 505 this.putIncludedCfMod(relativeIncludeFileNameWithMidfix, cfMod); 506 this.configModules.put(getConfigModuleIdentifyingName(cfMod), cfMod); 507 508 } finally { 509 fin.close(); 510 } 511 512 } catch (Exception x) { 513 LOGGER.log( 514 Level.WARN, 515 "Unable to load config module file: "+relativeIncludeFileNameWithMidfix, 516 x); 517 } 518 519 } } 522 } catch (ConfigException x) { 523 throw x; 524 } catch (Exception x) { 525 throw new ConfigException(x); 526 } 527 } 528 529 537 public void saveConfFile() 538 throws ConfigException 539 { 540 saveConfFile(null, false); 541 } 542 543 551 public void saveConfFile(boolean forceSaveAllModules) 552 throws ConfigException 553 { 554 saveConfFile(null, forceSaveAllModules); 555 } 556 557 protected Object saveMutex = new Object (); 558 559 567 public void saveConfFile(String includeFileMidfix) 568 throws ConfigException 569 { 570 saveConfFile(includeFileMidfix, false); 571 } 572 573 591 public void saveConfFile(String includeFileMidfix, boolean forceSaveAllModules) 592 throws ConfigException 593 { 594 synchronized (saveMutex) { 595 LOGGER.info("Saving config with includeFileMidfix=\""+includeFileMidfix+"\""); 596 try { 597 List internalConfigModules = new ArrayList (this.configModules.size()); 598 599 ConfigIncludes configIncludes = null; 600 601 if (multiFileMode) { 602 configIncludes = (ConfigIncludes)getConfigModule(ConfigIncludes.class, false); 604 if (configIncludes == null) { 605 configIncludes = new ConfigIncludes(); 607 configIncludes._setConfig(this); 608 configIncludes.init(); 609 putConfigModule(configIncludes); 610 } 611 else { 612 configIncludes.getConfigIncludes().clear(); 614 } 615 } 616 617 HashMap changedIncludedConfigModules = new HashMap (); 621 622 for (Iterator it = configModules.entrySet().iterator(); it.hasNext(); ) { 626 Map.Entry entry = (Map.Entry )it.next(); 627 ConfigModule cfMod = (ConfigModule)entry.getValue(); 628 629 String relativeCfIncFileName = getIncludedCfModFileName(cfMod); 630 ConfigInclude cfInc = new ConfigInclude( 631 cfMod, relativeCfIncFileName 632 ); 633 634 if(!multiFileMode || relativeCfIncFileName == null) { 635 internalConfigModules.add(cfMod); 637 } 638 else { 639 640 if(!isLazyConfigModule(cfMod) || cfMod._isChanged() || forceSaveAllModules) 641 configIncludes.getConfigIncludes().add(new ConfigInclude(cfMod, relativeCfIncFileName)); 642 if(cfMod._isChanged() || forceSaveAllModules) { 643 changedIncludedConfigModules.put(relativeCfIncFileName, includedCfModsByFileName.get(relativeCfIncFileName)); 646 } 647 } 648 } 650 651 String tmpCf = configFilename+".new"; 653 654 FileOutputStream fout = new FileOutputStream (tmpCf); 655 656 XMLEncoder e = new XMLEncoder (fout); 660 e.writeObject(internalConfigModules); 661 e.close(); 662 663 fout.close(); 664 665 672 if(!changedIncludedConfigModules.isEmpty()) { 676 for (Iterator it = changedIncludedConfigModules.entrySet().iterator(); it.hasNext(); ) { 677 Map.Entry entry = (Map.Entry ) it.next(); 678 String includedConfigModuleFilename = (String ) entry.getKey(); 679 ConfigModule includedConfigModule = (ConfigModule) entry.getValue(); 680 681 LOGGER.debug("waiting for readLock of configModule \"" + includedConfigModuleFilename + "\"..."); 682 includedConfigModule.acquireReadLock(); 683 try { 684 LOGGER.debug("got readLock of configModule \"" + includedConfigModuleFilename + "\". Opening file..."); 685 686 File tmpCfModFile = new File (configDir, 687 includedConfigModuleFilename + ".new"); 688 689 fout = new FileOutputStream (tmpCfModFile); 690 e = new XMLEncoder (fout); 694 695 LOGGER.debug("opened file for configModule \"" + includedConfigModuleFilename + "\". writing object..."); 696 e.writeObject(includedConfigModule); 697 includedConfigModule.setChanged(false); 698 e.close(); 699 fout.close(); 700 701 LOGGER.debug("configModule \"" + includedConfigModuleFilename + "\" written."); 702 } finally { 703 includedConfigModule.releaseLock(); 704 } 705 LOGGER.debug("read lock of configModule \"" + includedConfigModuleFilename + "\" released."); 706 707 } } 716 717 718 File of = new File (configFilename); 720 of.delete(); 721 File nf = new File (tmpCf); 722 nf.renameTo(of); 723 724 if(!changedIncludedConfigModules.isEmpty()) { 726 for (Iterator it = changedIncludedConfigModules.keySet().iterator(); 727 it.hasNext(); ) { 728 String includedConfigModuleFilename = (String ) it.next(); 729 730 File tmpCfModFile = new File (configDir, 731 includedConfigModuleFilename + 732 ".new"); 733 File cfModFile = new File (configDir, includedConfigModuleFilename); 735 cfModFile.delete(); 736 tmpCfModFile.renameTo(cfModFile); 737 } } 739 740 } catch (Exception x) { 741 throw new ConfigException(x); 742 } 743 } } 745 746 747 751 762 public ConfigModule getConfigModule(Class configModuleClass, boolean throwExceptionIfNotExistent) 763 { 764 return getConfigModule(configModuleClass.getName(), throwExceptionIfNotExistent); 765 } 766 767 public ConfigModule getConfigModule(Class configModuleClass, String identifier, boolean throwExceptionIfNotExistent) 768 { 769 return getConfigModule(configModuleClass.getName(), identifier, throwExceptionIfNotExistent); 770 } 771 772 780 public ConfigModule getConfigModule(Class configModuleClass) 781 { 782 return getConfigModule(configModuleClass.getName()); 783 } 784 785 789 public ConfigModule getCreateConfigModule(Class configModuleClass) 790 throws ConfigException 791 { 792 return getCreateConfigModule(configModuleClass, null); 793 } 794 795 804 public ConfigModule createConfigModule(Class configModuleClass) 805 throws ConfigException 806 { 807 return createConfigModule(configModuleClass, null); 808 } 809 810 814 public ConfigModule getCreateConfigModule(Class configModuleClass, String identifier) 815 throws ConfigException 816 { 817 return createConfigModule(configModuleClass, identifier); 818 } 819 820 830 public ConfigModule createConfigModule(Class configModuleClass, String identifier) 831 throws ConfigException 832 { 833 try { 834 ConfigModule cfMod = (ConfigModule)configModules.get(getConfigModuleIdentifyingName(configModuleClass, identifier)); 835 if (cfMod == null) { 836 cfMod = (ConfigModule)configModuleClass.newInstance(); 837 cfMod._setConfig(this); 838 cfMod.setIdentifier(identifier); 839 cfMod.init(); 840 configModules.put(getConfigModuleIdentifyingName(cfMod), cfMod); 841 registerLazyConfigModule(cfMod); 842 } 843 844 if (multiFileMode) { 845 StringBuffer sbPrefix = new StringBuffer (configFilename); 846 int lastSlashPos = sbPrefix.lastIndexOf(File.separator); 847 sbPrefix.delete(0, lastSlashPos + 1); 848 int lastDotPos = sbPrefix.lastIndexOf("."); 849 String suffix = sbPrefix.substring(lastDotPos); 850 sbPrefix.delete(lastDotPos, sbPrefix.length()); 851 852 853 putIncludedCfMod( 854 sbPrefix.toString()+beforeClassName+ 855 getConfigModuleIdentifyingName(cfMod)+ 857 suffix, 858 cfMod 859 ); 860 } 862 return cfMod; 863 } catch (Throwable t) { 864 throw new ConfigException(t); 865 } 866 } 867 868 869 876 public ConfigModule getConfigModule(String configModuleClassName) 877 { 878 return getConfigModule(configModuleClassName, null); 879 } 880 public ConfigModule getConfigModule(String configModuleClassName, String identifier) 881 { 882 ConfigModule cfMod = (ConfigModule)configModules.get(getConfigModuleIdentifyingName(configModuleClassName, identifier)); 883 if (cfMod == null) 884 throw new ConfigModuleNotFoundException("No ConfigModule of type \""+configModuleClassName+"\" existent!"); 885 return cfMod; 886 } 887 public ConfigModule getConfigModule(String configModuleClassName, boolean throwExceptionIfNotExistent) 888 { 889 return getConfigModule(configModuleClassName, null, throwExceptionIfNotExistent); 890 } 891 public ConfigModule getConfigModule(String configModuleClassName, String identifier, boolean throwExceptionIfNotExistent) 892 { 893 ConfigModule cfMod = (ConfigModule)configModules.get(getConfigModuleIdentifyingName(configModuleClassName, identifier)); 894 if (cfMod == null && throwExceptionIfNotExistent) 895 throw new ConfigModuleNotFoundException("No ConfigModule of type \""+configModuleClassName+"\" existent!"); 896 return cfMod; 897 } 898 899 903 public void putConfigModule(ConfigModule configModule) 904 { 905 String cfModFileName = getIncludedCfModFileName(configModule); 906 if (cfModFileName != null) { 907 includedCfModsByFileName.remove(cfModFileName); 908 includedCfModsByCfMod.remove(configModule); 909 } 911 configModules.put(getConfigModuleIdentifyingName(configModule), configModule); 912 } 913 914 915 private void readFromInputStream(InputStream fin) 919 throws ConfigException 920 { 921 try { 922 XMLDecoder d = new XMLDecoder (fin); 926 List ls = (List )d.readObject(); 927 d.close(); 928 929 fin.close(); 930 931 935 this.configModules.clear(); 936 937 Iterator it = ls.iterator(); 938 while (it.hasNext()) { 939 ConfigModule cfMod = (ConfigModule)it.next(); 940 cfMod._setConfig(this); 941 cfMod.init(); 942 this.configModules.put(getConfigModuleIdentifyingName(cfMod), cfMod); 943 } 944 } catch (Exception x) { 945 throw new ConfigException(x); 946 } 947 } 948 949 protected void putIncludedCfMod(String relativeCfModFileName, ConfigModule cfMod) 950 { 951 includedCfModsByFileName.put(relativeCfModFileName, cfMod); 952 includedCfModsByCfMod.put(cfMod, relativeCfModFileName); 953 } 954 protected ConfigModule getIncludedCfMod(String relativeCfModFileName) 955 { 956 return (ConfigModule)includedCfModsByFileName.get(relativeCfModFileName); 957 } 958 protected String getIncludedCfModFileName(ConfigModule cfMod) 959 { 960 return (String )includedCfModsByCfMod.get(cfMod); 961 } 962 963 private static String createIncludeFileName(String orgFileName, String identifier, String midfix) 964 { 965 boolean haveIdentifier = identifier != null && !identifier.equals(""); 966 boolean haveMidfix = midfix != null && !midfix.equals(""); 967 968 if(!haveMidfix && !haveIdentifier) 969 return orgFileName; 970 971 StringBuffer sb = new StringBuffer (orgFileName); 972 int lastDotPos = sb.lastIndexOf("."); 973 String ext; 974 if(lastDotPos != -1) { 975 ext = sb.substring(lastDotPos); 976 sb.delete(lastDotPos, sb.length()); 977 } else { 978 ext = ""; 979 } 980 981 985 if(haveIdentifier) { 986 sb.append(beforeIdentifier); 987 sb.append(identifier); 988 sb.append(ext); 989 } 990 991 if(haveMidfix) { 992 sb.append(beforeMidfix); 993 sb.append(midfix); 994 sb.append(ext); 995 } 996 997 return sb.toString(); 998 } 999 1000 private static String getConfigModuleIdentifyingName(ConfigModule module) 1001 { 1002 return getConfigModuleIdentifyingName(module.getClass(), module.getIdentifier()); 1003 } 1004 private static String getConfigModuleIdentifyingName(Class moduleClass, String identifier) 1005 { 1006 return getConfigModuleIdentifyingName(moduleClass.getName(), identifier); 1007 } 1008 private static String getConfigModuleIdentifyingName(String moduleClassName, String identifier) 1009 { 1010 StringBuffer result = new StringBuffer (moduleClassName); 1011 if(identifier != null && !identifier.equals("")) { 1012 result.append(beforeIdentifier); 1013 result.append(identifier); 1014 } 1015 return result.toString(); 1016 } 1017 1018} | Popular Tags |