From 20541d11dcc05d3d7664b2ec3954d3a95396fc91 Mon Sep 17 00:00:00 2001 From: Eric Lundberg Date: Thu, 4 Mar 2004 02:50:30 +0000 Subject: [PATCH] Added code to support serializing and deserializing of Streamable objects in the prefs. Thus we can now have DSets of arbitrary data types in our run time config objects, with swanky custom UI no less. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@2978 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../admin/server/ConfObjRegistry.java | 101 +++++++++++++++++- 1 file changed, 98 insertions(+), 3 deletions(-) diff --git a/src/java/com/threerings/admin/server/ConfObjRegistry.java b/src/java/com/threerings/admin/server/ConfObjRegistry.java index 0b4b38e5a..5b413daf8 100644 --- a/src/java/com/threerings/admin/server/ConfObjRegistry.java +++ b/src/java/com/threerings/admin/server/ConfObjRegistry.java @@ -1,21 +1,34 @@ // -// $Id: ConfObjRegistry.java,v 1.7 2004/02/25 14:39:14 mdb Exp $ +// $Id: ConfObjRegistry.java,v 1.8 2004/03/04 02:50:30 eric Exp $ package com.threerings.admin.server; +import java.io.ByteArrayInputStream; +import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.HashMap; import java.util.Iterator; +import com.samskivert.io.ByteArrayOutInputStream; import com.samskivert.util.Config; +import com.samskivert.util.StringUtil; + +import com.threerings.io.ObjectInputStream; +import com.threerings.io.ObjectOutputStream; +import com.threerings.io.Streamable; import com.threerings.presents.dobj.AttributeChangeListener; import com.threerings.presents.dobj.AttributeChangedEvent; import com.threerings.presents.dobj.DObject; +import com.threerings.presents.dobj.EntryAddedEvent; +import com.threerings.presents.dobj.EntryRemovedEvent; +import com.threerings.presents.dobj.EntryUpdatedEvent; +import com.threerings.presents.dobj.SetListener; import com.threerings.admin.Log; +import com.threerings.presents.dobj.ObjectAccessException; /** * Provides a registry of configuration distributed objects. Using @@ -89,7 +102,7 @@ public class ConfObjRegistry * registration. */ protected static class ConfObjRecord - implements AttributeChangeListener + implements AttributeChangeListener, SetListener { public DObject confObj; public Config config; @@ -123,6 +136,26 @@ public class ConfObjRegistry } } + // documentation inherited + public void entryAdded (EntryAddedEvent event) + { + // TODO test + serializeAttribute(event.getName()); + } + + // documentation inherited + public void entryUpdated (EntryUpdatedEvent event) + { + serializeAttribute(event.getName()); + } + + // documentation inherited + public void entryRemoved (EntryRemovedEvent event) + { + // TODO test + serializeAttribute(event.getName()); + } + public void attributeChanged (AttributeChangedEvent event) { // mirror this configuration update to the on-disk config @@ -145,7 +178,6 @@ public class ConfObjRegistry config.setValue(key, (int[])value); } else if (value instanceof String[]) { config.setValue(key, (String[])value); - } else { Log.info("Unable to flush config object change " + "[cobj=" + confObj.getClass().getName() + @@ -195,6 +227,25 @@ public class ConfObjRegistry String[] defval = (String[])field.get(confObj); field.set(confObj, config.getValue(key, defval)); + } else if (Streamable.class.isAssignableFrom(type)) { + + // don't freak out if the conf is blank. + String value = config.getValue(key, ""); + if (StringUtil.blank(value)) { + return; + } + + try { + ByteArrayInputStream bin = new ByteArrayInputStream( + StringUtil.unhexlate(value)); + ObjectInputStream oin = new ObjectInputStream(bin); + field.set(confObj, oin.readObject()); + } catch (Exception e) { + Log.warning("Failure decoding config value [type=" + + type + ", field=" + field + ", exception=" + + e + "]."); + } + } else { Log.warning("Can't init field of unknown type " + "[cobj=" + confObj.getClass().getName() + @@ -235,6 +286,50 @@ public class ConfObjRegistry return key.toString(); } + /** + * Get the specified attribute from the configuration object, and + * serialize it. + */ + protected void serializeAttribute (String attributeName) + { + String key = fieldToKey(attributeName); + Object value; + try { + value = confObj.getAttribute(attributeName); + } catch (ObjectAccessException oae) { + Log.warning("Exception getting dset [setname=" + attributeName + + "exception=" + oae + "]."); + return; + } + + if (value instanceof Streamable) { + serialize(key, value); + } else { + Log.info("Unable to flush config object change " + + "[cobj=" + confObj.getClass().getName() + + ", key=" + key + + ", type=" + value.getClass().getName() + + ", value=" + value + "]."); + } + } + + /** + * Save the specified object as serialized data associated with + * the specified key. + */ + protected void serialize (String key, Object value) + { + ByteArrayOutInputStream out = new ByteArrayOutInputStream(); + ObjectOutputStream oout = new ObjectOutputStream(out); + try { + oout.writeObject(value); + oout.flush(); + config.setValue(key, StringUtil.hexlate(out.toByteArray())); + } catch (IOException ioe) { + Log.info("Error serializing value " + value); + } + } + protected static final int[] INT_ARRAY_PROTO = new int[0]; protected static final float[] FLOAT_ARRAY_PROTO = new float[0]; protected static final String[] STRING_ARRAY_PROTO = new String[0];