in axis-rt-core/src/main/java/org/apache/axis/encoding/ser/ArrayDeserializer.java [78:359]
public void onStartElement(String namespace, String localName,
String prefix, Attributes attributes,
DeserializationContext context)
throws SAXException
{
// Deserializing the xml array requires processing the
// xsi:type= attribute, the soapenc:arrayType attribute,
// and the xsi:type attributes of the individual elements.
//
// The xsi:type=<qName> attribute is used to determine the java
// type of the array to instantiate. Axis expects it
// to be set to the generic "soapenc:Array" or to
// a specific qName. If the generic "soapenc:Array"
// specification is used, Axis determines the array
// type by examining the soapenc:arrayType attribute.
//
// The soapenc:arrayType=<qname><dims> is used to determine
// i) the number of dimensions,
// ii) the length of each dimension,
// iii) the default xsi:type of each of the elements.
//
// If the arrayType attribute is missing, Axis assumes
// a single dimension array with length equal to the number
// of nested elements. In such cases, the default xsi:type of
// the elements is determined using the array xsi:type.
//
// The xsi:type attributes of the individual elements of the
// array are used to determine the java type of the element.
// If the xsi:type attribute is missing for an element, the
// default xsi:type value is used.
if (log.isDebugEnabled()) {
log.debug("Enter: ArrayDeserializer::startElement()");
}
soapConstants = context.getSOAPConstants();
// Get the qname for the array type=, set it to null if
// the generic type is used.
QName typeQName = context.getTypeFromAttributes(namespace,
localName,
attributes);
if (typeQName == null) {
typeQName = getDefaultType();
}
if (typeQName != null &&
Constants.equals(Constants.SOAP_ARRAY, typeQName)) {
typeQName = null;
}
// Now get the arrayType value
QName arrayTypeValue = context.getQNameFromString(
Constants.getValue(attributes,
Constants.URIS_SOAP_ENC,
soapConstants.getAttrItemType()));
// The first part of the arrayType expression is
// the default item type qname.
// The second part is the dimension information
String dimString = null;
QName innerQName = null;
String innerDimString = "";
if (arrayTypeValue != null) {
if (soapConstants != SOAPConstants.SOAP12_CONSTANTS) {
// Doing SOAP 1.1
// Array dimension noted like this : [][x]
String arrayTypeValueNamespaceURI =
arrayTypeValue.getNamespaceURI();
String arrayTypeValueLocalPart =
arrayTypeValue.getLocalPart();
int leftBracketIndex =
arrayTypeValueLocalPart.lastIndexOf('[');
int rightBracketIndex =
arrayTypeValueLocalPart.lastIndexOf(']');
if (leftBracketIndex == -1
|| rightBracketIndex == -1
|| rightBracketIndex < leftBracketIndex) {
throw new IllegalArgumentException(
Messages.getMessage("badArrayType00",
"" + arrayTypeValue));
}
dimString =
arrayTypeValueLocalPart.substring(leftBracketIndex + 1,
rightBracketIndex);
arrayTypeValueLocalPart =
arrayTypeValueLocalPart.substring(0, leftBracketIndex);
// If multi-dim array set to soapenc:Array
if (arrayTypeValueLocalPart.endsWith("]")) {
defaultItemType = Constants.SOAP_ARRAY;
int bracket = arrayTypeValueLocalPart.indexOf("[");
innerQName = new QName(arrayTypeValueNamespaceURI,
arrayTypeValueLocalPart.substring(0, bracket));
innerDimString = arrayTypeValueLocalPart.substring(bracket);
} else {
defaultItemType = new QName(arrayTypeValueNamespaceURI,
arrayTypeValueLocalPart);
}
} else {
String arraySizeValue = attributes.getValue(soapConstants.getEncodingURI(), Constants.ATTR_ARRAY_SIZE);
int leftStarIndex = arraySizeValue.lastIndexOf('*');
// Skip to num if any
if (leftStarIndex != -1) {
// "*" => ""
if (leftStarIndex == 0 && arraySizeValue.length() == 1) {
// "* *" => ""
} else if (leftStarIndex == (arraySizeValue.length() - 1)) {
throw new IllegalArgumentException(
Messages.getMessage("badArraySize00",
"" + arraySizeValue));
// "* N" => "N"
} else {
dimString = arraySizeValue.substring(leftStarIndex + 2);
innerQName = arrayTypeValue;
innerDimString = arraySizeValue.substring(0, leftStarIndex + 1);
}
} else {
dimString = arraySizeValue;
}
if (innerDimString == null || innerDimString.length() == 0) {
defaultItemType = arrayTypeValue;
} else {
defaultItemType = Constants.SOAP_ARRAY12;
}
}
}
// If no type QName and no defaultItemType qname, use xsd:anyType
if (defaultItemType == null && typeQName == null) {
Class destClass = context.getDestinationClass();
if (destClass != null && destClass.isArray()) {
// This will get set OK down below...
} else {
defaultItemType = Constants.XSD_ANYTYPE;
}
}
// Determine the class type for the array.
arrayClass = null;
if (typeQName != null) {
arrayClass = context.getTypeMapping().
getClassForQName(typeQName);
}
if (typeQName == null || arrayClass == null) {
// type= information is not sufficient.
// Get an array of the default item type.
Class arrayItemClass = null;
QName compQName = defaultItemType;
// Nested array, use the innermost qname
String dims = "[]";
if (innerQName != null) {
compQName = innerQName;
if (soapConstants == SOAPConstants.SOAP12_CONSTANTS) {
// With SOAP 1.2 Array, we append [] for each * found
int offset = 0;
while ((offset = innerDimString.indexOf('*', offset)) != -1) {
dims += "[]";
offset ++;
}
} else {
// With SOAP 1.1 Array, we can append directly the complete innerDimString
dims += innerDimString;
}
}
// item Class
arrayItemClass = context.getTypeMapping().getClassForQName(compQName);
if (arrayItemClass != null) {
try {
// Append the dimension found to the classname computed from the itemClass
// to form the array classname
//
String loadableArrayClassName = JavaUtils.getLoadableClassName(
JavaUtils.getTextClassName(arrayItemClass.getName()) + dims);
arrayClass = ClassUtils.forName(loadableArrayClassName,
true,
arrayItemClass.getClassLoader());
} catch (Exception e) {
throw new SAXException(
Messages.getMessage("noComponent00",
"" + defaultItemType));
}
}
}
if (arrayClass == null) {
arrayClass = context.getDestinationClass();
}
if (arrayClass == null) {
throw new SAXException(
Messages.getMessage("noComponent00", "" + defaultItemType));
}
if (dimString == null || dimString.length() == 0) {
// Size determined using length of the members
value = new ArrayListExtension(arrayClass);
} else {
try
{
StringTokenizer tokenizer;
if (soapConstants == SOAPConstants.SOAP12_CONSTANTS) {
tokenizer = new StringTokenizer(dimString);
} else {
tokenizer = new StringTokenizer(dimString, "[],");
}
length = Integer.parseInt(tokenizer.nextToken());
if (tokenizer.hasMoreTokens()) {
// If the array is passed as a multi-dimensional array
// (i.e. int[2][3]) then store all of the
// mult-dim lengths.
// The valueReady method uses this array to set the
// proper mult-dim element.
mDimLength = new ArrayList();
mDimLength.add(new Integer(length));
while(tokenizer.hasMoreTokens()) {
mDimLength.add(
new Integer(
Integer.parseInt(tokenizer.nextToken())));
}
}
// Create an ArrayListExtension class to store the ArrayList
// plus converted objects.
ArrayList list = new ArrayListExtension(arrayClass, length);
// This is expensive as our array may not grown this big.
// Prevents problems when XML claims a huge size
// that it doesn't actually fill.
//for (int i = 0; i < length; i++) {
// list.add(null);
//}
value = list;
}
catch (NumberFormatException e)
{
throw new IllegalArgumentException(
Messages.getMessage("badInteger00", dimString));
}
}
// If soapenc:offset specified, set the current index accordingly
String offset = Constants.getValue(attributes,
Constants.URIS_SOAP_ENC,
Constants.ATTR_OFFSET);
if (offset != null) {
if (soapConstants == SOAPConstants.SOAP12_CONSTANTS) {
throw new SAXException(Messages.getMessage("noSparseArray"));
}
int leftBracketIndex = offset.lastIndexOf('[');
int rightBracketIndex = offset.lastIndexOf(']');
if (leftBracketIndex == -1
|| rightBracketIndex == -1
|| rightBracketIndex < leftBracketIndex)
{
throw new SAXException(
Messages.getMessage("badOffset00", offset));
}
curIndex =
convertToIndex(offset.substring(leftBracketIndex + 1,
rightBracketIndex),
"badOffset00");
}
if (log.isDebugEnabled()) {
log.debug("Exit: ArrayDeserializer::startElement()");
}
}