You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by sk...@apache.org on 2008/08/27 10:40:51 UTC
svn commit: r689411 -
/myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/dynaForm/lib/ObjectSerializationConverter.java
Author: skitching
Date: Wed Aug 27 01:40:50 2008
New Revision: 689411
URL: http://svn.apache.org/viewvc?rev=689411&view=rev
Log:
Add comments. Change char encoding to something clearer (but which
should make no actual difference).
Modified:
myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/dynaForm/lib/ObjectSerializationConverter.java
Modified: myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/dynaForm/lib/ObjectSerializationConverter.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/dynaForm/lib/ObjectSerializationConverter.java?rev=689411&r1=689410&r2=689411&view=diff
==============================================================================
--- myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/dynaForm/lib/ObjectSerializationConverter.java (original)
+++ myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/dynaForm/lib/ObjectSerializationConverter.java Wed Aug 27 01:40:50 2008
@@ -32,14 +32,29 @@
import java.io.Serializable;
/**
- * This converter will be used to e.g. render a selection menu. <br />
- * It is responsible to convert a object to a string-identifier representation with which it is possible to
- * recreate the object again - aka serialization
+ * Converter that can map a Serializable object into a plain java String.
+ * <p>
+ * This works like the standard java Serializable process, except that the resulting byte-array is
+ * then base64-encoded, ie is a String containing only ascii characters. The resulting value can
+ * safely be passed around as the "value" of a select-list, or a value embedded in a hidden field etc.
+ * <p>
+ * In particular, this allows the value of a SelectItem to be an object rather than a String, and the
+ * serialized form of a <i>small</i> object (such as the key class of a persistent entity) to be passed
+ * as a url query parameter.
+ * <p>
+ * Of course the object should not be too complicated, otherwise the string representation will
+ * be rather large!
*/
public class ObjectSerializationConverter implements Converter
{
public static final NullObject SELECT_NULL_OBJECT = new NullObject();
+ /**
+ * Given a String that was previously created by the getAsString method on this class,
+ * "deserialize" the content of the string into a new Object instance.
+ * <p>
+ * See method getAsString for more details.
+ */
public Object getAsObject(FacesContext context, UIComponent component, String value) throws ConverterException
{
if (value == null || value.length() < 1 || SELECT_NULL_OBJECT.equals(value))
@@ -51,8 +66,16 @@
Serializable objectIdent;
try
{
- byte[] base64 = Base64.decodeBase64(value.getBytes("UTF-8"));
- ois = new ObjectInputStream(new ByteArrayInputStream(base64));
+ // The string will have been created by getAsString. Therefore it will only ever
+ // contain 16-bit characters whose high 9 bits are zero. Every one of these chars
+ // will map fine to us-ascii, and will give us back the original base64-encoded
+ // byte-array form from the getAsString method. Note that UTF-8 should also work
+ // fine here; when the high 9 bits of a char are zero then the utf-8 representation
+ // of the char is a single byte that has its high bit set to zero, which is exactly
+ // what the original base64-encoded data had.
+ byte[] base64 = value.getBytes("US-ASCII");
+ byte[] rawData = Base64.decodeBase64(base64);
+ ois = new ObjectInputStream(new ByteArrayInputStream(rawData));
objectIdent = (Serializable) ois.readObject();
ois.close();
}
@@ -82,6 +105,16 @@
return objectIdent;
}
+ /**
+ * Return a serialized representation of the provided value, as a String type.
+ * <p>
+ * The provided value is serialized into a byte-array using normal java serialization,
+ * and the array is then base64-encoded. The result is a String that is safe to pass
+ * around in places that expect a String. The returned value can later be passed to the
+ * getAsToObject method of this class to recreate the value passed here.
+ * <p>
+ * The provided object must implement the Serializable interface.
+ */
public String getAsString(FacesContext context, UIComponent component, Object value) throws ConverterException
{
if (value == null || SELECT_NULL_OBJECT.equals(value))
@@ -96,7 +129,30 @@
oos = new ObjectOutputStream(baos);
oos.writeObject(value);
byte[] base64 = Base64.encodeBase64(baos.toByteArray());
- String objectString = new String(base64, "UTF-8");
+
+ // It doesn't really matter what encoding we use to create a String here, as long as
+ // we use the same encoding to convert back to a byte-array later (and the encoding
+ // chosen is "symmetrical").
+ //
+ // Using UTF-16BE would give us a very dense string representation (essentially no change to the data).
+ // However it does mean that:
+ // * the result will be unreadable
+ // * any attempt to write the string out as utf-8 will waste space
+ // * trying to write it out in an 8-bit encoding will fail, as the string will certainly
+ // hold 'chars' that are not representable in that encoding.
+ //
+ // Using UTF-8 and US-ASCII will result in the same String.
+ // * When interpreting as US-ASCII, the char conversion process will simply create a two-byte
+ // character (0<<8 |input) regardless of the input.
+ // * When interpreting as UTF-8, the char conversion process will look at each byte, and when the
+ // high bit is not set will simply create a two-byte character (0<<8 | input). Processing is
+ // more complicated when the high bit is set on a byte; however as the base64 encoding results
+ // in an array of bytes whose high bit is never set, the effect is identical to US-ASCII in this case.
+ //
+ // Because of this padding with zero bytes, the String takes up twice as much memory as the
+ // original byte array. So this method should only be used when simply passing around byte[]
+ // is not possible.
+ String objectString = new String(base64, "US-ASCII");
return objectString;
}
catch (IOException e)