* if the user chooses not to register a suitable deserializer then the
* UnknownDeserializer will be used, returning an UnknownExtensibilityElement.
*/
Schema schema = null;
SchemaReference schemaRef = null;
try
{
QName elementType = QNameUtils.newQName(el);
ExtensionDeserializer exDS =
extReg.queryDeserializer(parentType, elementType);
//Now unmarshall the DOM element.
ExtensibilityElement ee =
exDS.unmarshall(parentType, elementType, el, def, extReg);
if (ee instanceof Schema)
{
schema = (Schema) ee;
}
else
{
//Unknown extensibility element, so don't do any more schema parsing on it.
return ee;
}
//Keep track of parsed schemas to avoid duplicating Schema objects
//through duplicate or circular references (eg: A imports B imports A).
if (schema.getDocumentBaseURI() != null)
{
this.allSchemas.put(schema.getDocumentBaseURI(), schema);
}
//At this point, any SchemaReference objects held by the schema will not
//yet point to their referenced schemas, so we must now retrieve these
//schemas and set the schema references.
//First, combine the schema references for imports, includes and redefines
//into a single list
ArrayList allSchemaRefs = new ArrayList();
Collection ic = schema.getImports().values();
Iterator importsIterator = ic.iterator();
while(importsIterator.hasNext())
{
allSchemaRefs.addAll( (Collection) importsIterator.next() );
}
allSchemaRefs.addAll(schema.getIncludes());
allSchemaRefs.addAll(schema.getRedefines());
//Then, retrieve the schema referred to by each schema reference. If the
//schema has been read in previously, use the existing schema object.
//Otherwise unmarshall the DOM element into a new schema object.
ListIterator schemaRefIterator = allSchemaRefs.listIterator();
while(schemaRefIterator.hasNext())
{
try
{
schemaRef = (SchemaReference) schemaRefIterator.next();
if (schemaRef.getSchemaLocationURI() == null)
{
//cannot get the referenced schema, so ignore this schema reference
continue;
}
if (verbose)
{
System.out.println("Retrieving schema at '" +
schemaRef.getSchemaLocationURI() +
(schema.getDocumentBaseURI() == null
? "'."
: "', relative to '" +
schema.getDocumentBaseURI() + "'."));
}
InputStream inputStream = null;
InputSource inputSource = null;
//This is the child schema referred to by the schemaReference
Schema referencedSchema = null;
//This is the child schema's location obtained from the WSDLLocator or the URL
String location = null;
if (loc != null)
{
//Try to get the referenced schema using the wsdl locator
inputSource = loc.getImportInputSource(
schema.getDocumentBaseURI(), schemaRef.getSchemaLocationURI());
if (inputSource == null)
{
throw new WSDLException(WSDLException.OTHER_ERROR,
"Unable to locate with a locator "
+ "the schema referenced at '"
+ schemaRef.getSchemaLocationURI()
+ "' relative to document base '"
+ schema.getDocumentBaseURI() + "'");
}
location = loc.getLatestImportURI();
//if a schema from this location has been read previously, use it.
referencedSchema = (Schema) this.allSchemas.get(location);
}
else
{
// We don't have a wsdl locator, so try to retrieve the schema by its URL
String contextURI = schema.getDocumentBaseURI();
URL contextURL = (contextURI != null) ? StringUtils.getURL(null, contextURI) : null;
URL url = StringUtils.getURL(contextURL, schemaRef.getSchemaLocationURI());
location = url.toExternalForm();
//if a schema from this location has been retrieved previously, use it.
referencedSchema = (Schema) this.allSchemas.get(location);
if (referencedSchema == null)
{
// We haven't read this schema in before so do it now
inputStream = StringUtils.getContentAsInputStream(url);
if (inputStream != null)
{
inputSource = new InputSource(inputStream);
}
if (inputSource == null)
{
throw new WSDLException(WSDLException.OTHER_ERROR,
"Unable to locate with a url "
+ "the document referenced at '"
+ schemaRef.getSchemaLocationURI()
+ "'"
+ (contextURI == null ? "." : ", relative to '"
+ contextURI + "'."));
}
}
} //end if loc
// If we have not previously read the schema, get its DOM element now.
if (referencedSchema == null)
{
inputSource.setSystemId(location);
Document doc = getDocument(inputSource, location);
if (inputStream != null)
{
inputStream.close();
}
Element documentElement = doc.getDocumentElement();
// If it's a schema doc process it, otherwise the schema reference remains null
QName docElementQName = QNameUtils.newQName(documentElement);
if (SchemaConstants.XSD_QNAME_LIST.contains(docElementQName))
{
//We now need to call parseSchema recursively to parse the referenced
//schema. The document base URI of the referenced schema will be set to
//the document base URI of the current schema plus the schemaLocation in
//the schemaRef. We cannot explicitly pass in a new document base URI
//to the schema deserializer, so instead we will create a dummy
//Definition and set its documentBaseURI to the new document base URI.
//We can leave the other definition fields empty because we know
//that the SchemaDeserializer.unmarshall method uses the definition
//parameter only to get its documentBaseURI. If the unmarshall method
//implementation changes (ie: its use of definition changes) we may need
//to rethink this approach.
WSDLFactory factory = getWSDLFactory();
Definition dummyDef = factory.newDefinition();
dummyDef.setDocumentBaseURI(location);
//By this point, we know we have a SchemaDeserializer registered
//so we can safely cast the ExtensibilityElement to a Schema.
referencedSchema = (Schema) parseSchema( parentType,
documentElement,
dummyDef,
extReg);
}
} //end if referencedSchema
schemaRef.setReferencedSchema(referencedSchema);
}
catch (WSDLException e)
{
throw e;
}
catch (RuntimeException e)
{
throw e;
}
catch (Exception e)
{
throw new WSDLException(WSDLException.OTHER_ERROR,
"An error occurred trying to resolve schema referenced at '"
+ schemaRef.getSchemaLocationURI()
+ "'"
+ (schema.getDocumentBaseURI() == null ? "." : ", relative to '"
+ schema.getDocumentBaseURI() + "'."),
e);
}