It struck me as strange that PropertiesGameSettings didnt support setObject. My argument for adding it is that:
- PropertiesGameSettings is the default (and most widely used I imagine) game settings.
- GameControlManger.save() needs get/set object support to work.
Note: The code uses com.sun.org.apache.xerces.internal.impl.dv.util.Base64; for its Base64 encoding, which is an internal Sun library. Libraries of this kind are used in other places in the code base, but if need be I can write a quick base64 encoder.
Index: PropertiesGameSettings.java
===================================================================
--- PropertiesGameSettings.java (revision 4879)
+++ PropertiesGameSettings.java (working copy)
@@ -36,11 +36,16 @@
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.File;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.logging.Logger;
import java.util.logging.Level;
+import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
/**
* <code>PropertiesGameSettings</code> handles loading and saving a properties
@@ -490,11 +495,34 @@
}
/**
+ * Retruns an object stored inside a properties file by base64 decoding
+ * it and then deserialzing it. If the requested setting isn't an object
+ * stored this way, the default value is returned.
* @see GameSettings#getObject(String, Object)
*/
public Object getObject(String name, Object defaultValue) {
+
String stringValue = get(name);
- return (stringValue == null) ? defaultValue : stringValue;
+ if(stringValue == null) {
+ return defaultValue;
+ }
+ Object out;
+ try {
+ byte[] data = Base64.decode(stringValue);
+ ByteArrayInputStream s = new ByteArrayInputStream(data);
+ ObjectInputStream is = new ObjectInputStream(s);
+ out = is.readObject();
+ is.close();
+ s.close();
+
+ } catch (IOException ex) {
+ logger.log(Level.WARNING, "Problem deserializing object in settings.", ex);
+ return defaultValue;
+ } catch (ClassNotFoundException ex) {
+ logger.log(Level.WARNING, "Could find class for object in settings.", ex);
+ return defaultValue;
+ }
+ return out;
}
/**
@@ -584,20 +612,26 @@
}
/**
- * Not implemented.
- * Properties can not store an arbitrary Object in human-readable format.
- * Use set(String, String) instead.
+ * Stores an object in a properties file by first serializing it and
+ * then converting it into base64. If an object can be stored as a
+ * string it is often better to use set(String, String) instead.
*
* @see PreferencesGameSettings#setObject(String, boolean)
* @see #set(String, String)
- * @throws InternalError in all cases
*/
public void setObject(String name, Object value) {
- throw new InternalError(getClass().getName()
- + " Can't store arbitrary objects. "
- + "If there is a toString() method for your Object, and it is "
- + "Properties-compatible, use " + getClass().getName()
- + ".set(String, String).");
+ ByteArrayOutputStream s = new ByteArrayOutputStream();
+ try {
+ ObjectOutputStream os = new ObjectOutputStream(s);
+ os.writeObject(value);
+ os.close();
+ s.close();
+ } catch (IOException ex) {
+ logger.log(Level.WARNING, "Problem serializing object in settings.", ex);
+ }
+
+ String out = Base64.encode(s.toByteArray());
+ this.set(name, out);
}
/**