Author: zhoukevin
Date: Wed Apr 7 07:26:43 2010
New Revision: 931455
URL: http://svn.apache.org/viewvc?rev=931455&view=rev
Log:
Apply patch for HARMONY-5975: java.beans.XMLEncoder encodes the static field with customized
persistence delegate.
Additionally, repeated invoking to XMLEncoder.writeObject(o) method should write the corresponding
number of object before flush().
Added:
harmony/enhanced/java/trunk/classlib/modules/beans/src/test/resources/xml/StaticField.xml
Modified:
harmony/enhanced/java/trunk/classlib/modules/beans/src/main/java/java/beans/XMLEncoder.java
harmony/enhanced/java/trunk/classlib/modules/beans/src/test/java/org/apache/harmony/beans/tests/java/beans/XMLEncoderTest.java
Modified: harmony/enhanced/java/trunk/classlib/modules/beans/src/main/java/java/beans/XMLEncoder.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/java/trunk/classlib/modules/beans/src/main/java/java/beans/XMLEncoder.java?rev=931455&r1=931454&r2=931455&view=diff
==============================================================================
--- harmony/enhanced/java/trunk/classlib/modules/beans/src/main/java/java/beans/XMLEncoder.java
(original)
+++ harmony/enhanced/java/trunk/classlib/modules/beans/src/main/java/java/beans/XMLEncoder.java
Wed Apr 7 07:26:43 2010
@@ -18,20 +18,20 @@
package java.beans;
-import java.awt.SystemColor;
-import java.awt.font.TextAttribute;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
-import org.apache.harmony.awt.internal.nls.Messages;
+import org.apache.harmony.beans.internal.nls.Messages;
/**
* <code>XMLEncoder</code> extends <code>Encoder</code> to write
out the
@@ -96,6 +96,8 @@ public class XMLEncoder extends Encoder
private ReferenceMap records = new ReferenceMap();
+ private ReferenceMap cache = new ReferenceMap();
+
private boolean writingObject = false;
/**
@@ -171,6 +173,7 @@ public class XMLEncoder extends Encoder
// clear statement records
records.clear();
flushPendingStat.clear();
+ cache.clear();
// remove all old->new mappings
super.clear();
@@ -242,27 +245,34 @@ public class XMLEncoder extends Encoder
@SuppressWarnings("nls")
private void flushExpression(Object obj, Record rec, int indent,
- boolean asStatement) {
- // not first time, use idref
- if (rec.id != null) {
- flushIndent(indent);
- out.print("<object idref=\"");
- out.print(rec.id);
- out.println("\" />");
- return;
- }
+ boolean asStatement) {
+ // flush
+ Statement stat = asStatement ? new Statement(rec.exp.getTarget(),
+ rec.exp.getMethodName(), rec.exp.getArguments()) : rec.exp;
+ if (isStaticConstantsSupported
+ && "getField".equals(stat.getMethodName())) {
+ flushStatField(stat, indent);
+ return;
+ }
- // generate id, if necessary
- if (rec.refCount > 1) {
- rec.id = nameForClass(obj.getClass()) + idSerialNo;
- idSerialNo++;
- }
+ // not first time, use idref
+ if (rec.id != null) {
+ flushIndent(indent);
+ out.print("<object idref=\"");
+ out.print(rec.id);
+ out.println("\" />");
+ return;
+ }
- // flush
- Statement stat = asStatement ? new Statement(rec.exp.getTarget(),
- rec.exp.getMethodName(), rec.exp.getArguments()) : rec.exp;
- flushStatement(stat, rec.id, rec.stats, indent);
- }
+ // generate id, if necessary
+ if (rec.refCount > 1) {
+ rec.id = nameForClass(obj.getClass()) + idSerialNo;
+ idSerialNo++;
+ }
+
+ // flush
+ flushStatement(stat, rec.id, rec.stats, indent);
+ }
private void flushIndent(int indent) {
for (int i = 0; i < indent; i++) {
@@ -449,7 +459,7 @@ public class XMLEncoder extends Encoder
if (isStaticConstantsSupported
&& "getField".equals(stat.getMethodName())) {
- flushStatField(stat, id, indent);
+ flushStatField(stat, indent);
return;
}
@@ -457,48 +467,46 @@ public class XMLEncoder extends Encoder
flushStatCommon(stat, id, subStats, indent);
}
- @SuppressWarnings("nls")
- private void flushStatField(Statement stat, String id,
- int indent) {
- // open tag, begin
- flushIndent(indent);
- String tagName = "object";
- out.print("<");
- out.print(tagName);
-
- // id attribute
- if (id != null) {
- out.print(" id=\"");
- out.print(id);
- out.print("\"");
- }
-
- // special class attribute
- if (stat.getTarget() instanceof Class) {
- out.print(" class=\"");
- out.print(((Class) stat.getTarget()).getName());
- out.print("\"");
- }
+ @SuppressWarnings("nls")
+ private void flushStatField(Statement stat, int indent) {
+ // open tag, begin
+ flushIndent(indent);
+ out.print("<object");
+
+ // special class attribute
+ Object target = stat.getTarget();
+ if (target instanceof Class<?>) {
+ out.print(" class=\"");
+ out.print(((Class<?>) target).getName());
+ out.print("\"");
+ }
- Object target = stat.getTarget();
- if(target == SystemColor.class || target == TextAttribute.class) {
- out.print(" field=\"");
- out.print(stat.getArguments()[0]);
- out.print("\"");
- out.println("/>");
+ Field field = null;
+ if (target instanceof Class<?> && stat.getArguments().length == 1
+ && stat.getArguments()[0] instanceof String) {
+ try {
+ field = ((Class<?>) target).getField((String) stat
+ .getArguments()[0]);
+ } catch (Exception e) {
+ // ignored
+ }
+ }
- }
- else {
- out.print(" method=\"");
- out.print(stat.getMethodName());
- out.print("\"");
- out.println(">");
- Object fieldName = stat.getArguments()[0];
- flushObject(fieldName, indent + INDENT_UNIT);
- flushIndent(indent);
- out.println("</object>");
- }
- }
+ if (field != null && Modifier.isStatic(field.getModifiers())) {
+ out.print(" field=\"");
+ out.print(stat.getArguments()[0]);
+ out.print("\"");
+ out.println("/>");
+ } else {
+ out.print(" method=\"");
+ out.print(stat.getMethodName());
+ out.print("\"");
+ out.println(">");
+ flushObject(stat.getArguments()[0], indent + INDENT_UNIT);
+ flushIndent(indent);
+ out.println("</object>");
+ }
+ }
@SuppressWarnings("nls")
private void flushStatGetterSetter(Statement stat, String id,
@@ -909,36 +917,49 @@ public class XMLEncoder extends Encoder
* Records the object so that it can be written out later, then calls super
* implementation.
*/
- @Override
+ @Override
public void writeObject(Object o) {
- synchronized (this) {
- boolean oldWritingObject = writingObject;
- writingObject = true;
- try {
- super.writeObject(o);
- } finally {
- writingObject = oldWritingObject;
- }
+ synchronized (this) {
+ boolean oldWritingObject = writingObject;
+ writingObject = true;
+ try {
+ super.writeObject(o);
+ } finally {
+ writingObject = oldWritingObject;
+ }
- // root object?
- if (!writingObject) {
- // add to pending
- flushPending.addAll(flushPrePending);
- flushPendingStat.addAll(flushPrePending);
- flushPrePending.clear();
- if (flushPending.contains(o)) {
- flushPrePending.remove(o);
- flushPendingStat.remove(o);
- } else {
- flushPending.add(o);
- }
- if (needOwner) {
- this.flushPending.remove(owner);
- this.flushPending.add(0, owner);
- }
- }
- }
- }
+ // root object?
+ if (!writingObject) {
+ boolean isCached;
+ ArrayList<Object> pending = (ArrayList<Object>) cache.get(o);
+ if (isCached = (pending != null)) {
+ flushPrePending.clear();
+ flushPrePending.addAll(pending);
+ } else {
+ if (o != null) {
+ pending = new ArrayList<Object>();
+ pending.addAll(flushPrePending);
+ cache.put(o, pending);
+ }
+ }
+
+ // add to pending
+ flushPending.addAll(flushPrePending);
+ flushPendingStat.addAll(flushPrePending);
+ flushPrePending.clear();
+
+ if (!isCached && flushPending.contains(o)) {
+ flushPendingStat.remove(o);
+ } else {
+ flushPending.add(o);
+ }
+ if (needOwner) {
+ this.flushPending.remove(owner);
+ this.flushPending.add(0, owner);
+ }
+ }
+ }
+ }
/**
* Records the statement so that it can be written out later, then calls
Modified: harmony/enhanced/java/trunk/classlib/modules/beans/src/test/java/org/apache/harmony/beans/tests/java/beans/XMLEncoderTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/java/trunk/classlib/modules/beans/src/test/java/org/apache/harmony/beans/tests/java/beans/XMLEncoderTest.java?rev=931455&r1=931454&r2=931455&view=diff
==============================================================================
--- harmony/enhanced/java/trunk/classlib/modules/beans/src/test/java/org/apache/harmony/beans/tests/java/beans/XMLEncoderTest.java
(original)
+++ harmony/enhanced/java/trunk/classlib/modules/beans/src/test/java/org/apache/harmony/beans/tests/java/beans/XMLEncoderTest.java
Wed Apr 7 07:26:43 2010
@@ -17,6 +17,8 @@
package org.apache.harmony.beans.tests.java.beans;
+import java.awt.SystemColor;
+import java.awt.font.TextAttribute;
import java.beans.DefaultPersistenceDelegate;
import java.beans.Encoder;
import java.beans.ExceptionListener;
@@ -46,8 +48,6 @@ import org.apache.harmony.beans.tests.su
import org.apache.harmony.beans.tests.support.mock.MockBean4Codec;
import org.apache.harmony.beans.tests.support.mock.MockBean4Owner_Owner;
import org.apache.harmony.beans.tests.support.mock.MockBean4Owner_Target;
-import org.apache.harmony.beans.tests.support.mock.MockBean4StaticField;
-import org.apache.harmony.beans.tests.support.mock.MockBean4StaticField_PD;
import org.apache.harmony.beans.tests.support.mock.MockTreeMapClass;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
@@ -410,7 +410,18 @@ public class XMLEncoderTest extends Test
private void assertCodedXML(Object obj, String xmlFile,
ByteArrayOutputStream temp, XMLEncoder enc) throws Exception {
+ if (enc == null || temp == null) {
+ temp = new ByteArrayOutputStream();
+ enc = new XMLEncoder(temp);
+ }
+ enc.writeObject(obj);
+ enc.close();
+
+ assertXMLContent(obj, temp.toByteArray(), xmlFile);
+
+ }
+ private void assertXMLContent(Object obj, byte[] bytes, String xmlFile) throws Exception
{
InputStream refIn;
InputStreamReader xml;
@@ -420,14 +431,6 @@ public class XMLEncoderTest extends Test
TestEventHandler refHandler = new TestEventHandler();
String saxParserClassName = System.getProperty("org.xml.sax.driver");
String version = System.getProperty("java.version");
-
- if (enc == null || temp == null) {
- temp = new ByteArrayOutputStream();
- enc = new XMLEncoder(temp);
- }
- enc.writeObject(obj);
- enc.close();
- byte bytes[] = temp.toByteArray();
xml = new InputStreamReader(new ByteArrayInputStream(bytes), "UTF-8");
refIn = XMLEncoderTest.class.getResourceAsStream(xmlFile);
if (refIn == null) {
@@ -834,6 +837,38 @@ public class XMLEncoderTest extends Test
return false;
}
+ }
+ public void testWriteObject_StaticFields() throws Exception {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ XMLEncoder xmlEncoder = new XMLEncoder(bos);
+ xmlEncoder.setPersistenceDelegate(MockObject.class,
+ new MockObjectPersistenceDelegate());
+ xmlEncoder.writeObject(MockObject.inst);
+ xmlEncoder.writeObject(MockObject.inst);
+ xmlEncoder.writeObject(SystemColor.activeCaption);
+ xmlEncoder.writeObject(SystemColor.activeCaption);
+ xmlEncoder.writeObject(TextAttribute.FAMILY);
+ xmlEncoder.writeObject(TextAttribute.FAMILY);
+ xmlEncoder.close();
+ assertXMLContent(null, bos.toByteArray(), "/xml/StaticField.xml");
+ }
+
+ public static class MockObject {
+ public static MockObject inst = new MockObject();
+ }
+
+ public static class MockObjectPersistenceDelegate extends
+ PersistenceDelegate {
+ protected Expression instantiate(Object oldInstance, Encoder enc) {
+ Expression exp = null;
+ try {
+ exp = new Expression(MockObject.class.getField("inst"), "get",
+ new Object[] { null });
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return exp;
+ }
}
-}
+}
\ No newline at end of file
Added: harmony/enhanced/java/trunk/classlib/modules/beans/src/test/resources/xml/StaticField.xml
URL: http://svn.apache.org/viewvc/harmony/enhanced/java/trunk/classlib/modules/beans/src/test/resources/xml/StaticField.xml?rev=931455&view=auto
==============================================================================
--- harmony/enhanced/java/trunk/classlib/modules/beans/src/test/resources/xml/StaticField.xml
(added)
+++ harmony/enhanced/java/trunk/classlib/modules/beans/src/test/resources/xml/StaticField.xml
Wed Apr 7 07:26:43 2010
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<java version="${version}" class="java.beans.XMLDecoder">
+ <object class="org.apache.harmony.beans.tests.java.beans.XMLEncoderTest$MockObject" field="inst"/>
+ <object class="org.apache.harmony.beans.tests.java.beans.XMLEncoderTest$MockObject" field="inst"/>
+ <object class="java.awt.SystemColor" field="activeCaption"/>
+ <object class="java.awt.SystemColor" field="activeCaption"/>
+ <object class="java.awt.font.TextAttribute" field="FAMILY"/>
+ <object class="java.awt.font.TextAttribute" field="FAMILY"/>
+</java>
\ No newline at end of file
|