001package arcommon.persistens; 002 003import java.io.BufferedWriter; 004import java.io.File; 005import java.io.IOException; 006 007import arcommon.FileUtil; 008import arcommon.ReflectionUtil; 009import arcommon.Util; 010import arcommon.xml.XmlUtil; 011 012public class SettingsUtil { 013 private static final String XML_SETTINGS_EXTENSION = "xml"; 014 private static final String JAVA_SERIALIZATION_SETTINGS_EXTENSION = "dat"; 015 016 private static String settingsFileName = "Settings." + JAVA_SERIALIZATION_SETTINGS_EXTENSION; 017 private static boolean settingsFileNameSet = false; 018 public static boolean useXml = true; 019 public static boolean saveXmlOnlyIfChanged = true; 020 private static String originalSettingsContent; 021 public static boolean warnOnNotExist = true; 022 023 private static ISettings settings; 024 private static ISettings defaultSettings; 025 private static Class<? extends ISettings> defaultSettingsClass; 026 027 public static String getSettingsFileName() { 028 return settingsFileName; 029 } 030 031 public static void setSettingsFileName(String psettingsFileName) { 032 if (psettingsFileName == null) { 033 throw new IllegalArgumentException("psettingsFileName == null"); 034 } 035 if (settingsFileNameSet) { 036 throw new RuntimeException("settingsFileName has already been set to \"" + settingsFileName + "\""); 037 } 038 settingsFileName = psettingsFileName; 039 settingsFileNameSet = true; 040 } 041 042 public static ISettings load() { 043 if (settings == null && !loadLocal()) { 044 if (defaultSettings == null && defaultSettingsClass == null) { 045 throw new RuntimeException("defaultSettings (and defaultSettingsClass) is null. Call setDefaultSettings()!"); 046 } 047 if (defaultSettingsClass != null) { 048 defaultSettings = ReflectionUtil.createInstanceDefaultConstructor(defaultSettingsClass); 049 } 050 settings = defaultSettings; 051 } 052 return settings; 053 } 054 055 public static void setDefaultSettings(ISettings pdefaultSettings) { 056 if (pdefaultSettings == null) { 057 throw new IllegalArgumentException("pdefaultSettings == null"); 058 } 059 if (defaultSettings != null) { 060 throw new RuntimeException("defaultSettings has already been set to " + defaultSettings); 061 } 062 if (defaultSettingsClass != null) { 063 throw new RuntimeException("defaultSettingsClass has already been set to " + defaultSettingsClass); 064 } 065 defaultSettings = pdefaultSettings; 066 } 067 068 public static void setDefaultSettingsClass(Class<? extends ISettings> pdefaultSettingsClass) { 069 if (pdefaultSettingsClass == null) { 070 throw new IllegalArgumentException("pdefaultSettingsClass == null"); 071 } 072 if (defaultSettings != null) { 073 throw new RuntimeException("defaultSettings has already been set to " + defaultSettings); 074 } 075 if (defaultSettingsClass != null) { 076 throw new RuntimeException("defaultSettingsClass has already been set to " + defaultSettingsClass); 077 } 078 defaultSettingsClass = pdefaultSettingsClass; 079 } 080 081 public static ISettings reload() { 082 settings = null; 083 return load(); 084 } 085 086 private static String calculateOldFileName() { // TODO Remove when all old settings files have been deleted. 087 String tempFileName = settingsFileName.substring(0, settingsFileName.length() - XML_SETTINGS_EXTENSION.length()); 088 tempFileName += JAVA_SERIALIZATION_SETTINGS_EXTENSION; 089 return tempFileName; 090 } 091 092 private static boolean loadLocal() { 093 if (!new File(settingsFileName).exists()) { 094 if (warnOnNotExist) { 095 Util.printMessageWithSourceLine("!new File(" + settingsFileName + ").exists()"); 096 } 097 if (useXml && settingsFileName.endsWith(XML_SETTINGS_EXTENSION)) { 098 String tempFileName = calculateOldFileName(); 099 if (!new File(tempFileName).exists()) { 100 if (warnOnNotExist) { 101 Util.printMessageWithSourceLine("!new File(" + tempFileName + ").exists()"); 102 } 103 } else { 104 settings = (ISettings)SerializableUtil.loadObjectFromFile(tempFileName); 105 return settings != null; 106 } 107 } 108 return false; 109 } 110 111 if (useXml) { 112 if (saveXmlOnlyIfChanged) { 113 originalSettingsContent = FileUtil.readFile(settingsFileName, XmlUtil.XML_ENCODING); 114 settings = (ISettings)XmlUtil.xmlStringToObject(originalSettingsContent); 115 } else { 116 settings = (ISettings)SerializableUtil.loadObjectFromFileAsXml(settingsFileName); 117 } 118 } else { 119 settings = (ISettings)SerializableUtil.loadObjectFromFile(settingsFileName); 120 } 121 122 return settings != null; 123 } 124 125 public static void saveUsingTempFileIfChanged() { 126 saveUsingTempFileIfChanged(settingsFileName); 127 } 128 129 public static void saveUsingTempFileIfChanged(String fileName) { 130 String currentSettingsXmlString = null; 131 if (useXml && saveXmlOnlyIfChanged) { 132 currentSettingsXmlString = XmlUtil.objectToXmlString(settings); 133 if (currentSettingsXmlString.equals(originalSettingsContent)) { 134 Util.printMessageWithSourceLine("Settings not changed => No save"); 135 return ; 136 } 137 } 138 139 final String currentSettingsXmlStringFinal = currentSettingsXmlString; 140 FileUtil.WriteUsingTempFileAction saveUsingTempFileAction = new FileUtil.WriteUsingTempFileAction() { 141 @Override 142 public void saveFile(String tempFileName, boolean append, String encoding) throws IOException { 143 if (currentSettingsXmlStringFinal != null) { 144 FileUtil.writeFile(tempFileName, currentSettingsXmlStringFinal, false, XmlUtil.XML_ENCODING); 145 } else { 146 save(tempFileName); 147 } 148 } 149 150 @Override 151 public void writeContentOfFile(BufferedWriter out) throws IOException { 152 throw new RuntimeException("Internal error. Should not be called"); 153 } 154 155 @Override 156 public boolean backupOldFile() { 157 return false; 158 } 159 }; 160 FileUtil.writeUsingTempFile(fileName, saveUsingTempFileAction); 161 } 162 163 public static void save() { 164 save(settingsFileName); 165 } 166 167 public static void save(String fileName) { 168 if (useXml) { 169 SerializableUtil.saveObjectToFileAsXML(fileName, settings); 170 171 String tempFileName = calculateOldFileName(); 172 File file = new File(tempFileName); 173 if (file.exists()) { 174 Util.printMessageWithSourceLine("new File(" + tempFileName + ").exists() => Delete"); 175 file.delete(); 176 } 177 } else { 178 SerializableUtil.saveObjectToFile(fileName, settings); 179 } 180 } 181}