Hi, I spend some time finding out how the JDK makes it possible that a PersistenceDelegate registered for AbstractMap is used for all its subclasses.
The funny thing is that the whole behavior depends on three places. Two of them were implemented already because they are part of the spec. The final component consists only of one line (calling super.inititialize() in DefaultPersistenceDelegate.initialize()). Along the lines I found out that the XMLEncoder gets into an endless recursion when it serializes a class which is not public. The problem is not specific to this case the recursion would happen in any when an exception occurs during the Expression.getValue() call. A simple early "return" fixes that. I have to admit that the wrong behavior slipped in when I copied most of Encoder.writeExpression's code into XMLEncoder.writeExpression. Anyway this fixes PR #25941 . The ChangeLog entry: 2006-01-24 Robert Schuster <[EMAIL PROTECTED]> * java/beans/XMLEncoder.java: (writeExpression): Added early return (fixes PR #25941). * java/beans/Encoder: Removed unused imports. (setupDefaultPersistenceDelegates): Removed unneccessary PersistenceDelegates for subclasses. * java/beans/PersistenceDelegate: (initialize): Use local variable as first argument as it was intended once.
Index: java/beans/DefaultPersistenceDelegate.java =================================================================== RCS file: /cvsroot/classpath/classpath/java/beans/DefaultPersistenceDelegate.java,v retrieving revision 1.1 diff -u -r1.1 DefaultPersistenceDelegate.java --- java/beans/DefaultPersistenceDelegate.java 8 Jan 2006 19:31:38 -0000 1.1 +++ java/beans/DefaultPersistenceDelegate.java 24 Jan 2006 16:42:17 -0000 @@ -157,6 +157,23 @@ protected void initialize(Class type, Object oldInstance, Object newInstance, Encoder out) { + // Calling the supertype's implementation of initialize makes it + // possible that descendants of classes like AbstractHashMap + // or Hashtable are serialized correctly. This mechanism grounds on + // two other facts: + // * Each class which has not registered a special purpose + // PersistenceDelegate is handled by a DefaultPersistenceDelegate + // instance. + // * PersistenceDelegate.initialize() is implemented in a way that it + // calls the initialize method of the superclass' persistence delegate. + super.initialize(type, oldInstance, newInstance, out); + + // Suppresses the writing of property setting statements when this delegate + // is not used for the exact instance type. By doing so the following code + // is called only once per object. + if (type != oldInstance.getClass()) + return; + try { PropertyDescriptor[] propertyDescs = Introspector.getBeanInfo( Index: java/beans/Encoder.java =================================================================== RCS file: /cvsroot/classpath/classpath/java/beans/Encoder.java,v retrieving revision 1.1 diff -u -r1.1 Encoder.java --- java/beans/Encoder.java 8 Jan 2006 19:31:38 -0000 1.1 +++ java/beans/Encoder.java 24 Jan 2006 16:42:17 -0000 @@ -44,15 +44,9 @@ import gnu.java.beans.encoder.MapPersistenceDelegate; import gnu.java.beans.encoder.PrimitivePersistenceDelegate; -import java.util.ArrayList; +import java.util.AbstractCollection; import java.util.HashMap; -import java.util.HashSet; import java.util.IdentityHashMap; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.TreeMap; -import java.util.TreeSet; -import java.util.Vector; /** * @author Robert Schuster ([EMAIL PROTECTED]) @@ -123,31 +117,11 @@ delegates.put(Object[].class, new ArrayPersistenceDelegate()); pd = new CollectionPersistenceDelegate(); - delegates.put(ArrayList.class, pd); - delegates.put(LinkedList.class, pd); - delegates.put(Vector.class, pd); - delegates.put(HashSet.class, pd); - delegates.put(LinkedHashSet.class, pd); - delegates.put(TreeSet.class, pd); + delegates.put(AbstractCollection.class, pd); pd = new MapPersistenceDelegate(); - delegates.put(HashMap.class, pd); - delegates.put(TreeMap.class, pd); + delegates.put(java.util.AbstractMap.class, pd); delegates.put(java.util.Hashtable.class, pd); - delegates.put(java.util.IdentityHashMap.class, pd); - - delegates.put(java.util.LinkedHashMap.class, pd); - delegates.put(java.util.Properties.class, pd); - - delegates.put(java.awt.RenderingHints.class, pd); - delegates.put(java.util.WeakHashMap.class, pd); - delegates.put(javax.swing.UIDefaults.class, pd); - - // TODO: These classes need to be implemented first - //delegates.put(java.security.AuthProvider.class, pd); - //delegates.put(java.util.concurrent.ConcurrentHashMap.class, pd); - //delegates.put(java.util.EnumMap.class, pd); - //delegates.put(javax.management.openmbean.TabularDataSupport.class, pd); defaultPersistenceDelegate = new DefaultPersistenceDelegate(); delegates.put(Object.class, defaultPersistenceDelegate); @@ -199,7 +173,6 @@ public void exceptionThrown(Exception e) { System.err.println("exception thrown: " + e); - e.printStackTrace(); } }; } Index: java/beans/PersistenceDelegate.java =================================================================== RCS file: /cvsroot/classpath/classpath/java/beans/PersistenceDelegate.java,v retrieving revision 1.1 diff -u -r1.1 PersistenceDelegate.java --- java/beans/PersistenceDelegate.java 8 Jan 2006 19:31:38 -0000 1.1 +++ java/beans/PersistenceDelegate.java 24 Jan 2006 16:42:17 -0000 @@ -59,9 +59,8 @@ { type = type.getSuperclass(); - PersistenceDelegate pd = out.getPersistenceDelegate( - oldInstance.getClass().getSuperclass()); - + PersistenceDelegate pd = out.getPersistenceDelegate(type); + pd.initialize(type, oldInstance, newInstance, out); } } Index: java/beans/XMLEncoder.java =================================================================== RCS file: /cvsroot/classpath/classpath/java/beans/XMLEncoder.java,v retrieving revision 1.1 diff -u -r1.1 XMLEncoder.java --- java/beans/XMLEncoder.java 8 Jan 2006 19:31:38 -0000 1.1 +++ java/beans/XMLEncoder.java 24 Jan 2006 16:42:17 -0000 @@ -168,6 +168,8 @@ // an erroneous state to the ScanEngine without behaving different // to the JDK. scanEngine.revoke(); + + return; } writeObject(value);
signature.asc
Description: OpenPGP digital signature
_______________________________________________ Classpath-patches mailing list Classpath-patches@gnu.org http://lists.gnu.org/mailman/listinfo/classpath-patches