1 /* 2 * Copyright (c) 2008-2019 Emmanuel Dupuy. 3 * This project is distributed under the GPLv3 license. 4 * This is a Copyleft license that gives the user the right to use, 5 * copy and modify the code freely for non-commercial purposes. 6 */ 7 8 package org.jd.gui.service.configuration; 9 10 import org.jd.gui.Constants; 11 import org.jd.gui.model.configuration.Configuration; 12 import org.jd.gui.service.platform.PlatformService; 13 import org.jd.gui.util.exception.ExceptionUtil; 14 15 import javax.swing.*; 16 import javax.xml.stream.*; 17 import java.awt.*; 18 import java.io.*; 19 import java.net.URL; 20 import java.util.*; 21 import java.util.List; 22 import java.util.jar.Manifest; 23 24 public class ConfigurationXmlPersisterProvider implements ConfigurationPersister { 25 protected static final String ERROR_BACKGROUND_COLOR = "JdGuiPreferences.errorBackgroundColor"; 26 protected static final String JD_CORE_VERSION = "JdGuiPreferences.jdCoreVersion"; 27 28 protected static final File FILE = getConfigFile(); 29 getConfigFile()30 protected static File getConfigFile() { 31 String configFilePath = System.getProperty(Constants.CONFIG_FILENAME); 32 33 if (configFilePath != null) { 34 File configFile = new File(configFilePath); 35 if (configFile.exists()) { 36 return configFile; 37 } 38 } 39 40 if (PlatformService.getInstance().isLinux()) { 41 // See: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html 42 String xdgConfigHome = System.getenv("XDG_CONFIG_HOME"); 43 if (xdgConfigHome != null) { 44 File xdgConfigHomeFile = new File(xdgConfigHome); 45 if (xdgConfigHomeFile.exists()) { 46 return new File(xdgConfigHomeFile, Constants.CONFIG_FILENAME); 47 } 48 } 49 50 File userConfigFile = new File(System.getProperty("user.home"), ".config"); 51 if (userConfigFile.exists()) { 52 return new File(userConfigFile, Constants.CONFIG_FILENAME); 53 } 54 } else if (PlatformService.getInstance().isWindows()) { 55 // See: http://blogs.msdn.com/b/patricka/archive/2010/03/18/where-should-i-store-my-data-and-configuration-files-if-i-target-multiple-os-versions.aspx 56 String roamingConfigHome = System.getenv("APPDATA"); 57 if (roamingConfigHome != null) { 58 File roamingConfigHomeFile = new File(roamingConfigHome); 59 if (roamingConfigHomeFile.exists()) { 60 return new File(roamingConfigHomeFile, Constants.CONFIG_FILENAME); 61 } 62 } 63 } 64 65 return new File(Constants.CONFIG_FILENAME); 66 } 67 68 @Override load()69 public Configuration load() { 70 // Default values 71 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 72 73 int w = (screenSize.width>Constants.DEFAULT_WIDTH) ? Constants.DEFAULT_WIDTH : screenSize.width; 74 int h = (screenSize.height>Constants.DEFAULT_HEIGHT) ? Constants.DEFAULT_HEIGHT : screenSize.height; 75 int x = (screenSize.width-w)/2; 76 int y = (screenSize.height-h)/2; 77 78 Configuration config = new Configuration(); 79 config.setMainWindowLocation(new Point(x, y)); 80 config.setMainWindowSize(new Dimension(w, h)); 81 config.setMainWindowMaximize(false); 82 83 String defaultLaf = System.getProperty("swing.defaultlaf"); 84 85 config.setLookAndFeel((defaultLaf != null) ? defaultLaf : UIManager.getSystemLookAndFeelClassName()); 86 87 File recentSaveDirectory = new File(System.getProperty("user.dir")); 88 89 config.setRecentLoadDirectory(recentSaveDirectory); 90 config.setRecentSaveDirectory(recentSaveDirectory); 91 92 if (FILE.exists()) { 93 try (FileInputStream fis = new FileInputStream(FILE)) { 94 XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(fis); 95 96 // Load values 97 String name = ""; 98 Stack<String> names = new Stack<>(); 99 List<File> recentFiles = new ArrayList<>(); 100 boolean maximize = false; 101 Map<String, String> preferences = config.getPreferences(); 102 103 while (reader.hasNext()) { 104 switch (reader.next()) { 105 case XMLStreamConstants.START_ELEMENT: 106 names.push(name); 107 name += '/' + reader.getLocalName(); 108 switch (name) { 109 case "/configuration/gui/mainWindow/location": 110 x = Integer.parseInt(reader.getAttributeValue(null, "x")); 111 y = Integer.parseInt(reader.getAttributeValue(null, "y")); 112 break; 113 case "/configuration/gui/mainWindow/size": 114 w = Integer.parseInt(reader.getAttributeValue(null, "w")); 115 h = Integer.parseInt(reader.getAttributeValue(null, "h")); 116 break; 117 } 118 break; 119 case XMLStreamConstants.END_ELEMENT: 120 name = names.pop(); 121 break; 122 case XMLStreamConstants.CHARACTERS: 123 switch (name) { 124 case "/configuration/recentFilePaths/filePath": 125 File file = new File(reader.getText().trim()); 126 if (file.exists()) { 127 recentFiles.add(file); 128 } 129 break; 130 case "/configuration/recentDirectories/loadPath": 131 file = new File(reader.getText().trim()); 132 if (file.exists()) { 133 config.setRecentLoadDirectory(file); 134 } 135 break; 136 case "/configuration/recentDirectories/savePath": 137 file = new File(reader.getText().trim()); 138 if (file.exists()) { 139 config.setRecentSaveDirectory(file); 140 } 141 break; 142 case "/configuration/gui/lookAndFeel": 143 config.setLookAndFeel(reader.getText().trim()); 144 break; 145 case "/configuration/gui/mainWindow/maximize": 146 maximize = Boolean.parseBoolean(reader.getText().trim()); 147 break; 148 default: 149 if (name.startsWith("/configuration/preferences/")) { 150 String key = name.substring("/configuration/preferences/".length()); 151 preferences.put(key, reader.getText().trim()); 152 } 153 break; 154 } 155 break; 156 } 157 } 158 159 if (recentFiles.size() > Constants.MAX_RECENT_FILES) { 160 // Truncate 161 recentFiles = recentFiles.subList(0, Constants.MAX_RECENT_FILES); 162 } 163 config.setRecentFiles(recentFiles); 164 165 if ((x >= 0) && (y >= 0) && (x + w < screenSize.width) && (y + h < screenSize.height)) { 166 // Update preferences 167 config.setMainWindowLocation(new Point(x, y)); 168 config.setMainWindowSize(new Dimension(w, h)); 169 config.setMainWindowMaximize(maximize); 170 } 171 172 reader.close(); 173 } catch (Exception e) { 174 assert ExceptionUtil.printStackTrace(e); 175 } 176 } 177 178 if (! config.getPreferences().containsKey(ERROR_BACKGROUND_COLOR)) { 179 config.getPreferences().put(ERROR_BACKGROUND_COLOR, "0xFF6666"); 180 } 181 182 config.getPreferences().put(JD_CORE_VERSION, getJdCoreVersion()); 183 184 return config; 185 } 186 getJdCoreVersion()187 protected String getJdCoreVersion() { 188 try { 189 Enumeration<URL> enumeration = ConfigurationXmlPersisterProvider.class.getClassLoader().getResources("META-INF/MANIFEST.MF"); 190 191 while (enumeration.hasMoreElements()) { 192 try (InputStream is = enumeration.nextElement().openStream()) { 193 String attribute = new Manifest(is).getMainAttributes().getValue("JD-Core-Version"); 194 if (attribute != null) { 195 return attribute; 196 } 197 } 198 } 199 } catch (IOException e) { 200 assert ExceptionUtil.printStackTrace(e); 201 } 202 203 return "SNAPSHOT"; 204 } 205 206 @Override save(Configuration configuration)207 public void save(Configuration configuration) { 208 Point l = configuration.getMainWindowLocation(); 209 Dimension s = configuration.getMainWindowSize(); 210 211 try (FileOutputStream fos = new FileOutputStream(FILE)) { 212 XMLStreamWriter writer = XMLOutputFactory.newInstance().createXMLStreamWriter(fos); 213 214 // Save values 215 writer.writeStartDocument(); 216 writer.writeCharacters("\n"); 217 writer.writeStartElement("configuration"); 218 writer.writeCharacters("\n\t"); 219 220 writer.writeStartElement("gui"); 221 writer.writeCharacters("\n\t\t"); 222 writer.writeStartElement("mainWindow"); 223 writer.writeCharacters("\n\t\t\t"); 224 writer.writeStartElement("location"); 225 writer.writeAttribute("x", String.valueOf(l.x)); 226 writer.writeAttribute("y", String.valueOf(l.y)); 227 writer.writeEndElement(); 228 writer.writeCharacters("\n\t\t\t"); 229 writer.writeStartElement("size"); 230 writer.writeAttribute("w", String.valueOf(s.width)); 231 writer.writeAttribute("h", String.valueOf(s.height)); 232 writer.writeEndElement(); 233 writer.writeCharacters("\n\t\t\t"); 234 writer.writeStartElement("maximize"); 235 writer.writeCharacters(String.valueOf(configuration.isMainWindowMaximize())); 236 writer.writeEndElement(); 237 writer.writeCharacters("\n\t\t"); 238 writer.writeEndElement(); 239 writer.writeCharacters("\n\t\t"); 240 writer.writeStartElement("lookAndFeel"); 241 writer.writeCharacters(configuration.getLookAndFeel()); 242 writer.writeEndElement(); 243 writer.writeCharacters("\n\t"); 244 writer.writeEndElement(); 245 writer.writeCharacters("\n\t"); 246 247 writer.writeStartElement("recentFilePaths"); 248 249 for (File recentFile : configuration.getRecentFiles()) { 250 writer.writeCharacters("\n\t\t"); 251 writer.writeStartElement("filePath"); 252 writer.writeCharacters(recentFile.getAbsolutePath()); 253 writer.writeEndElement(); 254 } 255 256 writer.writeCharacters("\n\t"); 257 writer.writeEndElement(); 258 writer.writeCharacters("\n\t"); 259 260 writer.writeStartElement("recentDirectories"); 261 writer.writeCharacters("\n\t\t"); 262 writer.writeStartElement("loadPath"); 263 writer.writeCharacters(configuration.getRecentLoadDirectory().getAbsolutePath()); 264 writer.writeEndElement(); 265 writer.writeCharacters("\n\t\t"); 266 writer.writeStartElement("savePath"); 267 writer.writeCharacters(configuration.getRecentSaveDirectory().getAbsolutePath()); 268 writer.writeEndElement(); 269 writer.writeCharacters("\n\t"); 270 writer.writeEndElement(); 271 writer.writeCharacters("\n\t"); 272 273 writer.writeStartElement("preferences"); 274 275 for (Map.Entry<String, String> preference : configuration.getPreferences().entrySet()) { 276 writer.writeCharacters("\n\t\t"); 277 writer.writeStartElement(preference.getKey()); 278 writer.writeCharacters(preference.getValue()); 279 writer.writeEndElement(); 280 } 281 282 writer.writeCharacters("\n\t"); 283 writer.writeEndElement(); 284 writer.writeCharacters("\n"); 285 286 writer.writeEndElement(); 287 writer.writeEndDocument(); 288 writer.close(); 289 } catch (Exception e) { 290 assert ExceptionUtil.printStackTrace(e); 291 } 292 } 293 } 294