gdaniels 2003/08/29 22:20:58
Modified: java/src/org/apache/axis/description TypeDesc.java
Added: java/test/typedesc ComplexBean.java ComplexBean2.java
ComplexBean3.java PackageTests.java SimpleBean.java
SimpleBean2.java TestTypeDescSynch.java build.xml
Log:
Fix http://nagoya.apache.org/bugzilla/show_bug.cgi?id=22819
Thanks to [EMAIL PROTECTED] for the analysis/testcase.
Revision Changes Path
1.35 +16 -7 xml-axis/java/src/org/apache/axis/description/TypeDesc.java
Index: TypeDesc.java
===================================================================
RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/description/TypeDesc.java,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -r1.34 -r1.35
--- TypeDesc.java 31 Jul 2003 06:25:18 -0000 1.34
+++ TypeDesc.java 30 Aug 2003 05:20:58 -0000 1.35
@@ -57,7 +57,6 @@
import org.apache.axis.utils.BeanPropertyDescriptor;
import org.apache.axis.utils.BeanUtils;
-import org.apache.axis.utils.ClassUtils;
import org.apache.axis.utils.Messages;
import org.apache.axis.utils.cache.MethodCache;
@@ -86,6 +85,7 @@
/** Can this instance search for metadata in parents of the type it describes?
*/
private boolean canSearchParents = true;
+ private boolean hasSearchedParents = false;
/**
* Creates a new <code>TypeDesc</code> instance. The type desc can search
@@ -196,7 +196,7 @@
// complete description of their content model in their own
// metadata, per the XML schema rules for
// derivation-by-restriction
- if (canSearchParents && searchParents) {
+ if (canSearchParents && searchParents && !hasSearchedParents) {
// check superclasses if they exist
Class cls = javaClass.getSuperclass();
if (cls != null && !cls.getName().startsWith("java.")) {
@@ -219,6 +219,8 @@
// END FIX http://nagoya.apache.org/bugzilla/show_bug.cgi?id=17188
}
}
+
+ hasSearchedParents = true;
}
return fields;
@@ -465,13 +467,20 @@
// may be a faster way to set the property descriptions than
// using BeanUtils.getPd. But for now calling getPd is sufficient.
if (propertyDescriptors == null) {
- propertyDescriptors = BeanUtils.getPd(javaClass, this);
- if (!lookedForAny) {
- anyDesc = BeanUtils.getAnyContentPD(javaClass);
- lookedForAny = true;
- }
+ makePropertyDescriptors();
}
return propertyDescriptors;
+ }
+
+ private synchronized void makePropertyDescriptors() {
+ if (propertyDescriptors != null)
+ return;
+
+ propertyDescriptors = BeanUtils.getPd(javaClass, this);
+ if (!lookedForAny) {
+ anyDesc = BeanUtils.getAnyContentPD(javaClass);
+ lookedForAny = true;
+ }
}
public BeanPropertyDescriptor getAnyContentDescriptor() {
1.1 xml-axis/java/test/typedesc/ComplexBean.java
Index: ComplexBean.java
===================================================================
package test.typedesc;
import org.apache.axis.description.AttributeDesc;
import org.apache.axis.description.FieldDesc;
import org.apache.axis.description.TypeDesc;
import org.apache.axis.encoding.SimpleType;
import javax.xml.namespace.QName;
public class ComplexBean extends SimpleBean implements java.io.Serializable {
public String c;
public String d;
public String e;
public String f;
private static TypeDesc typeDesc = new TypeDesc(ComplexBean.class);
static {
FieldDesc fd = new AttributeDesc();
fd.setFieldName("c");
fd.setXmlName(new QName("foo", "c"));
typeDesc.addFieldDesc(fd);
fd = new AttributeDesc();
fd.setFieldName("d");
fd.setXmlName(new QName("foo", "d"));
typeDesc.addFieldDesc(fd);
fd = new AttributeDesc();
fd.setFieldName("e");
((AttributeDesc)fd).setAttributeName("ffffff");
fd.setXmlName(new QName("foo", "e"));
typeDesc.addFieldDesc(fd);
fd = new AttributeDesc();
fd.setFieldName("f");
fd.setXmlName(new QName("foo", "f"));
typeDesc.addFieldDesc(fd);
}
public static TypeDesc getTypeDesc() { return typeDesc; }
public ComplexBean() {}
public void setC(String value) {
}
public String getC() {
return null;
}
public void setD(String value) {
}
public String getD() {
return null;
}
public void setE(String value) {
}
public String getE() {
return null;
}
public void setF(String value) {
}
public String getF() {
return null;
}
}
1.1 xml-axis/java/test/typedesc/ComplexBean2.java
Index: ComplexBean2.java
===================================================================
package test.typedesc;
import org.apache.axis.description.AttributeDesc;
import org.apache.axis.description.FieldDesc;
import org.apache.axis.description.TypeDesc;
import org.apache.axis.encoding.SimpleType;
import javax.xml.namespace.QName;
public class ComplexBean2 extends SimpleBean2 implements java.io.Serializable {
public String c;
public String d;
public String e;
private static TypeDesc typeDesc = new TypeDesc(ComplexBean2.class);
static {
FieldDesc fd = new AttributeDesc();
fd.setFieldName("c");
fd.setXmlName(new QName("foo", "c"));
typeDesc.addFieldDesc(fd);
fd = new AttributeDesc();
fd.setFieldName("d");
fd.setXmlName(new QName("foo", "d"));
typeDesc.addFieldDesc(fd);
fd = new AttributeDesc();
fd.setFieldName("e");
((AttributeDesc)fd).setAttributeName("ffffff");
fd.setXmlName(new QName("foo", "e"));
typeDesc.addFieldDesc(fd);
}
public static TypeDesc getTypeDesc() { return typeDesc; }
public ComplexBean2() {}
public void setC(String value) {
}
public String getC() {
return null;
}
public void setD(String value) {
}
public String getD() {
return null;
}
public void setE(String value) {
}
public String getE() {
return null;
}
}
1.1 xml-axis/java/test/typedesc/ComplexBean3.java
Index: ComplexBean3.java
===================================================================
package test.typedesc;
import org.apache.axis.description.AttributeDesc;
import org.apache.axis.description.FieldDesc;
import org.apache.axis.description.TypeDesc;
import org.apache.axis.encoding.SimpleType;
import javax.xml.namespace.QName;
public class ComplexBean3 extends SimpleBean2 implements java.io.Serializable {
public String c;
public String d;
private static TypeDesc typeDesc = new TypeDesc(ComplexBean3.class);
static {
FieldDesc fd = new AttributeDesc();
fd.setFieldName("c");
fd.setXmlName(new QName("foo", "c"));
typeDesc.addFieldDesc(fd);
fd = new AttributeDesc();
fd.setFieldName("d");
fd.setXmlName(new QName("foo", "d"));
typeDesc.addFieldDesc(fd);
}
public static TypeDesc getTypeDesc() { return typeDesc; }
public ComplexBean3() {}
public void setC(String value) {
}
public String getC() {
return null;
}
public void setD(String value) {
}
public String getD() {
return null;
}
}
1.1 xml-axis/java/test/typedesc/PackageTests.java
Index: PackageTests.java
===================================================================
package test.typedesc;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
public class PackageTests extends TestCase {
public PackageTests(String name) {
super(name);
}
public static Test suite() throws Exception {
TestSuite suite = new TestSuite();
suite.addTestSuite(TestTypeDescSynch.class);
return suite;
}
}
1.1 xml-axis/java/test/typedesc/SimpleBean.java
Index: SimpleBean.java
===================================================================
package test.typedesc;
import org.apache.axis.description.AttributeDesc;
import org.apache.axis.description.FieldDesc;
import org.apache.axis.description.TypeDesc;
import org.apache.axis.encoding.SimpleType;
import javax.xml.namespace.QName;
public class SimpleBean implements java.io.Serializable {
public String a;
public String b;
private static TypeDesc typeDesc = new TypeDesc(SimpleBean.class);
static {
FieldDesc fd = new AttributeDesc();
fd.setFieldName("a");
fd.setXmlName(new QName("foo", "a"));
typeDesc.addFieldDesc(fd);
fd = new AttributeDesc();
fd.setFieldName("b");
fd.setXmlName(new QName("foo", "b"));
typeDesc.addFieldDesc(fd);
}
public static TypeDesc getTypeDesc() { return typeDesc; }
public SimpleBean() {}
public void setA(String value) {
}
public String getA() {
return null;
}
public void setB(String value) {
}
public String getB() {
return null;
}
}
1.1 xml-axis/java/test/typedesc/SimpleBean2.java
Index: SimpleBean2.java
===================================================================
package test.typedesc;
import org.apache.axis.description.AttributeDesc;
import org.apache.axis.description.FieldDesc;
import org.apache.axis.description.TypeDesc;
import org.apache.axis.encoding.SimpleType;
import javax.xml.namespace.QName;
public class SimpleBean2 implements java.io.Serializable {
public String a;
public String b;
private static TypeDesc typeDesc = new TypeDesc(SimpleBean2.class);
static {
FieldDesc fd = new AttributeDesc();
fd.setFieldName("a");
fd.setXmlName(new QName("foo", "a"));
typeDesc.addFieldDesc(fd);
fd = new AttributeDesc();
fd.setFieldName("b");
fd.setXmlName(new QName("foo", "b"));
typeDesc.addFieldDesc(fd);
}
public static TypeDesc getTypeDesc() { return typeDesc; }
public SimpleBean2() {}
public void setA(String value) {
}
public String getA() {
return null;
}
public void setB(String value) {
}
public String getB() {
return null;
}
}
1.1 xml-axis/java/test/typedesc/TestTypeDescSynch.java
Index: TestTypeDescSynch.java
===================================================================
package test.typedesc;
import junit.framework.TestCase;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.description.AttributeDesc;
import org.apache.axis.description.TypeDesc;
import org.apache.axis.encoding.ser.BeanSerializerFactory;
import org.apache.axis.encoding.ser.BeanDeserializerFactory;
import javax.xml.namespace.QName;
/**
* Confirm TypeDesc bugs are indeed fixed.
*
* See http://nagoya.apache.org/bugzilla/show_bug.cgi?id=22819 for details
*
* @author [EMAIL PROTECTED]
*/
public class TestTypeDescSynch extends TestCase {
public TestTypeDescSynch(String name) {
super(name);
}
public TestTypeDescSynch() {
super("Test TypeDesc Synch");
}
// with won't fail
public void testFields() throws Exception {
TypeDesc desc= TypeDesc.getTypeDescForClass(ComplexBean2.class);
for (int i=0; i < 10; i++) {
desc.getFields(true);
// Check to make sure we keep to the constant 5 fields (this
// used to grow each time we called getFields(true)).
assertEquals(5, desc.getFields().length);
}
}
// this should fail
public void testFields2() throws Exception {
Service service = new Service();
Call call = (Call)service.createCall();
call.registerTypeMapping(ComplexBean3.class,
new QName("foo2", "bar2"),
BeanSerializerFactory.class,
BeanDeserializerFactory.class,
false);
TypeDesc desc= TypeDesc.getTypeDescForClass(ComplexBean3.class);
assertEquals(4, desc.getFields().length);
}
// this might fail
public void testSynch() throws Exception {
int threads = 30;
ThreadTest[] thread = new ThreadTest[threads];
for (int i=0;i<threads;i++) {
thread[i] = new ThreadTest();
thread[i].start();
}
Throwable ex = null;
for (int i=0;i<threads;i++) {
thread[i].join();
if (ex == null && thread[i].getException() != null) {
ex = thread[i].getException();
}
}
// either assertion will fail or ArrayIndexOutOfBoundException will
// be raised (or it might be ok)
TypeDesc desc= TypeDesc.getTypeDescForClass(ComplexBean.class);
assertEquals(6, desc.getFields().length);
if (ex != null) {
fail(ex.getMessage());
}
}
class ThreadTest extends Thread {
Throwable ex = null;
public Throwable getException() {
return this.ex;
}
public void run() {
try {
/*
Service service = new Service();
Call call = (Call)service.createCall();
call.registerTypeMapping(ComplexBean.class,
new QName("foo", "bar"),
BeanSerializerFactory.class,
BeanDeserializerFactory.class,
false);
*/
// this - demonstrates the same problem as above
// just can check the ArrayIndexOutOfBoundsException
BeanSerializerFactory f =
new BeanSerializerFactory(ComplexBean.class,
new QName("foo", "bar"));
} catch (Exception e) {
ex = e;
}
}
}
public static void main(String args[])
{
try {
TestTypeDescSynch tester = new TestTypeDescSynch("TypeDesc Test");
tester.testSynch();
tester.testFields();
} catch (Exception e) {
e.printStackTrace();
}
}
}
1.1 xml-axis/java/test/typedesc/build.xml
Index: build.xml
===================================================================
<?xml version="1.0" ?>
<!DOCTYPE project [
<!ENTITY properties SYSTEM "file:../../xmls/properties.xml">
<!ENTITY paths SYSTEM "file:../../xmls/path_refs.xml">
<!ENTITY taskdefs SYSTEM "file:../../xmls/taskdefs.xml">
<!ENTITY taskdefs_post_compile SYSTEM
"file:../../xmls/taskdefs_post_compile.xml">
<!ENTITY targets SYSTEM "file:../../xmls/targets.xml">
]>
<!-- ===================================================================
<description>
Test/Sample Component file for Axis
Notes:
This is a build file for use with the Jakarta Ant build tool.
Prerequisites:
jakarta-ant from http://jakarta.apache.org
Build Instructions:
To compile
ant compile
To execute
ant run
Author:
Matt Seibert [EMAIL PROTECTED]
Copyright:
Copyright (c) 2002-2003 Apache Software Foundation.
</description>
==================================================================== -->
<project default="compile">
<property name="axis.home" location="../../" />
<property name="componentName" value="test/typedesc"/>
&properties;
&paths;
&taskdefs;
&taskdefs_post_compile;
&targets;
<target name="clean">
<echo message="Removing ${build.dir}/classes/${componentName} and
${build.dir}/work/${componentName}" />
<delete dir="${build.dir}/classes/${componentName}"/>
<delete dir="${build.dir}/work/${componentName}"/>
</target>
<target name="copy" depends="setenv"/>
<target name="compile" depends="copy">
<echo message="Compiling test.${componentName}"/>
<javac srcdir="${axis.home}" destdir="${build.dest}" debug="${debug}"
fork="${javac.fork}">
<classpath>
<path refid="classpath"/>
</classpath>
<include name="${componentName}/*.java"/>
</javac>
</target>
<target name="run">
<antcall target="execute-Component" />
</target>
</project>