Add option to exclude user directories from preferences export
This commit is contained in:
parent
7186aa6dd0
commit
db55a2f4f3
@ -381,6 +381,10 @@ PreferencesExporter.chooser.title = Export the Preferences File
|
|||||||
|
|
||||||
PreferencesImporter.chooser.title = Import a Preferences File
|
PreferencesImporter.chooser.title = Import a Preferences File
|
||||||
|
|
||||||
|
PreferencesOptionPanel.title = Export settings
|
||||||
|
PreferencesOptionPanel.checkbox.userDirectories = Export user directories
|
||||||
|
PreferencesOptionPanel.checkbox.userDirectories.ttip = If checked, user directories (possible sensitive information) will be exported.
|
||||||
|
|
||||||
! Welcome dialog
|
! Welcome dialog
|
||||||
welcome.dlg.title = Welcome to OpenRocket
|
welcome.dlg.title = Welcome to OpenRocket
|
||||||
welcome.dlg.lbl.thankYou = Thank you for downloading OpenRocket
|
welcome.dlg.lbl.thankYou = Thank you for downloading OpenRocket
|
||||||
|
@ -53,6 +53,7 @@ public abstract class Preferences implements ChangeSource {
|
|||||||
public static final String EXPORT_EVENT_COMMENTS = "ExportEventComments";
|
public static final String EXPORT_EVENT_COMMENTS = "ExportEventComments";
|
||||||
public static final String EXPORT_COMMENT_CHARACTER = "ExportCommentCharacter";
|
public static final String EXPORT_COMMENT_CHARACTER = "ExportCommentCharacter";
|
||||||
public static final String USER_LOCAL = "locale";
|
public static final String USER_LOCAL = "locale";
|
||||||
|
public static final String DEFAULT_DIRECTORY = "defaultDirectory";
|
||||||
|
|
||||||
public static final String PLOT_SHOW_POINTS = "ShowPlotPoints";
|
public static final String PLOT_SHOW_POINTS = "ShowPlotPoints";
|
||||||
|
|
||||||
@ -80,6 +81,7 @@ public abstract class Preferences implements ChangeSource {
|
|||||||
public static final String MARKER_STYLE_ICON = "MarkerStyleIcon";
|
public static final String MARKER_STYLE_ICON = "MarkerStyleIcon";
|
||||||
private static final String SHOW_MARKERS = "ShowMarkers";
|
private static final String SHOW_MARKERS = "ShowMarkers";
|
||||||
private static final String SHOW_ROCKSIM_FORMAT_WARNING = "ShowRocksimFormatWarning";
|
private static final String SHOW_ROCKSIM_FORMAT_WARNING = "ShowRocksimFormatWarning";
|
||||||
|
private static final String EXPORT_USER_DIRECTORIES = "ExportUserDirectories";
|
||||||
|
|
||||||
//Preferences related to 3D graphics
|
//Preferences related to 3D graphics
|
||||||
public static final String OPENGL_ENABLED = "OpenGLIsEnabled";
|
public static final String OPENGL_ENABLED = "OpenGLIsEnabled";
|
||||||
@ -231,7 +233,15 @@ public abstract class Preferences implements ChangeSource {
|
|||||||
public final void setShowRockSimFormatWarning(boolean check) {
|
public final void setShowRockSimFormatWarning(boolean check) {
|
||||||
this.putBoolean(SHOW_ROCKSIM_FORMAT_WARNING, check);
|
this.putBoolean(SHOW_ROCKSIM_FORMAT_WARNING, check);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final boolean getExportUserDirectories() {
|
||||||
|
return this.getBoolean(EXPORT_USER_DIRECTORIES, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setExportUserDirectories(boolean check) {
|
||||||
|
this.putBoolean(EXPORT_USER_DIRECTORIES, check);
|
||||||
|
}
|
||||||
|
|
||||||
public final double getDefaultMach() {
|
public final double getDefaultMach() {
|
||||||
return Application.getPreferences().getChoice(Preferences.DEFAULT_MACH_NUMBER, 0.9, 0.3);
|
return Application.getPreferences().getChoice(Preferences.DEFAULT_MACH_NUMBER, 0.9, 0.3);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
package net.sf.openrocket.gui.components;
|
||||||
|
|
||||||
|
import net.miginfocom.swing.MigLayout;
|
||||||
|
import net.sf.openrocket.l10n.Translator;
|
||||||
|
import net.sf.openrocket.startup.Application;
|
||||||
|
import net.sf.openrocket.startup.Preferences;
|
||||||
|
|
||||||
|
import javax.swing.BorderFactory;
|
||||||
|
import javax.swing.JCheckBox;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import java.awt.event.ItemEvent;
|
||||||
|
import java.awt.event.ItemListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A panel that adds storage options for exporting preferences.
|
||||||
|
*/
|
||||||
|
public class PreferencesOptionPanel extends JPanel {
|
||||||
|
private static final Translator trans = Application.getTranslator();
|
||||||
|
private static final Preferences prefs = Application.getPreferences();
|
||||||
|
|
||||||
|
public PreferencesOptionPanel() {
|
||||||
|
super(new MigLayout("fill, ins 0"));
|
||||||
|
|
||||||
|
JPanel panel = new JPanel(new MigLayout("fill, ins 4lp"));
|
||||||
|
panel.setBorder(BorderFactory.createTitledBorder(trans.get("PreferencesOptionPanel.title")));
|
||||||
|
|
||||||
|
JCheckBox exportUserDirectories = new JCheckBox(trans.get("PreferencesOptionPanel.checkbox.userDirectories"));
|
||||||
|
exportUserDirectories.setToolTipText(trans.get("PreferencesOptionPanel.checkbox.userDirectories.ttip"));
|
||||||
|
exportUserDirectories.setSelected(prefs.getExportUserDirectories());
|
||||||
|
exportUserDirectories.addItemListener(new ItemListener() {
|
||||||
|
@Override
|
||||||
|
public void itemStateChanged(ItemEvent e) {
|
||||||
|
prefs.setExportUserDirectories(e.getStateChange() == ItemEvent.SELECTED);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
panel.add(exportUserDirectories, "wrap 10lp");
|
||||||
|
|
||||||
|
this.add(panel, "growx, north");
|
||||||
|
}
|
||||||
|
}
|
@ -1,22 +1,56 @@
|
|||||||
package net.sf.openrocket.gui.util;
|
package net.sf.openrocket.gui.util;
|
||||||
|
|
||||||
|
import net.sf.openrocket.arch.SystemInfo;
|
||||||
|
import net.sf.openrocket.gui.components.PreferencesOptionPanel;
|
||||||
|
import net.sf.openrocket.gui.main.MRUDesignFile;
|
||||||
import net.sf.openrocket.gui.widgets.SaveFileChooser;
|
import net.sf.openrocket.gui.widgets.SaveFileChooser;
|
||||||
import net.sf.openrocket.l10n.Translator;
|
import net.sf.openrocket.l10n.Translator;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
import javax.swing.JFileChooser;
|
import javax.swing.JFileChooser;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
import javax.xml.transform.OutputKeys;
|
||||||
|
import javax.xml.transform.Transformer;
|
||||||
|
import javax.xml.transform.TransformerException;
|
||||||
|
import javax.xml.transform.TransformerFactory;
|
||||||
|
import javax.xml.transform.dom.DOMSource;
|
||||||
|
import javax.xml.transform.stream.StreamResult;
|
||||||
|
import java.awt.Dimension;
|
||||||
import java.awt.Window;
|
import java.awt.Window;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.util.prefs.BackingStoreException;
|
import java.util.prefs.BackingStoreException;
|
||||||
import java.util.prefs.Preferences;
|
import java.util.prefs.Preferences;
|
||||||
|
|
||||||
public abstract class PreferencesExporter {
|
public abstract class PreferencesExporter {
|
||||||
private static final Translator trans = Application.getTranslator();
|
private static final Translator trans = Application.getTranslator();
|
||||||
private static final Logger log = LoggerFactory.getLogger(PreferencesExporter.class);
|
private static final Logger log = LoggerFactory.getLogger(PreferencesExporter.class);
|
||||||
|
private static final net.sf.openrocket.startup.Preferences prefs = Application.getPreferences();
|
||||||
|
|
||||||
|
private static final String[] userDirectoriesKeysToIgnore; // Preference keys to ignore when exporting user directories (= keys that export user directories)
|
||||||
|
private static final String[] prefixKeysToIgnore; // Preference keys to ignore when exporting user directories (= keys that start with these prefixes)
|
||||||
|
|
||||||
|
static {
|
||||||
|
userDirectoriesKeysToIgnore = new String[] {
|
||||||
|
net.sf.openrocket.startup.Preferences.USER_THRUST_CURVES_KEY,
|
||||||
|
net.sf.openrocket.startup.Preferences.DEFAULT_DIRECTORY
|
||||||
|
};
|
||||||
|
prefixKeysToIgnore = new String[] {
|
||||||
|
MRUDesignFile.MRU_FILE_LIST_PROPERTY
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static boolean exportPreferences(Window parent, Preferences preferences) {
|
public static boolean exportPreferences(Window parent, Preferences preferences) {
|
||||||
JFileChooser chooser = new SaveFileChooser();
|
JFileChooser chooser = new SaveFileChooser();
|
||||||
@ -24,10 +58,15 @@ public abstract class PreferencesExporter {
|
|||||||
chooser.setAcceptAllFileFilterUsed(false);
|
chooser.setAcceptAllFileFilterUsed(false);
|
||||||
chooser.setFileFilter(FileHelper.XML_FILTER);
|
chooser.setFileFilter(FileHelper.XML_FILTER);
|
||||||
chooser.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultDirectory());
|
chooser.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultDirectory());
|
||||||
|
chooser.setAccessory(new PreferencesOptionPanel());
|
||||||
|
|
||||||
|
// TODO: update this dynamically instead of hard-coded values
|
||||||
// TODO: add storageoptions to choose whether to export user directories or not (default to not)
|
// The macOS file chooser has an issue where it does not update its size when the accessory is added.
|
||||||
|
if (SystemInfo.getPlatform() == SystemInfo.Platform.MAC_OS) {
|
||||||
|
Dimension currentSize = chooser.getPreferredSize();
|
||||||
|
Dimension newSize = new Dimension((int) (1.25 * currentSize.width), (int) (1.2 * currentSize.height));
|
||||||
|
chooser.setPreferredSize(newSize);
|
||||||
|
}
|
||||||
|
|
||||||
//// Ensures No Problems When Choosing File
|
//// Ensures No Problems When Choosing File
|
||||||
if (chooser.showSaveDialog(parent) != JFileChooser.APPROVE_OPTION) {
|
if (chooser.showSaveDialog(parent) != JFileChooser.APPROVE_OPTION) {
|
||||||
@ -35,7 +74,7 @@ public abstract class PreferencesExporter {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
((SwingPreferences) Application.getPreferences()).setDefaultDirectory(chooser.getCurrentDirectory());
|
((SwingPreferences) prefs).setDefaultDirectory(chooser.getCurrentDirectory());
|
||||||
|
|
||||||
File file = chooser.getSelectedFile();
|
File file = chooser.getSelectedFile();
|
||||||
if (file == null) {
|
if (file == null) {
|
||||||
@ -43,14 +82,20 @@ public abstract class PreferencesExporter {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
file = FileHelper.forceExtension(file, "xml");
|
final File newFile = FileHelper.forceExtension(file, "xml");
|
||||||
if (!FileHelper.confirmWrite(file, parent)) {
|
if (!FileHelper.confirmWrite(newFile, parent)) {
|
||||||
log.info("Cancelled export of preferences.");
|
log.info("Cancelled export of preferences.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
try (FileOutputStream fos = new FileOutputStream(file)) {
|
try (FileOutputStream fos = new FileOutputStream(newFile)) {
|
||||||
preferences.exportSubtree(fos);
|
if (prefs.getExportUserDirectories()) {
|
||||||
|
// Export all preferences
|
||||||
|
preferences.exportSubtree(fos);
|
||||||
|
} else {
|
||||||
|
// Export all preferences except user directories
|
||||||
|
exportFilteredPreferences(preferences, fos);
|
||||||
|
}
|
||||||
log.info("Preferences exported successfully.");
|
log.info("Preferences exported successfully.");
|
||||||
} catch (IOException | BackingStoreException e) {
|
} catch (IOException | BackingStoreException e) {
|
||||||
log.warn("Error while importing preferences: " + e.getMessage());
|
log.warn("Error while importing preferences: " + e.getMessage());
|
||||||
@ -58,4 +103,92 @@ public abstract class PreferencesExporter {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void exportFilteredPreferences(Preferences preferences, FileOutputStream fos) throws BackingStoreException, IOException {
|
||||||
|
// Filter out user directories
|
||||||
|
Preferences root = Preferences.userRoot();
|
||||||
|
String originalNodeName = ((SwingPreferences) prefs).getNodename();
|
||||||
|
String nodeName = originalNodeName + "-temp";
|
||||||
|
if (root.nodeExists(nodeName)) {
|
||||||
|
root.node(nodeName).removeNode();
|
||||||
|
}
|
||||||
|
Preferences tempPrefs = root.node(nodeName);
|
||||||
|
|
||||||
|
// Fill in all parameters to the temporary preferences, except for user directories
|
||||||
|
copyFilteredPreferences(preferences, tempPrefs, userDirectoriesKeysToIgnore, prefixKeysToIgnore);
|
||||||
|
|
||||||
|
// Export the filtered preferences
|
||||||
|
try {
|
||||||
|
// Export the filtered preferences to a temporary file
|
||||||
|
Path tempFile = Files.createTempFile("ORprefs_" + System.currentTimeMillis(), ".xml");
|
||||||
|
try (FileOutputStream tempFos = new FileOutputStream(tempFile.toFile())) {
|
||||||
|
tempPrefs.exportSubtree(tempFos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read and parse the temporary file
|
||||||
|
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||||
|
Document doc;
|
||||||
|
try (FileInputStream tempFis = new FileInputStream(tempFile.toFile())) {
|
||||||
|
doc = factory.newDocumentBuilder().parse(tempFis);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find and rename the node
|
||||||
|
NodeList nodeList = doc.getElementsByTagName("node");
|
||||||
|
for (int i = 0; i < nodeList.getLength(); i++) {
|
||||||
|
Element element = (Element) nodeList.item(i);
|
||||||
|
if (element.getAttribute("name").equals(nodeName)) {
|
||||||
|
element.setAttribute("name", ((SwingPreferences) prefs).getNodename());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a transformer to write the XML document to the FileOutputStream
|
||||||
|
Transformer transformer = TransformerFactory.newInstance().newTransformer();
|
||||||
|
|
||||||
|
// Set output properties to include the correct DOCTYPE declaration
|
||||||
|
transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "http://java.sun.com/dtd/preferences.dtd");
|
||||||
|
transformer.setOutputProperty(OutputKeys.STANDALONE, "no");
|
||||||
|
|
||||||
|
// Write the XML document to the FileOutputStream
|
||||||
|
DOMSource source = new DOMSource(doc);
|
||||||
|
StreamResult result = new StreamResult(fos);
|
||||||
|
transformer.transform(source, result);
|
||||||
|
|
||||||
|
// Clean up the temporary file
|
||||||
|
Files.deleteIfExists(tempFile);
|
||||||
|
} catch (ParserConfigurationException | TransformerException | SAXException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
root.node(nodeName).removeNode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void copyFilteredPreferences(Preferences src, Preferences dest, String[] keysToIgnore, String[] prefixKeysToIgnore) throws BackingStoreException {
|
||||||
|
for (String key : src.keys()) {
|
||||||
|
boolean ignoreKey = false;
|
||||||
|
for (String keyToIgnore : keysToIgnore) {
|
||||||
|
if (key.equals(keyToIgnore)) {
|
||||||
|
ignoreKey = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ignoreKey) {
|
||||||
|
for (String prefixKeyToIgnore : prefixKeysToIgnore) {
|
||||||
|
if (key.startsWith(prefixKeyToIgnore)) {
|
||||||
|
ignoreKey = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ignoreKey) {
|
||||||
|
dest.put(key, src.get(key, null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String childNodeName : src.childrenNames()) {
|
||||||
|
Preferences srcChild = src.node(childNodeName);
|
||||||
|
Preferences destChild = dest.node(childNodeName);
|
||||||
|
copyFilteredPreferences(srcChild, destChild, keysToIgnore, prefixKeysToIgnore);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,9 +34,6 @@ public abstract class PreferencesImporter {
|
|||||||
|
|
||||||
File importFile = chooser.getSelectedFile();
|
File importFile = chooser.getSelectedFile();
|
||||||
try (FileInputStream fis = new FileInputStream(importFile)) {
|
try (FileInputStream fis = new FileInputStream(importFile)) {
|
||||||
|
|
||||||
// TODO: don't import user directories?
|
|
||||||
|
|
||||||
Preferences.importPreferences(fis);
|
Preferences.importPreferences(fis);
|
||||||
log.info("Preferences imported successfully.");
|
log.info("Preferences imported successfully.");
|
||||||
} catch (IOException | InvalidPreferencesFormatException e) {
|
} catch (IOException | InvalidPreferencesFormatException e) {
|
||||||
|
@ -88,7 +88,9 @@ public class SwingPreferences extends net.sf.openrocket.startup.Preferences {
|
|||||||
PREFNODE = root.node(NODENAME);
|
PREFNODE = root.node(NODENAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getNodename() {
|
||||||
|
return NODENAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////
|
//////////////////////
|
||||||
@ -232,7 +234,7 @@ public class SwingPreferences extends net.sf.openrocket.startup.Preferences {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public File getDefaultDirectory() {
|
public File getDefaultDirectory() {
|
||||||
String file = getString("defaultDirectory", null);
|
String file = getString(net.sf.openrocket.startup.Preferences.DEFAULT_DIRECTORY, null);
|
||||||
if (file == null)
|
if (file == null)
|
||||||
return null;
|
return null;
|
||||||
return new File(file);
|
return new File(file);
|
||||||
@ -245,7 +247,7 @@ public class SwingPreferences extends net.sf.openrocket.startup.Preferences {
|
|||||||
} else {
|
} else {
|
||||||
d = dir.getAbsolutePath();
|
d = dir.getAbsolutePath();
|
||||||
}
|
}
|
||||||
putString("defaultDirectory", d);
|
putString(net.sf.openrocket.startup.Preferences.DEFAULT_DIRECTORY, d);
|
||||||
storeVersion();
|
storeVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user