Index: src/test/java/org/apache/harmony/beans/tests/java/beans/PersistenceDelegateTest.java
===================================================================
--- src/test/java/org/apache/harmony/beans/tests/java/beans/PersistenceDelegateTest.java (revision 555924)
+++ src/test/java/org/apache/harmony/beans/tests/java/beans/PersistenceDelegateTest.java (working copy)
@@ -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());
+ }
// <--
Index: src/main/java/java/beans/PersistenceDelegate.java
===================================================================
--- src/main/java/java/beans/PersistenceDelegate.java (revision 555924)
+++ src/main/java/java/beans/PersistenceDelegate.java (working copy)
@@ -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;
+/**
+ * PersistenceDelegate 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
+ * PersisteneceDelegate 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 @@
}
}
}
+
}
+
Index: src/main/java/java/beans/XMLDecoder.java
===================================================================
--- src/main/java/java/beans/XMLDecoder.java (revision 555924)
+++ src/main/java/java/beans/XMLDecoder.java (working copy)
@@ -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;
+/**
+ * XMLDecoder reads objects from xml created by
+ * XMLEncoder.
+ *