if (value == null)
throw new IOException(Messages.getMessage("cantDoNullArray00"));
MessageContext msgContext = context.getMessageContext();
SchemaVersion schema = SchemaVersion.SCHEMA_2001;
SOAPConstants soap = SOAPConstants.SOAP11_CONSTANTS;
boolean encoded = true;
if (msgContext != null) {
encoded = msgContext.isEncoded();
schema = msgContext.getSchemaVersion();
soap = msgContext.getSOAPConstants();
}
Class cls = value.getClass();
Collection list = null;
if (!cls.isArray()) {
if (!(value instanceof Collection)) {
throw new IOException(
Messages.getMessage("cantSerialize00", cls.getName()));
}
list = (Collection)value;
}
// Get the componentType of the array/list
Class componentType;
if (list == null) {
componentType = cls.getComponentType();
} else {
componentType = Object.class;
}
// Check to see if componentType is also an array.
// If so, set the componentType to the most nested non-array
// componentType. Increase the dims string by "[]"
// each time through the loop.
// Note from Rich Scheuerle:
// This won't handle Lists of Lists or
// arrays of Lists....only arrays of arrays.
String dims = "";
while (componentType.isArray()) {
componentType = componentType.getComponentType();
if (soap == SOAPConstants.SOAP12_CONSTANTS)
dims += "* ";
else
dims += "[]";
}
// Get the QName of the componentType.
// If not found, look at the super classes
QName componentQName = context.getCurrentXMLType();
if (componentQName != null) {
if ((componentQName.equals(xmlType) ||
componentQName.equals(soap.getArrayType()))) {
componentQName = null;
}
}
if (componentQName == null) {
componentQName = context.getQNameForClass(componentType);
}
if (componentQName == null) {
Class searchCls = componentType;
while(searchCls != null && componentQName == null) {
searchCls = searchCls.getSuperclass();
componentQName = context.getQNameForClass(searchCls);
}
if (componentQName != null) {
componentType = searchCls;
}
}
if (componentQName == null) {
throw new IOException(
Messages.getMessage("noType00", componentType.getName()));
}
int len = (list == null) ? Array.getLength(value) : list.size();
String arrayType = "";
int dim2Len = -1;
if (encoded) {
if (soap == SOAPConstants.SOAP12_CONSTANTS)
arrayType = dims + len;
else
arrayType = dims + "[" + len + "]";
// Discover whether array can be serialized directly as a two-dimensional
// array (i.e. arrayType=int[2,3]) versus an array of arrays.
// Benefits:
// - Less text passed on the wire.
// - Easier to read wire format
// - Tests the deserialization of multi-dimensional arrays.
// Drawbacks:
// - Is not safe! It is possible that the arrays are multiply
// referenced. Transforming into a 2-dim array will cause the
// multi-referenced information to be lost. Plus there is no
// way to determine whether the arrays are multi-referenced.
// - .NET currently (Dec 2002) does not support 2D SOAP-encoded arrays
//
// OLD Comment as to why this was ENABLED:
// It is necessary for
// interoperability (echo2DStringArray). It is 'safe' for now
// because Axis treats arrays as non multi-ref (see the note
// in SerializationContextImpl.isPrimitive(...) )
// More complicated processing is necessary for 3-dim arrays, etc.
//
// Axis 1.1 - December 2002
// Turned this OFF because Microsoft .NET can not deserialize
// multi-dimensional SOAP-encoded arrays, and this interopability
// is pretty high visibility. Make it a global configuration parameter:
// <parameter name="enable2DArrayEncoding" value="true"/> (tomj)
//
// Check the message context to see if we should turn 2D processing ON
// Default is OFF
boolean enable2Dim = false;
// Vidyanand : added this check
if( msgContext != null ) {
enable2Dim = JavaUtils.isTrueExplicitly(msgContext.getProperty(
AxisEngine.PROP_TWOD_ARRAY_ENCODING));
}
if (enable2Dim && !dims.equals("")) {
if (cls.isArray() && len > 0) {
boolean okay = true;
// Make sure all of the component arrays are the same size
for (int i=0; i < len && okay; i++) {
Object elementValue = Array.get(value, i);
if (elementValue == null)
okay = false;
else if (dim2Len < 0) {
dim2Len = Array.getLength(elementValue);
if (dim2Len <= 0) {
okay = false;
}
} else if (dim2Len != Array.getLength(elementValue)) {
okay = false;
}
}
// Update the arrayType to use mult-dim array encoding
if (okay) {
dims = dims.substring(0, dims.length()-2);
if (soap == SOAPConstants.SOAP12_CONSTANTS)
arrayType = dims + len + " " + dim2Len;
else
arrayType = dims + "[" + len + "," + dim2Len + "]";
} else {
dim2Len = -1;
}
}
}
}
// Need to distinguish if this is array processing for an
// actual schema array or for a maxOccurs usage.
// For the maxOccurs case, the currentXMLType of the context is
// the same as the componentQName.
boolean maxOccursUsage = !encoded &&
componentQName.equals(context.getCurrentXMLType());
if (encoded) {
AttributesImpl attrs;
if (attributes == null) {
attrs = new AttributesImpl();
} else if (attributes instanceof AttributesImpl) {
attrs = (AttributesImpl)attributes;
} else {
attrs = new AttributesImpl(attributes);
}
String compType = context.attributeQName2String(componentQName);
if (attrs.getIndex(soap.getEncodingURI(), soap.getAttrItemType()) == -1) {
String encprefix =
context.getPrefixForURI(soap.getEncodingURI());
if (soap != SOAPConstants.SOAP12_CONSTANTS) {
compType = compType + arrayType;
attrs.addAttribute(soap.getEncodingURI(),
soap.getAttrItemType(),
encprefix + ":arrayType",
"CDATA",
compType);
} else {
attrs.addAttribute(soap.getEncodingURI(),
soap.getAttrItemType(),
encprefix + ":itemType",
"CDATA",
compType);
attrs.addAttribute(soap.getEncodingURI(),
"arraySize",
encprefix + ":arraySize",
"CDATA",
arrayType);
}