These modifications are based on the v1 release done on October 7, 2002
(since this is the only "official" release).
---------------------------------------------------------------------
IMPROVEMENT #1 : probably the most important one (already reported in Bug
15724)
---------------------------------------------------------------------
I made this modification after I found out wsdl2java to be extremely slow
with large WSDL files. In my case, the WSDL file had about 150 schema types.
On a Pentium III 700Mhz and 512Mhz, it was taking 15 minutes to generate the
Java stubs. After my code change, it was taking... 10 seconds.
My investigation revealed that 98% of the time was spent figuring out what
are the derived types of a schema type. When you have a somewhat large
object model, this computation was done multiple for a given type. The trick
is obviously to cache this computation for each type.
Class: org.apache.axis.wsdl.symbolTable.Utils
/**
* This method returns a set of all types that are derived
* from this type via an extension of a complexType
*/
public static HashSet getDerivedTypes(TypeEntry type, SymbolTable
symbolTable) {
HashSet types = (HashSet) symbolTable.derivedSets.get(type);
if (types != null)
return types;
types = new HashSet();
symbolTable.derivedSets.put(type, types);
if (type != null && type.getNode() != null) {
getDerivedTypes(type, types, symbolTable);
} else if (Constants.isSchemaXSD(type.getQName().getNamespaceURI())
&&
(type.getQName().getLocalPart().equals("anyType")||
type.getQName().getLocalPart().equals("any"))) {
// All types are derived from anyType
types.addAll(symbolTable.getTypes());
}
return types;
} // getNestedTypes
private static void getDerivedTypes(
TypeEntry type, HashSet types, SymbolTable symbolTable) {
// If all types are in the set, return
if (types.size() == symbolTable.getTypes().size()) {
return;
}
// Search the dictionary for derived types of type
Vector allTypes = symbolTable.getTypes();
Iterator it = allTypes.iterator();
while(it.hasNext()) {
TypeEntry derivedType = (TypeEntry) it.next();
if (derivedType instanceof DefinedType &&
derivedType.getNode() != null &&
!types.contains(derivedType) &&
SchemaUtils.getComplexElementExtensionBase(
derivedType.getNode(),
symbolTable) == type) {
types.add(derivedType);
HashSet derivedTypes = getDerivedTypes(derivedType,
symbolTable);
types.addAll(derivedTypes);
}
}
} // getDerivedTypes
Class: org.apache.axis.wsdl.symbolTable.SymbolTable
public HashMap derivedSets = new HashMap();
---------------------------------------------------------------------
IMPROVEMENT #2 : BeanDeserializerFactory should respect the class
set in deserClass such that Bean deserializer can be
subclassed.
Likewise for BeanSerializerFactory with serClass.
---------------------------------------------------------------------
Class: org.apache.axis.encoding.ser.BeanDeserializerFactory
static final Class[] ctorArgTypes =
{
Class.class,
QName.class,
TypeDesc.class,
java.util.Map.class
};
protected Deserializer getGeneralPurpose(String mechanismType)
{
if ((javaType == null) || (xmlType == null))
return super.getGeneralPurpose(mechanismType);
if (deserClass == EnumDeserializer.class)
return super.getGeneralPurpose(mechanismType);
try
{
Constructor ctor = deserClass.getConstructor(ctorArgTypes);
Object[] args = new Object[] { javaType, xmlType, typeDesc, propertyMap
};
return (Deserializer) ctor.newInstance(args);
}
catch (Exception e)
{
return new BeanDeserializer(javaType, xmlType, typeDesc, propertyMap);
}
}
Class: org.apache.axis.encoding.ser.BeanSerializerFactory
static final Class[] ctorArgTypes =
{
Class.class,
QName.class,
TypeDesc.class,
BeanPropertyDescriptor[].class
};
protected Serializer getGeneralPurpose(String mechanismType)
{
if ((javaType == null) || (xmlType == null))
return super.getGeneralPurpose(mechanismType);
if (serClass == EnumSerializer.class)
return super.getGeneralPurpose(mechanismType);
try
{
Constructor ctor = serClass.getConstructor(ctorArgTypes);
Object[] args = new Object[] { javaType, xmlType, typeDesc,
propertyDescriptor };
return (Serializer) ctor.newInstance(args);
}
catch (Exception e)
{
return new BeanSerializer(javaType, xmlType, typeDesc,
propertyDescriptor);
}
}
---------------------------------------------------------------------
IMPROVEMENT #3 : allow a subclass of Bean serializer to hook his own
BeanPropertyTarget
---------------------------------------------------------------------
Title says it all.
Class: org.apache.axis.encoding.ser.BeanDeserializer
/**
* Deserializer interface called on each child element encountered in
* the XML stream.
* @param namespace is the namespace of the child element
* @param localName is the local name of the child element
* @param prefix is the prefix used on the name of the child element
* @param attributes are the attributes of the child element
* @param context is the deserialization context.
* @return is a Deserializer to use to deserialize a child (must be
* a derived class of SOAPHandler) or null if no deserialization should
* be performed.
*/
public SOAPHandler onStartChild(String namespace,
String localName,
String prefix,
Attributes attributes,
DeserializationContext context)
throws SAXException
{
BeanPropertyDescriptor propDesc = null;
FieldDesc fieldDesc = null;
String encodingStyle =
context.getMessageContext().getEncodingStyle();
boolean isEncoded = Constants.isSOAP_ENC(encodingStyle);
QName elemQName = new QName(namespace, localName);
// The collectionIndex needs to be reset for Beans with multiple
arrays
if ((prevQName == null) || (!prevQName.equals(elemQName))) {
collectionIndex = -1;
}
prevQName = elemQName;
if (typeDesc != null) {
// Lookup the name appropriately (assuming an unqualified
// name for SOAP encoding, using the namespace otherwise)
String fieldName = typeDesc.getFieldNameForElement(elemQName,
isEncoded);
propDesc = (BeanPropertyDescriptor)propertyMap.get(fieldName);
fieldDesc = typeDesc.getFieldByName(fieldName);
}
if (propDesc == null) {
// look for a field by this name.
propDesc = (BeanPropertyDescriptor) propertyMap.get(localName);
}
// try and see if this is an xsd:any namespace="##any" element
before
// reporting a problem
if (propDesc == null) {
// try to put unknown elements into a SOAPElement property, if
// appropriate
propDesc = getAnyPropertyDesc();
if (propDesc != null) {
try {
MessageElement [] curElements =
(MessageElement[])propDesc.get(value);
int length = 0;
if (curElements != null) {
length = curElements.length;
}
MessageElement [] newElements = new
MessageElement[length + 1];
if (curElements != null) {
System.arraycopy(curElements, 0,
newElements, 0, length);
}
MessageElement thisEl = context.getCurElement();
newElements[length] = thisEl;
propDesc.set(value, newElements);
return new SOAPHandler();
} catch (Exception e) {
throw new SAXException(e);
}
}
}
if (propDesc == null) {
// No such field
throw new SAXException(
Messages.getMessage("badElem00", javaType.getName(),
localName));
}
// Get the child's xsi:type if available
QName childXMLType = context.getTypeFromXSITypeAttr(namespace,
localName,
attributes);
String href = attributes.getValue("href");
// If no xsi:type or href, check the meta-data for the field
if (childXMLType == null && fieldDesc != null && href == null) {
childXMLType = fieldDesc.getXmlType();
}
// Get Deserializer for child, default to using DeserializerImpl
Deserializer dSer = getDeserializer(childXMLType,
propDesc.getType(),
href,
context);
// It is an error if the dSer is not found, the base
// deserializer impl is returned so that it can generate the correct
message.
if (dSer == null) {
dSer = new DeserializerImpl();
return (SOAPHandler)dSer;
}
// Register value target
if (propDesc.isWriteable()) {
// If this is an indexed property, and the deserializer we found
// was NOT the ArrayDeserializer, this is a non-SOAP array:
// <bean>
// <field>value1</field>
// <field>value2</field>
// ...
// In this case, we want to use the collectionIndex and make
sure
// the deserialized value for the child element goes into the
// right place in the collection.
if (propDesc.isIndexed() && !(dSer instanceof
ArrayDeserializer)) {
collectionIndex++;
dSer.registerValueTarget(createValueTarget(value,
propDesc,
collectionIndex));
} else {
// If we're here, the element maps to a single field value,
// whether that be a "basic" type or an array, so use the
// normal (non-indexed) BeanPropertyTarget form.
collectionIndex = -1;
dSer.registerValueTarget(createValueTarget(value, propDesc,
-1));
}
}
return (SOAPHandler)dSer;
}
protected Target createValueTarget(Object value, BeanPropertyDescriptor
propDesc, int collectionIndex)
{
return new BeanPropertyTarget(value, propDesc, collectionIndex);
}
_________________________________________________________________
MSN Messenger : discutez en direct avec vos amis !
http://www.msn.fr/msger/default.asp
- RE: Improvements to Axis (among others, performance... Jean-François Cloutier
- RE: Improvements to Axis (among others, perfor... Eric . D . Friedman