You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by le...@apache.org on 2007/07/16 08:52:31 UTC

svn commit: r556525 - in /harmony/enhanced/classlib/trunk/modules/beans: META-INF/ src/main/java/java/beans/ src/main/java/org/apache/harmony/beans/ src/test/java/org/apache/harmony/beans/tests/java/beans/

Author: leoli
Date: Sun Jul 15 23:52:30 2007
New Revision: 556525

URL: http://svn.apache.org/viewvc?view=rev&rev=556525
Log:
Apply patch for HARMONY-4326([classlib][beans] Current java6 bean implementation does not persist java.lang.refect.Method properly).

Modified:
    harmony/enhanced/classlib/trunk/modules/beans/META-INF/MANIFEST.MF
    harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/PersistenceDelegate.java
    harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/XMLDecoder.java
    harmony/enhanced/classlib/trunk/modules/beans/src/main/java/org/apache/harmony/beans/java_lang_reflect_MethodPersistenceDelegate.java
    harmony/enhanced/classlib/trunk/modules/beans/src/test/java/org/apache/harmony/beans/tests/java/beans/PersistenceDelegateTest.java

Modified: harmony/enhanced/classlib/trunk/modules/beans/META-INF/MANIFEST.MF
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/beans/META-INF/MANIFEST.MF?view=diff&rev=556525&r1=556524&r2=556525
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/beans/META-INF/MANIFEST.MF (original)
+++ harmony/enhanced/classlib/trunk/modules/beans/META-INF/MANIFEST.MF Sun Jul 15 23:52:30 2007
@@ -23,10 +23,11 @@
  java.util,
  java.util.regex;resolution:=optional,
  javax.accessibility;resolution:=optional,
+ javax.xml.parsers,
  org.apache.harmony.kernel.vm,
+ org.apache.harmony.testframework.serialization;hy_usage=test;resolution:=optional,
  org.xml.sax,
  org.xml.sax.helpers,
- org.apache.harmony.testframework.serialization;hy_usage=test;resolution:=optional,
  tests.util;hy_usage=test;resolution:=optional
 Export-Package: java.beans,
  java.beans.beancontext

Modified: harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/PersistenceDelegate.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/PersistenceDelegate.java?view=diff&rev=556525&r1=556524&r2=556525
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/PersistenceDelegate.java (original)
+++ harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/PersistenceDelegate.java Sun Jul 15 23:52:30 2007
@@ -1,76 +1,123 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
+/* 
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
  *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
-package java.beans;
 
-import org.apache.harmony.beans.internal.nls.Messages;
+package java.beans;
 
+/**
+ * <code>PersistenceDelegate</code> instances write received bean objects to
+ * encoders in the form of expressions and statements, which can be evaluated or
+ * executed to reconstruct the recorded bean objects in a new environment during
+ * decoding. Expressions are usually used to instantiate bean objects in the new
+ * environment, and statements are used to initialize their properties if
+ * necessary. As a result, the reconstructed bean objects become equivalent to
+ * the original recorded ones in terms of their public states.
+ * 
+ */
 public abstract class PersistenceDelegate {
 
-    protected void initialize(Class<?> type, Object oldInstance,
-            Object newInstance, Encoder out) {
-
-        if (type == null) {
-            throw new NullPointerException(Messages.getString("beans.4B")); //$NON-NLS-1$
-        }
+    /**
+     * Default constructor.
+     */
+    public PersistenceDelegate() {
+        // empty
+    }
 
-        if (out != null) {
-            PersistenceDelegate pd = out.getPersistenceDelegate(type
-                    .getSuperclass());
-
-            if (pd != null) {
-                try {
-                    pd.initialize(type, oldInstance, newInstance, out);
-                } catch (StackOverflowError err) {
-                    // circular redundancy
-                    // we should catch in order to be compatible with RI
-                }
-            }
-        } else {
-            throw new NullPointerException(
-                    Messages.getString("beans.4C")); //$NON-NLS-1$
+    /**
+     * Produces a series of expressions and statements for the initialization of
+     * a bean object's properties. The default implementation simply invokes the
+     * initialization provided by the super class's
+     * <code>PersisteneceDelegate</code> instance.
+     * 
+     * @param type
+     *            the type of the bean
+     * @param oldInstance
+     *            the original bean object to be recorded
+     * @param newInstance
+     *            the simmulating new bean object to be initialized
+     * @param enc
+     *            the encoder to write the outputs to
+     */
+    protected void initialize(Class<?> type, Object oldInstance,
+            Object newInstance, Encoder enc) {
+        Class c = type.getSuperclass();
+        if (null != c) {
+            PersistenceDelegate pd = enc.getPersistenceDelegate(c);
+            pd.initialize(c, oldInstance, newInstance, enc);
         }
     }
 
-    protected abstract Expression instantiate(Object oldInstance, Encoder out);
-
-    protected boolean mutatesTo(Object oldInstance, Object newInstance) {
-        boolean bothInstancesAreNull = (oldInstance == null)
-                && (newInstance == null);
-
-        if (bothInstancesAreNull) {
+    /**
+     * Constructs an expression for instantiating an object of the same type as
+     * the old instance. Any exceptions occured during this process could be
+     * reported to the exception listener registered in the given encoder.
+     * 
+     * @param oldInstance
+     *            the old instance
+     * @param enc
+     *            the encoder that wants to record the old instance
+     * @return an expression for instantiating an object of the same type as the
+     *         old instance
+     */
+    protected abstract Expression instantiate(Object oldInstance, Encoder enc);
+
+    /**
+     * Determines whether one object mutates to the other object. One object is
+     * considered able to mutate to another object if they are indistinguishable
+     * in terms of behaviors of all public APIs. The default implementation here
+     * is to return true only if the two objects are instances of the same
+     * class.
+     * 
+     * @param o1
+     *            one object
+     * @param o2
+     *            the other object
+     * @return true if second object mutates to the first object, otherwise
+     *         false
+     */
+    protected boolean mutatesTo(Object o1, Object o2) {
+        if (null == o1 || null == o2 ) {
             return false;
         }
-        return (oldInstance != null) && (newInstance != null) ? oldInstance
-                .getClass() == newInstance.getClass() : false;
+        return o1.getClass() == o2.getClass();
     }
 
+    /**
+     * Writes a bean object to the given encoder. First it is checked whether
+     * the simulating new object can be mutated to the old instance. If yes, it
+     * is initialized to produce a series of expressions and statements that can
+     * be used to restore the old instance. Otherwise, remove the new object in
+     * the simulating new environment and writes an expression that can
+     * instantiate a new instance of the same type as the old one to the given
+     * encoder.
+     * 
+     * @param oldInstance
+     *            the old instance to be written
+     * @param out
+     *            the encoder that the old instance will be written to
+     */
     public void writeObject(Object oldInstance, Encoder out) {
-        // nulls are covered by NullPersistenceDelegate
-        assert oldInstance != null;
-
         Object newInstance = out.get(oldInstance);
-
         if (mutatesTo(oldInstance, newInstance)) {
             initialize(oldInstance.getClass(), oldInstance, newInstance, out);
         } else {
-        	out.remove(oldInstance);
-
-            out.writeExpression(instantiate(oldInstance, out));
+            out.remove(oldInstance);
+            Expression exp = instantiate(oldInstance, out);
+            out.writeExpression(exp);
             newInstance = out.get(oldInstance);
             
             if (newInstance != null) {
@@ -79,4 +126,6 @@
             }
         }
     }
+
 }
+

Modified: harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/XMLDecoder.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/XMLDecoder.java?view=diff&rev=556525&r1=556524&r2=556525
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/XMLDecoder.java (original)
+++ harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/XMLDecoder.java Sun Jul 15 23:52:30 2007
@@ -1,142 +1,541 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
+/* 
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
  *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
+
 package java.beans;
 
-import java.io.IOException;
 import java.io.InputStream;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-import java.util.Vector;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Stack;
+
+import javax.xml.parsers.SAXParserFactory;
 
-import org.apache.harmony.beans.Handler;
-import org.xml.sax.InputSource;
+import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
-import org.xml.sax.XMLReader;
-import org.xml.sax.helpers.XMLReaderFactory;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
 
+/**
+ * <code>XMLDecoder</code> reads objects from xml created by
+ * <code>XMLEncoder</code>.
+ * <p>The API is similar to <code>ObjectInputStream</code>.</p>
+ *
+ */
 public class XMLDecoder {
 
-    private InputStream is = null;
+    private ClassLoader defaultClassLoader = null;
+    
+    private static class DefaultExceptionListener implements ExceptionListener {
+
+        public void exceptionThrown(Exception e) {
+            e.printStackTrace();
+            System.err.println("Continue...");
+        }
+    }
 
-    private Object owner = null;
+    private class SAXHandler extends DefaultHandler {
 
-    private ExceptionListener exceptionListener = null;
+        boolean inJavaElem = false;
 
-    private final Vector<Object> objects = new Vector<Object>();
+        HashMap idObjMap = new HashMap();
 
-    private Iterator<Object> iterator = null;
-    
-    private ClassLoader classLoader = null;
+        public void characters(char[] ch, int start, int length)
+                throws SAXException {
+            if (!inJavaElem) {
+                return;
+            }
+            if (readObjs.size() > 0) {
+                Elem elem = (Elem) readObjs.peek();
+                if (elem.isBasicType) {
+                    String str = new String(ch, start, length);
+                    elem.methodName = elem.methodName == null ? str
+                            : elem.methodName + str;
+                }
+            }
+        }
 
-    public XMLDecoder(InputStream is, Object owner,
-            ExceptionListener exceptionListener, ClassLoader cl) {
-        this.is = is;
-        this.owner = owner;
-        this.exceptionListener = exceptionListener;
-        this.classLoader = cl;
+        public void startElement(String uri, String localName, String qName,
+                Attributes attributes) throws SAXException {
+            if (!inJavaElem) {
+                if ("java".equals(qName)) {
+                    inJavaElem = true;
+                } else {
+                    listener.exceptionThrown(new Exception(
+                            "unknown root element: " + qName));
+                }
+                return;
+            }
+
+            if ("object".equals(qName)) {
+                startObjectElem(attributes);
+            } else if ("array".equals(qName)) {
+                startArrayElem(attributes);
+            } else if ("void".equals(qName)) {
+                startVoidElem(attributes);
+            } else if ("boolean".equals(qName) || "byte".equals(qName)
+                    || "char".equals(qName) || "class".equals(qName)
+                    || "double".equals(qName) || "float".equals(qName)
+                    || "int".equals(qName) || "long".equals(qName)
+                    || "short".equals(qName) || "string".equals(qName)
+                    || "null".equals(qName)) {
+                startBasicElem(qName, attributes);
+            }
+        }
+
+        private void startObjectElem(Attributes attributes) throws SAXException {
+            Elem elem = new Elem();
+            elem.isExpression = true;
+            elem.id = attributes.getValue("id");
+            elem.idref = attributes.getValue("idref");
+            if (elem.idref == null) {
+                obtainTarget(elem, attributes);
+                obtainMethod(elem, attributes);
+            }
+			
+            readObjs.push(elem);
+        }
+
+        private void obtainTarget(Elem elem, Attributes attributes) {
+            String className = attributes.getValue("class");
+            if (className != null) {
+                try {
+                    elem.target = classForName(className);
+                } catch (ClassNotFoundException e) {
+                    listener.exceptionThrown(e);
+                }
+            } else {
+                Elem parent = latestUnclosedElem();
+				if(parent == null) {
+					elem.target = owner;
+					return;
+				}
+                elem.target = execute(parent);
+            }
+        }
+
+        private void obtainMethod(Elem elem, Attributes attributes) {
+            elem.methodName = attributes.getValue("method");
+            if (elem.methodName != null) {
+                return;
+            }
+
+            elem.methodName = attributes.getValue("property");
+            if (elem.methodName != null) {
+                elem.fromProperty = true;
+                return;
+            }
+
+            elem.methodName = attributes.getValue("index");
+            if (elem.methodName != null) {
+                elem.fromIndex = true;
+                return;
+            }
+
+            elem.methodName = attributes.getValue("field");
+            if (elem.methodName != null) {
+				elem.fromField = true;
+                return;
+            }
+
+            elem.methodName = attributes.getValue("owner");
+            if (elem.methodName != null) {
+				elem.fromOwner = true;
+                return;
+            }
+
+            elem.methodName = "new"; // default method name
+        }
+
+        private Class classForName(String className)
+                throws ClassNotFoundException {
+            if ("boolean".equals(className)) {
+                return Boolean.TYPE;
+            } else if ("byte".equals(className)) {
+                return Byte.TYPE;
+            } else if ("char".equals(className)) {
+                return Character.TYPE;
+            } else if ("double".equals(className)) {
+                return Double.TYPE;
+            } else if ("float".equals(className)) {
+                return Float.TYPE;
+            } else if ("int".equals(className)) {
+                return Integer.TYPE;
+            } else if ("long".equals(className)) {
+                return Long.TYPE;
+            } else if ("short".equals(className)) {
+                return Short.TYPE;
+            } else {
+                return Class.forName(className, true,
+                        defaultClassLoader == null ? Thread.currentThread()
+                                .getContextClassLoader() : defaultClassLoader);
+            }
+        }
+
+        private void startArrayElem(Attributes attributes) {
+            Elem elem = new Elem();
+            elem.isExpression = true;
+            elem.id = attributes.getValue("id");
+            try {
+                // find componet class
+                Class compClass = classForName(attributes.getValue("class"));
+                // find length
+                int length = Integer.parseInt(attributes.getValue("length"));
+                // execute, new array instance
+                elem.result = Array.newInstance(compClass, length);
+                elem.isExecuted = true;
+            } catch (Exception e) {
+                listener.exceptionThrown(e);
+            }
+            readObjs.push(elem);
+        }
+
+        private void startVoidElem(Attributes attributes) {
+            Elem elem = new Elem();
+            elem.id = attributes.getValue("id");
+            obtainTarget(elem, attributes);
+            obtainMethod(elem, attributes);
+            readObjs.push(elem);
+        }
+
+        private void startBasicElem(String tagName, Attributes attributes) {
+            Elem elem = new Elem();
+            elem.isBasicType = true;
+            elem.isExpression = true;
+            elem.id = attributes.getValue("id");
+            elem.idref = attributes.getValue("idref");
+            elem.target = tagName;
+            readObjs.push(elem);
+        }
+
+        public void endElement(String uri, String localName, String qName)
+                throws SAXException {
+            if (!inJavaElem) {
+                return;
+            }
+            if ("java".equals(qName)) {
+                inJavaElem = false;
+                return;
+            }
+            // find the elem to close
+            Elem toClose = latestUnclosedElem();
+            // make sure it is executed
+            execute(toClose);
+            // set to closed
+            toClose.isClosed = true;
+            // pop it and its children
+            while (readObjs.pop() != toClose) {
+                //
+            }
+            // push back expression
+            if (toClose.isExpression) {
+                readObjs.push(toClose);
+            }
+        }
+
+        private Elem latestUnclosedElem() {
+            for (int i = readObjs.size() - 1; i >= 0; i--) {
+                Elem elem = (Elem) readObjs.get(i);
+                if (!elem.isClosed) {
+                    return elem;
+                }
+            }
+            return null;
+        }
+
+        private Object execute(Elem elem) {
+            if (elem.isExecuted) {
+                return elem.result;
+            }
+
+            // execute to obtain result
+            try {
+                if (elem.idref != null) {
+                    elem.result = idObjMap.get(elem.idref);
+                } else if (elem.isBasicType) {
+                    elem.result = executeBasic(elem);
+                } else {
+                    elem.result = executeCommon(elem);
+                }
+            } catch (Exception e) {
+                listener.exceptionThrown(e);
+            }
+
+            // track id
+            if (elem.id != null) {
+                idObjMap.put(elem.id, elem.result);
+            }
+
+            elem.isExecuted = true;
+            return elem.result;
+        }
+
+        private Object executeCommon(Elem elem) throws Exception {
+            // pop args
+            ArrayList args = new ArrayList(5);
+            while (readObjs.peek() != elem) {
+                Elem argElem = (Elem) readObjs.pop();
+                args.add(0, argElem.result);
+            }
+            // decide method name
+            String method = elem.methodName;
+            if (elem.fromProperty) {
+                method = (args.size() == 0 ? "get" : "set")
+                        + capitalize(method);
+            }
+            if (elem.fromIndex) {
+                Integer index = Integer.valueOf(method);
+                args.add(0, index);
+                method = args.size() == 1 ? "get" : "set";
+            }
+			if(elem.fromField) {
+				Field f = ((Class)elem.target).getField(method);
+		        return (new Expression(f, "get", new Object[] {null})).getValue();
+			}
+			if(elem.fromOwner) {
+				return owner;
+			}
+			
+			if(elem.target == owner) {
+				if("getOwner".equals(method)) {
+					return owner;
+				} else {
+					Class[] c = new Class[args.size()];
+					for(int i = 0; i < args.size(); i++) {
+						c[i] = args.get(i).getClass();
+					}
+					Method m = owner.getClass().getMethod(method, c);
+					return m.invoke(owner, args.toArray());
+				}
+			}
+			
+            // execute
+            Expression exp = new Expression(elem.target, method, args.toArray());
+            return exp.getValue();
+        }
+
+        private String capitalize(String str) {
+            StringBuffer buf = new StringBuffer(str);
+            buf.setCharAt(0, Character.toUpperCase(buf.charAt(0)));
+            return buf.toString();
+        }
+
+        private Object executeBasic(Elem elem) throws Exception {
+            String tag = (String) elem.target;
+            String value = elem.methodName;
+
+            if ("null".equals(tag)) {
+                return null;
+            } else if ("string".equals(tag)) {
+                return value;
+            } else if ("class".equals(tag)) {
+                return classForName(value);
+            } else if ("boolean".equals(tag)) {
+                return Boolean.valueOf(value);
+            } else if ("byte".equals(tag)) {
+                return Byte.valueOf(value);
+            } else if ("char".equals(tag)) {
+                return new Character(value.charAt(0));
+            } else if ("double".equals(tag)) {
+                return Double.valueOf(value);
+            } else if ("float".equals(tag)) {
+                return Float.valueOf(value);
+            } else if ("int".equals(tag)) {
+                return Integer.valueOf(value);
+            } else if ("long".equals(tag)) {
+                return Long.valueOf(value);
+            } else if ("short".equals(tag)) {
+                return Short.valueOf(value);
+            } else {
+                throw new Exception("Unknown tag of basic type: " + tag);
+            }
+        }
+
+        public void error(SAXParseException e) throws SAXException {
+            listener.exceptionThrown(e);
+        }
+
+        public void fatalError(SAXParseException e) throws SAXException {
+            listener.exceptionThrown(e);
+        }
+
+        public void warning(SAXParseException e) throws SAXException {
+            listener.exceptionThrown(e);
+        }
     }
 
-    public XMLDecoder(InputStream is, Object owner,
-            ExceptionListener exceptionListener) {
-        this.is = is;
-        this.owner = owner;
-        this.exceptionListener = exceptionListener;
+    private static class Elem {
+		String id;
+
+        String idref;
+
+        boolean isExecuted;
+
+        boolean isExpression;
+
+        boolean isBasicType;
+
+        boolean isClosed;
+
+        Object target;
+
+        String methodName;
+
+        boolean fromProperty;
+
+        boolean fromIndex;
+		
+		boolean fromField;
+
+        boolean fromOwner;
+
+        Object result;
     }
 
-    public XMLDecoder(InputStream is, Object owner) {
-        this.is = is;
-        this.owner = owner;
+    private InputStream inputStream;
+
+    private ExceptionListener listener;
+
+    private Object owner;
+
+    private Stack readObjs = new Stack();
+
+    private int readObjIndex = 0;
+
+    /**
+     * Create a decoder to read from specified input stream.
+     *
+     * @param inputStream   an input stream of xml
+     */
+    public XMLDecoder(InputStream inputStream) {
+        this(inputStream, null, null);
     }
 
-    public XMLDecoder(InputStream is) {
-        this.is = is;
+    /**
+     * Create a decoder to read from specified input stream.
+     *
+     * @param inputStream   an input stream of xml
+     * @param owner         the owner of this decoder
+     */
+    public XMLDecoder(InputStream inputStream, Object owner) {
+        this(inputStream, owner, null);
     }
 
-    public void setOwner(Object owner) {
+    /**
+     * Create a decoder to read from specified input stream.
+     *
+     * @param inputStream   an input stream of xml
+     * @param owner         the owner of this decoder
+     * @param listener      listen to the exceptions thrown by the decoder
+     */
+    public XMLDecoder(InputStream inputStream, Object owner,
+            ExceptionListener listener) {
+        if (inputStream == null) {
+            throw new IllegalArgumentException("Input stream cannot be null");
+        }
+        if (listener == null) {
+            listener = new DefaultExceptionListener();
+        }
+        this.inputStream = inputStream;
         this.owner = owner;
-    }
+        this.listener = listener;
 
-    public Object readObject() {
         try {
-            if (iterator == null) {
-                initialize();
-            }
-            return iterator.next();
-        } catch (NoSuchElementException nsee) {
-            throw new ArrayIndexOutOfBoundsException();
+            SAXParserFactory.newInstance().newSAXParser().parse(inputStream,
+                    new SAXHandler());
+        } catch (Exception e) {
+            listener.exceptionThrown(e);
         }
     }
-
-    public Object getOwner() {
-        return owner;
+    
+    public XMLDecoder(InputStream inputStream, Object owner,
+            ExceptionListener listener, ClassLoader cl) {
+        this(inputStream, owner, listener);
+        defaultClassLoader = cl;
     }
 
-    public void setExceptionListener(ExceptionListener exceptionListener) {
-        this.exceptionListener = exceptionListener;
+    /**
+     * Close the input stream of xml data.
+     */
+    public void close() {
+        try {
+            inputStream.close();
+        } catch (Exception e) {
+            listener.exceptionThrown(e);
+        }
     }
 
+    /**
+     * Returns the exception listener.
+     * @return the exception listener
+     */
     public ExceptionListener getExceptionListener() {
-        return exceptionListener;
+        return listener;
     }
 
-    public void close() {
-        try {
-            is.close();
-        } catch (IOException ioe) {
-            handleException(ioe);
-        }
+    /**
+     * Returns the owner of this decoder.
+     * @return the owner of this decoder
+     */
+    public Object getOwner() {
+        return owner;
     }
 
-    private void handleException(Exception e) {
-        if (exceptionListener != null) {
-            exceptionListener.exceptionThrown(e);
+    /**
+     * Reads the next object.
+     *
+     * @return the next object
+     * @exception ArrayIndexOutOfBoundsException if no more objects to read
+     */
+    public Object readObject() {
+        if (readObjIndex >= readObjs.size()) {
+            throw new ArrayIndexOutOfBoundsException("no more objects to read");
+        }
+        Elem elem = (Elem) readObjs.get(readObjIndex);
+        if (!elem.isClosed) {
+            // bad element, error occured while parsing
+            throw new ArrayIndexOutOfBoundsException("no more objects to read");
         }
+        readObjIndex++;
+        return elem.result;
     }
 
-    private void initialize() {
-        ClassLoader oldCL = null;
-        
-        try {
-            String saxParserClassName = System
-                    .getProperty("org.xml.sax.driver"); //$NON-NLS-1$
-
-            if (saxParserClassName == null) {
-                saxParserClassName = "org.apache.xerces.parsers.SAXParser"; //$NON-NLS-1$
-            }
-            XMLReader xmlReader = XMLReaderFactory
-                    .createXMLReader(saxParserClassName);
-            xmlReader.setContentHandler(new Handler(this, objects));
-            if (classLoader != null) {
-                oldCL = Thread.currentThread().getContextClassLoader();
-                Thread.currentThread().setContextClassLoader(classLoader);
-            }
-            xmlReader.parse(new InputSource(is));
-            if (classLoader != null) {
-                Thread.currentThread().setContextClassLoader(oldCL);
-            }
-        } catch (SAXException saxe) {
-            saxe.printStackTrace();
-            handleException(saxe);
-        } catch (IOException ioe) {
-            ioe.printStackTrace();
-            handleException(ioe);
-        } finally {
-            iterator = objects.iterator();
+    /**
+     * Sets the exception listener.
+     *
+     * @param listener  an exception listener
+     */
+    public void setExceptionListener(ExceptionListener listener) {
+        if (listener != null) {
+            this.listener = listener;
         }
     }
+
+    /**
+     * Sets the owner of this decoder.
+     *
+     * @param owner     the owner of this decoder
+     */
+    public void setOwner(Object owner) {
+        this.owner = owner;
+    }
 }
+
+

Modified: harmony/enhanced/classlib/trunk/modules/beans/src/main/java/org/apache/harmony/beans/java_lang_reflect_MethodPersistenceDelegate.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/beans/src/main/java/org/apache/harmony/beans/java_lang_reflect_MethodPersistenceDelegate.java?view=diff&rev=556525&r1=556524&r2=556525
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/beans/src/main/java/org/apache/harmony/beans/java_lang_reflect_MethodPersistenceDelegate.java (original)
+++ harmony/enhanced/classlib/trunk/modules/beans/src/main/java/org/apache/harmony/beans/java_lang_reflect_MethodPersistenceDelegate.java Sun Jul 15 23:52:30 2007
@@ -32,7 +32,7 @@
         assert oldInstance instanceof Method : oldInstance;
         Method oldMethod = (Method) oldInstance;
         Class<?> declClass = oldMethod.getDeclaringClass();
-        return new Expression(oldMethod, declClass, "getDeclaredMethod", //$NON-NLS-1$
+        return new Expression(oldMethod, declClass, "getMethod", //$NON-NLS-1$
                 new Object[] { oldMethod.getName(), oldMethod.getParameterTypes() });
     }
 

Modified: harmony/enhanced/classlib/trunk/modules/beans/src/test/java/org/apache/harmony/beans/tests/java/beans/PersistenceDelegateTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/beans/src/test/java/org/apache/harmony/beans/tests/java/beans/PersistenceDelegateTest.java?view=diff&rev=556525&r1=556524&r2=556525
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/beans/src/test/java/org/apache/harmony/beans/tests/java/beans/PersistenceDelegateTest.java (original)
+++ harmony/enhanced/classlib/trunk/modules/beans/src/test/java/org/apache/harmony/beans/tests/java/beans/PersistenceDelegateTest.java Sun Jul 15 23:52:30 2007
@@ -21,23 +21,22 @@
 import java.beans.Expression;
 import java.beans.PersistenceDelegate;
 import java.beans.Statement;
-
-import java.util.Stack;
+import java.beans.XMLDecoder;
+import java.beans.XMLEncoder;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
 import java.util.EmptyStackException;
+import java.util.Stack;
 
 import junit.framework.TestCase;
 
 import org.apache.harmony.beans.tests.support.mock.MockFoo;
 import org.apache.harmony.beans.tests.support.mock.MockFooStop;
-
-import java.beans.XMLEncoder;
-import java.beans.XMLDecoder;
-import java.io.ByteArrayOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.DataInputStream;
-import java.io.BufferedOutputStream;
-import java.io.IOException;
-import java.lang.reflect.Field;
 /**
  * Test java.beans.PersistenceDelegate
  */
@@ -251,6 +250,23 @@
         assertEquals(value, field);
 		assertEquals(value.getName(), field.getName());
 	}
+    
+    public void test_writeObject_java_lang_reflect_Method() throws SecurityException, NoSuchMethodException{
+        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+        XMLEncoder encoder = new XMLEncoder(new BufferedOutputStream(
+            byteArrayOutputStream));
+        Method method = Bar.class.getMethod("barTalk", (Class[])null);
+
+        encoder.writeObject(method);
+        encoder.close();
+        DataInputStream stream = new DataInputStream(new ByteArrayInputStream(
+                byteArrayOutputStream.toByteArray()));
+        XMLDecoder decoder = new XMLDecoder(stream);
+        Method aMethod = (Method) decoder.readObject();
+        assertEquals(method, aMethod);
+        assertEquals(method.getName(), aMethod.getName());
+        assertEquals("barTalk", aMethod.getName());
+    }
 
     // <--