Java tutorial
/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.woden.internal; import java.io.IOException; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.Hashtable; import java.util.Map; import javax.xml.namespace.QName; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.woden.ErrorReporter; import org.apache.woden.WSDLException; import org.apache.woden.WSDLReader; import org.apache.woden.WSDLSource; import org.apache.woden.XMLElement; import org.apache.woden.internal.resolver.DOMSchemaResolverAdapter; import org.apache.woden.internal.resolver.EntityResolverAdapter; import org.apache.woden.internal.schema.ImportedSchemaImpl; import org.apache.woden.internal.schema.InlinedSchemaImpl; import org.apache.woden.internal.schema.SchemaConstants; import org.apache.woden.internal.util.StringUtils; import org.apache.woden.internal.wsdl20.Constants; import org.apache.woden.internal.wsdl20.validation.WSDLComponentValidator; import org.apache.woden.internal.wsdl20.validation.WSDLDocumentValidator; import org.apache.woden.internal.wsdl20.validation.WSDLValidator; import org.apache.woden.internal.xpointer.DOMXMLElementEvaluator; import org.apache.woden.schema.Schema; import org.apache.woden.wsdl20.Description; import org.apache.woden.wsdl20.extensions.ExtensionRegistry; import org.apache.woden.wsdl20.xml.DescriptionElement; import org.apache.woden.wsdl20.xml.ImportElement; import org.apache.woden.wsdl20.xml.IncludeElement; import org.apache.woden.wsdl20.xml.TypesElement; import org.apache.woden.wsdl20.xml.WSDLElement; import org.apache.woden.xml.XMLAttr; import org.apache.woden.xpointer.InvalidXPointerException; import org.apache.woden.xpointer.XPointer; import org.apache.ws.commons.schema.XmlSchema; import org.apache.ws.commons.schema.XmlSchemaCollection; import org.apache.ws.commons.schema.XmlSchemaException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.xml.sax.EntityResolver; import org.xml.sax.ErrorHandler; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; /** * Implements the WSDLReader behaviour for DOM-based parsing. * * @author John Kaputin (jkaputin@apache.org) */ public class DOMWSDLReader extends BaseWSDLReader { private static final String emptyString = "".intern(); static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage"; static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema"; static final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource"; // TODO: This external schema location should be removed once an URI resolution framework // with a catalog is added to Woden. static final String WSDL120_SCHEMA_SOURCE = "http://www.w3.org/2007/03/wsdl/wsdl20.xsd"; static final String WSDL120_EXTENSIONS_SCHEMA_SOURCE = "http://www.w3.org/2007/03/wsdl/wsdl20-extensions.xsd"; static final String W3C_XML_SCHEMA_SCHEMA_SOURCE = "http://www.w3.org/2001/XMLSchema.xsd"; static final String[] schemas = { WSDL120_SCHEMA_SOURCE, WSDL120_EXTENSIONS_SCHEMA_SOURCE, W3C_XML_SCHEMA_SCHEMA_SOURCE, }; /** SLF based logger. */ private static final Log logger = LogFactory.getLog(DOMWSDLReader.class); //a map of imported schema definitions keyed by schema location URI private Map fImportedSchemas = new Hashtable(); /** * WSDL document validator. Only one instance is needed. */ private WSDLDocumentValidator docValidator = null; /** * WSDL component validator. Only one instance is needed. */ private WSDLComponentValidator compValidator = null; DOMWSDLReader(WSDLContext wsdlContext) throws WSDLException { super(wsdlContext); } /* ************************************************************ * API public methods * ************************************************************/ /* (non-Javadoc) * @see org.apache.woden.WSDLReader#createWSDLSource() */ public WSDLSource createWSDLSource() { return new DOMWSDLSource(getErrorReporter()); } /* * @see org.apache.woden.WSDLReader#readWSDL(String) */ public Description readWSDL(String wsdlURI) throws WSDLException { URL url; try { url = StringUtils.getURL(null, wsdlURI); } catch (MalformedURLException e) { String msg = getErrorReporter().getFormattedMessage("WSDL516", new Object[] { wsdlURI }); throw new WSDLException(WSDLException.PARSER_ERROR, msg, e); } String wsdlURL = url.toString(); // ensure InputSource runs thru the URI Resolver InputSource inputSource = new InputSource(resolveURI(wsdlURL)); return readWSDL(wsdlURL, inputSource); } /* (non-Javadoc) * @see org.apache.woden.WSDLReader#readWSDL(org.apache.woden.WSDLSource) */ public Description readWSDL(WSDLSource wsdlSource) throws WSDLException { //TODO decide on how to handle null args in readWSDL methods (e.g. //IllegalArgExc, WSDLExc, return null, etc). Object source = wsdlSource.getSource(); URI baseURI = wsdlSource.getBaseURI(); String wsdlURL = null; if (baseURI != null) { URL url; try { url = StringUtils.getURL(null, baseURI.toString()); } catch (MalformedURLException e) { String msg = getErrorReporter().getFormattedMessage("WSDL516", new Object[] { baseURI.toString() }); throw new WSDLException(WSDLException.PARSER_ERROR, msg, e); } wsdlURL = url.toString(); } if (source instanceof Element) { return readWSDL(wsdlURL, (Element) source); } else if (source instanceof Document) { return readWSDL(wsdlURL, (Document) source); } else if (source instanceof InputSource) { return readWSDL(wsdlURL, (InputSource) source); } else { //This exception is checked in WSDLSource.setSource but we check //again here in case the wrong type of WSDLSource has been used //with this type of WSDLReader. String sourceClass = source.getClass().getName(); String readerClass = this.getClass().getName(); String msg = getErrorReporter().getFormattedMessage("WSDL017", new Object[] { sourceClass, readerClass }); throw new WSDLException(WSDLException.PARSER_ERROR, msg); } } /* * Helper method for readWSDL(WSDLSource) */ private Description readWSDL(String wsdlURL, Element docEl) throws WSDLException { XMLElement descEl = createXMLElement(docEl); DescriptionElement descElem = parseDescription(wsdlURL, descEl, null); Description descComp = descElem.toComponent(); //TODO if schema errors, don't do any further validation (i.e. assertions assume WSDL is schema valid) // Validate the model if validation is enabled. if (features.getValue(WSDLReader.FEATURE_VALIDATION)) { /* if(docValidator == null) { docValidator = new WSDLDocumentValidator(); } if(docValidator.validate(descElem, getErrorReporter())) { if(compValidator == null) { compValidator = new WSDLComponentValidator(); } compValidator.validate(descComp, getErrorReporter()); } */ (new WSDLValidator()).validate(descComp, fWsdlContext); } return descComp; } /* * Helper method for readWSDL(WSDLSource) */ private Description readWSDL(String wsdlURI, Document domDoc) throws WSDLException { //Try to find an element the XPointer points to if a Fragment Identifier exists. URI uri = null; try { uri = new URI(wsdlURI); } catch (URISyntaxException e) { String msg = getErrorReporter().getFormattedMessage("WSDL506", new Object[] { null, wsdlURI }); throw new WSDLException(WSDLException.PARSER_ERROR, msg, e); } String fragment = uri.getFragment(); if (fragment == null) { //No fragment identifier so just use the root element. return readWSDL(wsdlURI, domDoc.getDocumentElement());//Use document root if no WSDL20 root found. } else { XPointer xpointer; try { xpointer = new XPointer(fragment); } catch (InvalidXPointerException e) { String msg = getErrorReporter().getFormattedMessage("WSDL530", new Object[] { fragment, wsdlURI }); throw new WSDLException(WSDLException.PARSER_ERROR, msg, e); } Element root = domDoc.getDocumentElement(); DOMXMLElementEvaluator evaluator = new DOMXMLElementEvaluator(xpointer, root, getErrorReporter()); Element result = evaluator.evaluateElement(); if (result != null) { //Element from XPointer evaluation. return readWSDL(wsdlURI, result); } else { String msg = getErrorReporter().getFormattedMessage("WSDL531", new Object[] { fragment, wsdlURI }); throw new WSDLException(WSDLException.PARSER_ERROR, msg); } } } /* * Helper method for readWSDL(WSDLSource) */ private Description readWSDL(String wsdlURI, InputSource inputSource) throws WSDLException { try { Document wsdlDocument = getDocument(inputSource, wsdlURI); return readWSDL(wsdlURI, wsdlDocument); } catch (IOException e) { String msg = getErrorReporter().getFormattedMessage("WSDL503", new Object[] { wsdlURI }); throw new WSDLException(WSDLException.PARSER_ERROR, msg, e); } } /* ************************************************************ * Parsing methods - e.g. parseXXXX() * ************************************************************/ protected Schema parseSchemaInline(XMLElement schemaEl, DescriptionElement desc) throws WSDLException { InlinedSchemaImpl schema = new InlinedSchemaImpl(); schema.setXMLElement(schemaEl); schema.setId(schemaEl.getAttributeValue(SchemaConstants.ATTR_ID)); String tns = schemaEl.getAttributeValue(SchemaConstants.ATTR_TARGET_NAMESPACE); if (tns != null) { schema.setNamespace(getURI(tns)); } String baseURI = desc.getDocumentBaseURI() != null ? desc.getDocumentBaseURI().toString() : null; XmlSchema schemaDef = null; try { Element domSchemaEl = (Element) schemaEl.getSource(); XmlSchemaCollection xsc = new XmlSchemaCollection(); xsc.setBaseUri(baseURI); // Plug in the selected woden URI Resolver xsc.setSchemaResolver(new DOMSchemaResolverAdapter(getURIResolver(), schemaEl)); schemaDef = xsc.read(domSchemaEl, baseURI); } catch (XmlSchemaException e) { getErrorReporter().reportError(new ErrorLocatorImpl(), //TODO line&col nos. "WSDL521", new Object[] { baseURI }, ErrorReporter.SEVERITY_WARNING, e); } catch (RuntimeException e) { getErrorReporter().reportError(new ErrorLocatorImpl(), //TODO line&col nos. "WSDL521", new Object[] { baseURI }, ErrorReporter.SEVERITY_ERROR, e); } if (schemaDef != null) { schema.setSchemaDefinition(schemaDef); } else { schema.setReferenceable(false); } return schema; } /* * Parse the <xs:import> element and resolve the import to an * XML Schema definition. Failure to retrieve * the schema will only matter if any WSDL components contain elements or * constraints that refer to the schema, and typically this will be * determined later by WSDL validation. So just report any such errors * and return the SchemaImport object (i.e. with a null schema property). * * WSDL 2.0 spec validation: * - namespace attribute is REQUIRED * - imported schema MUST have a targetNamespace * - namespace and targetNamespace MUST be the same * * TODO implement a framework for caching schemas by namespace and resolving xs:import */ protected Schema parseSchemaImport(XMLElement importEl, DescriptionElement desc) throws WSDLException { ImportedSchemaImpl schema = new ImportedSchemaImpl(); schema.setXMLElement(importEl); String importNS = importEl.getAttributeValue(SchemaConstants.ATTR_NAMESPACE); if (importNS != null) { schema.setNamespace(getURI(importNS)); } String schemaLoc = importEl.getAttributeValue(SchemaConstants.ATTR_SCHEMA_LOCATION); if (schemaLoc != null) { schema.setSchemaLocation(getURI(schemaLoc)); } if (schema.getNamespace() == null) { //The namespace attribute is REQUIRED on xs:import, so don't continue. schema.setReferenceable(false); return schema; } XmlSchema schemaDef = null; if (schema.getSchemaLocation() != null) { schemaDef = retrieveSchema(importEl, desc.getDocumentBaseURI(), schemaLoc); } if (schemaDef == null) { //Either there was no schemaLocation or it did not resolve to a schema, //so try to retrieve a schema at the namespace. schemaDef = retrieveSchema(importEl, null, importNS); } if (schemaDef == null) { //Check if any WSDL imports contain a schema with this namespace. //TODO there may be multiple schemas that this namespace import could resolve to. This is a temporary solution pending WODEN- post M7. ImportElement[] imports = desc.getImportElements(); for (int i = 0; i < imports.length; i++) { ImportElement importElem = (ImportElement) imports[i]; DescriptionElement nestedDesc = importElem.getDescriptionElement(); if (nestedDesc != null) { TypesElement typesElem = nestedDesc.getTypesElement(); if (typesElem != null) { Schema[] schemas = typesElem.getSchemas(schema.getNamespace()); for (int j = 0; j < schemas.length; j++) { Schema s = (Schema) schemas[i]; XmlSchema x = s.getSchemaDefinition(); if (x != null) { schemaDef = x; break; } } } } } } if (schemaDef == null) { //Check if any WSDL includes contain a schema with this namespace. //TODO there may be multiple schemas that this namespace import could resolve to. This is a temporary solution pending WODEN- post M7. IncludeElement[] includes = desc.getIncludeElements(); for (int i = 0; i < includes.length; i++) { IncludeElement includeElem = (IncludeElement) includes[i]; DescriptionElement nestedDesc = includeElem.getDescriptionElement(); if (nestedDesc != null) { TypesElement typesElem = nestedDesc.getTypesElement(); if (typesElem != null) { Schema[] schemas = typesElem.getSchemas(schema.getNamespace()); for (int j = 0; j < schemas.length; j++) { Schema s = (Schema) schemas[i]; XmlSchema x = s.getSchemaDefinition(); if (x != null) { schemaDef = x; break; } } } } } } if (schemaDef != null) { schema.setSchemaDefinition(schemaDef); } else { schema.setReferenceable(false); } return schema; } protected void parseExtensionAttributes(XMLElement extEl, Class wsdlClass, WSDLElement wsdlObj, DescriptionElement desc) throws WSDLException { Element domEl = (Element) extEl.getSource(); NamedNodeMap nodeMap = domEl.getAttributes(); int length = nodeMap.getLength(); for (int i = 0; i < length; i++) { Attr domAttr = (Attr) nodeMap.item(i); String localName = domAttr.getLocalName(); String namespaceURI = domAttr.getNamespaceURI(); String prefix = domAttr.getPrefix(); QName attrType = new QName(namespaceURI, localName, (prefix != null ? prefix : emptyString)); String attrValue = domAttr.getValue(); if (namespaceURI != null && !namespaceURI.equals(Constants.NS_STRING_WSDL20)) { if (!namespaceURI.equals(Constants.NS_STRING_XMLNS) && !namespaceURI.equals(Constants.NS_STRING_XSI)) //TODO handle xsi attrs elsewhere, without need to register { //TODO reg namespaces at appropriate element scope, not just at desc. //DOMUtils.registerUniquePrefix(prefix, namespaceURI, desc); ExtensionRegistry extReg = fWsdlContext.extensionRegistry; XMLAttr xmlAttr = extReg.createExtAttribute(wsdlClass, attrType, extEl, attrValue); if (xmlAttr != null) //TODO use an 'UnknownAttr' class in place of null { wsdlObj.setExtensionAttribute(attrType, xmlAttr); } } else { //TODO parse xmlns namespace declarations - here or elsewhere? } } else { //TODO confirm non-native attrs in WSDL 2.0 namespace will be detected by schema validation, //so no need to handle error here. } } } /* ************************************************************ * Utility/helper methods * ************************************************************/ /* (non-Javadoc) * @see org.apache.woden.internal.BaseWSDLReader#createXMLElement(java.lang.Object) */ protected XMLElement createXMLElement(Object elem) { DOMXMLElement domXMLElement = new DOMXMLElement(getErrorReporter()); domXMLElement.setSource(elem); return domXMLElement; } //TODO when refactoring DOMWSDLReader into BaseWSDLReader, make this method abstract in BaseWSDLReader //and keep this concrete implementation in DOMWSDLReader. protected void parseNamespaceDeclarations(XMLElement xmlElem, WSDLElement wsdlElem) throws WSDLException { Element elem = (Element) xmlElem.getSource(); NamedNodeMap attrs = elem.getAttributes(); int size = attrs.getLength(); for (int i = 0; i < size; i++) { Attr attr = (Attr) attrs.item(i); String namespaceURI = attr.getNamespaceURI(); String localPart = attr.getLocalName(); String value = attr.getValue(); if ((Constants.NS_STRING_XMLNS).equals(namespaceURI)) { if (!(Constants.ATTR_XMLNS).equals(localPart)) { wsdlElem.addNamespace(localPart, getURI(value)); //a prefixed namespace } else { wsdlElem.addNamespace(null, getURI(value)); //the default namespace } } } } protected void parseSchemaForXMLSchema(DescriptionElement desc) throws WSDLException { // Parse the schema for schema to include the built in schema types in the Woden model. // TODO: As there are a finite number of built in schema types it may be better to create // constants rather than reading the schema for schema on the creation of every model. // Also, this method currently requires that the schema elements exist in the types element. // This may not be the best idea as it may imply that this schema contains an actual import // statement in a WSDL 2.0 document. This method also does not work for when building the // model programmatically. // This method should be reevaluated at a later point. TypesElement types = desc.getTypesElement(); if (types == null) { types = desc.addTypesElement(); } if (types.getTypeSystem() == null) { types.setTypeSystem(Constants.TYPE_XSD_2001); } try { Document schemaDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); Element schemaElem = schemaDoc.createElementNS(SchemaConstants.NS_STRING_SCHEMA, SchemaConstants.ELEM_IMPORT); schemaElem.setAttribute(SchemaConstants.ATTR_NAMESPACE, SchemaConstants.NS_STRING_SCHEMA); schemaElem.setAttribute(SchemaConstants.ATTR_SCHEMA_LOCATION, resolveURI("http://www.w3.org/2001/XMLSchema.xsd")); XMLElement xmlEl = createXMLElement(schemaElem); desc.getTypesElement().addSchema(parseSchemaImport(xmlEl, desc)); } catch (Exception e) { logger.error("A problem was encountered while creating the build in XML schema types: " + e); } } private XmlSchema retrieveSchema(XMLElement contextElement, URI contextURI, String schemaSpec) throws WSDLException { Document importedSchemaDoc = null; Element schemaEl = null; String schemaLoc = null; URL url = null; try { /* * For simple resolvers, we resolve the parent (Description) URI * to be used as the context. This allows for relative locationURIs * to be resolved implicitly - they are considered to be located * relative to the resolved parent. Therefore, relative URIs such as these * need not be listed in the catalog file. */ /* TODO * OASIS-style catalogs have a convenience notation to define root URIs * thus grouping related URLs together. In this case the context URI here * should be left alone, but the resultant locationURL resolved instead. * * Implement a boolean system property like org.apache.woden.resolver.useRelativeURLs * (set by the resolver ctor). SimpleURIResolver (et al) should set this to true, * OASISCatalogResolver should set to false. */ URL contextURL = (contextURI != null) ? contextURI.toURL() : null; url = StringUtils.getURL(contextURL, schemaSpec); } catch (MalformedURLException e) { String baseLoc = contextURI != null ? contextURI.toString() : null; getErrorReporter().reportError(new ErrorLocatorImpl(), //TODO line&col nos. "WSDL502", new Object[] { baseLoc, schemaLoc }, ErrorReporter.SEVERITY_ERROR); //can't continue schema retrieval with a bad URL. return null; } String schemaURL = url.toString(); //If the schema has already been imported, reuse it. XmlSchema schemaDef = (XmlSchema) fImportedSchemas.get(schemaURL); if (schemaDef == null) { //not previously imported, so retrieve it now. String resolvedLoc = null; try { URI resolvedURI = resolveURI(getURI(schemaURL)); resolvedLoc = resolvedURI.toString(); importedSchemaDoc = getDocument(new InputSource(resolvedLoc), resolvedLoc); } catch (IOException e4) { //schema retrieval failed (e.g. 'not found') getErrorReporter().reportError(new ErrorLocatorImpl(), //TODO line&col nos. "WSDL504", new Object[] { schemaURL }, ErrorReporter.SEVERITY_WARNING, e4); //cannot continue without resolving the URL return null; } schemaEl = importedSchemaDoc.getDocumentElement(); try { //String baseLoc = contextURI != null ? contextURI.toString() : null; String baseLoc = resolvedLoc; XmlSchemaCollection xsc = new XmlSchemaCollection(); xsc.setBaseUri(resolvedLoc); // Plug in the selected woden URI Resolver xsc.setSchemaResolver(new DOMSchemaResolverAdapter(getURIResolver(), contextElement)); schemaDef = xsc.read(schemaEl, baseLoc); fImportedSchemas.put(schemaURL, schemaDef); } catch (XmlSchemaException e) { getErrorReporter().reportError(new ErrorLocatorImpl(), //TODO line&col nos. "WSDL522", new Object[] { schemaURL }, ErrorReporter.SEVERITY_WARNING, e); } } return schemaDef; } // replaced with JAXP API /* private Document getDocument(InputSource inputSource, String desc) throws WSDLException, IOException { //TODO use 'desc' URL in any error message(s) for problem resolution. //DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // //factory.setNamespaceAware(true); DOMParser parser = new DOMParser(); parser.setEntityResolver(new EntityResolverAdapter(getURIResolver())); try { parser.setFeature(org.apache.xerces.impl.Constants.SAX_FEATURE_PREFIX + org.apache.xerces.impl.Constants.NAMESPACES_FEATURE, true); parser.setFeature(org.apache.xerces.impl.Constants.SAX_FEATURE_PREFIX + org.apache.xerces.impl.Constants.NAMESPACE_PREFIXES_FEATURE, true); } catch (SAXNotRecognizedException e) { } catch (SAXNotSupportedException e) { } // Enable validation on the XML parser if it has been enabled // for the Woden parser. if (features.getValue(WSDLReader.FEATURE_VALIDATION)) { //factory.setValidating(true); try { parser.setFeature(org.apache.xerces.impl.Constants.SAX_FEATURE_PREFIX + org.apache.xerces.impl.Constants.VALIDATION_FEATURE, true); parser.setFeature(org.apache.xerces.impl.Constants.XERCES_FEATURE_PREFIX + org.apache.xerces.impl.Constants.SCHEMA_VALIDATION_FEATURE, true); // TODO: This external schema location should be removed once an URI resolution framework // with a catalog is added to Woden. parser .setProperty( org.apache.xerces.impl.Constants.XERCES_PROPERTY_PREFIX + org.apache.xerces.impl.Constants.SCHEMA_LOCATION, "http://www.w3.org/ns/wsdl " + resolveURI("http://www.w3.org/2007/03/wsdl/wsdl20.xsd") + " http://www.w3.org/ns/wsdl-extensions " + resolveURI("http://www.w3.org/2007/03/wsdl/wsdl20-extensions.xsd") + " http://www.w3.org/2001/XMLSchema " + resolveURI("http://www.w3.org/2001/XMLSchema.xsd")); } catch (SAXNotRecognizedException e) { logger.error("validation not supported by parser."); } catch (SAXNotSupportedException e) { } } else { //factory.setValidating(false); } Document doc = null; try { //DocumentBuilder builder = factory.newDocumentBuilder(); //builder.getDOMImplementation().hasFeature(); //builder.setErrorHandler(new ErrorHandlerWrapper(getErrorReporter())); //builder.setEntityResolver(new DefaultHandler()); //doc = builder.parse(inputSource); parser.parse(inputSource); doc = parser.getDocument(); } //catch (ParserConfigurationException e) //{ //String msg = getErrorReporter().getFormattedMessage("WSDL002", new Object[] {"XML"}); //throw new WSDLException(WSDLException.CONFIGURATION_ERROR, msg, e); //} catch (SAXException e) { getErrorReporter().reportError(new ErrorLocatorImpl(), //TODO line&col nos. "WSDL500", new Object[] { "SAX", desc }, ErrorReporter.SEVERITY_FATAL_ERROR, e); } //TODO - potentially returns null. correct after deciding how //to handle exceptions (e.g. return inside try block). return doc; } */ private Document getDocument(InputSource inputSource, String desc) throws WSDLException, IOException { //TODO use 'desc' URL in any error message(s) for problem resolution. Document doc = null; try { DocumentBuilderFactory factory = createDocumentBuilderFactory(true); EntityResolverAdapter entityResolver = new EntityResolverAdapter(getURIResolver()); ErrorHandler errorHandler = new ErrorHandlerWrapper(getErrorReporter()); DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler); doc = builder.parse(inputSource); } catch (ParserConfigurationException e) { String msg = getErrorReporter().getFormattedMessage("WSDL002", new Object[] { "XML" }); throw new WSDLException(WSDLException.CONFIGURATION_ERROR, msg, e); } catch (SAXException e) { getErrorReporter().reportError(new ErrorLocatorImpl(), //TODO line&col nos. "WSDL500", new Object[] { "SAX", desc }, ErrorReporter.SEVERITY_FATAL_ERROR, e); } //TODO - potentially returns null. correct after deciding how //to handle exceptions (e.g. return inside try block). return doc; } /* * Retrieve a WSDL document by resolving the location URI specified * on a WSDL <import> or <include> element. * * TODO add support for a URL Catalog Resolver */ protected DescriptionElement getWSDLFromLocation(String locationURI, DescriptionElement desc, Map wsdlModules) throws WSDLException { DescriptionElement referencedDesc = null; Element docEl; URL locationURL = null; URI contextURI = null; try { /* * For simple resolvers, we resolve the parent (Description) URI * to be used as the context. This allows for relative locationURIs * to be resolved implicitly - they are considered to be located * relative to the resolved parent. Therefore, relative URIs such as these * need not be listed in the catalog file. */ /* TODO * OASIS-style catalogs have a convenience notation to define root URIs * thus grouping related URLs together. In this case the context URI here * should be left alone, but the resultant locationURL resolved instead. * * Implement a boolean system property like org.apache.woden.resolver.useRelativeURLs * (set by the resolver ctor). SimpleURIResolver (et al) should set this to true, * OASISCatalogResolver should set to false. */ // contextURI = desc.getDocumentBaseURI(); contextURI = resolveURI(desc.getDocumentBaseURI()); URL contextURL = (contextURI != null) ? contextURI.toURL() : null; locationURL = StringUtils.getURL(contextURL, locationURI); } catch (MalformedURLException e) { String baseURI = contextURI != null ? contextURI.toString() : null; getErrorReporter().reportError(new ErrorLocatorImpl(), //TODO line&col nos. "WSDL502", new Object[] { baseURI, locationURI }, ErrorReporter.SEVERITY_ERROR); //can't continue import with a bad URL. return null; } String locationStr = locationURL.toString(); //Check if WSDL imported or included previously from this location. referencedDesc = (DescriptionElement) wsdlModules.get(locationStr); if (referencedDesc == null) { //not previously imported or included, so retrieve the WSDL. try { Document doc = getDocument(new InputSource(locationStr), locationStr); docEl = doc.getDocumentElement(); } catch (IOException e) { //document retrieval failed (e.g. 'not found') getErrorReporter().reportError(new ErrorLocatorImpl(), //TODO line&col nos. "WSDL503", new Object[] { locationStr }, ErrorReporter.SEVERITY_WARNING, e); //cannot continue without the referenced document return null; } //The referenced document should contain a WSDL <description> QName docElQN = new QName(docEl.getNamespaceURI(), docEl.getLocalName()); if (!Constants.Q_ELEM_DESCRIPTION.equals(docElQN)) { getErrorReporter().reportError(new ErrorLocatorImpl(), //TODO line&col nos. "WSDL501", new Object[] { Constants.Q_ELEM_DESCRIPTION, docElQN }, ErrorReporter.SEVERITY_ERROR); //cannot continue without a <description> element return null; } XMLElement descEl = createXMLElement(docEl); referencedDesc = parseDescription(locationStr, descEl, wsdlModules); if (!wsdlModules.containsKey(locationStr)) { wsdlModules.put(locationStr, referencedDesc); } } return referencedDesc; } /** * Create the JAXP DocumentBuilderFactory instance.Use JAXP 1.2 API for validation. * @param namespaceAware whether the returned factory is to provide support for XML namespaces * @return the JAXP DocumentBuilderFactory * @throws ParserConfigurationException if we failed to build a proper DocumentBuilderFactory */ protected DocumentBuilderFactory createDocumentBuilderFactory(boolean namespaceAware) throws ParserConfigurationException, WSDLException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(namespaceAware); // Enable validation on the XML parser if it has been enabled // for the Woden parser. if (features.getValue(WSDLReader.FEATURE_VALIDATION)) { factory.setValidating(true); // Enforce namespace aware for XSD... factory.setNamespaceAware(true); try { factory.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA); factory.setAttribute(JAXP_SCHEMA_SOURCE, schemas); } catch (IllegalArgumentException e) { getErrorReporter().reportError(new ErrorLocatorImpl(), //TODO line&col nos. "WSDL515", new Object[] { factory.getClass().getName() }, ErrorReporter.SEVERITY_FATAL_ERROR, e); } } else { factory.setValidating(false); } return factory; } /** * Create a JAXP DocumentBuilder will use for parsing XML documents. * @param factory the JAXP DocumentBuilderFactory that the DocumentBuilder * should be created with * @param entityResolver the SAX EntityResolver to use * @param errorHandler the SAX ErrorHandler to use * @return the JAXP DocumentBuilder * @throws ParserConfigurationException if thrown by JAXP methods */ protected DocumentBuilder createDocumentBuilder(DocumentBuilderFactory factory, EntityResolver entityResolver, ErrorHandler errorHandler) throws ParserConfigurationException { DocumentBuilder docBuilder = factory.newDocumentBuilder(); if (entityResolver != null) { docBuilder.setEntityResolver(entityResolver); } if (errorHandler != null) { docBuilder.setErrorHandler(errorHandler); } return docBuilder; } /** * A wrapper that plugs Woden's error reporter mechanism into the * XML parser used to parse the WSDL document. */ class ErrorHandlerWrapper implements org.xml.sax.ErrorHandler { /** * The error reporter used to report errors in Woden. */ private ErrorReporter errorReporter; /** * Constructor. * * @param errorReporter The error reporter to be wrapped. */ public ErrorHandlerWrapper(ErrorReporter errorReporter) { this.errorReporter = errorReporter; } /* (non-Javadoc) * @see org.xml.sax.ErrorHandler#error(org.xml.sax.SAXParseException) */ public void error(SAXParseException error) throws SAXException { ErrorLocatorImpl locator = new ErrorLocatorImpl(); locator.setLineNumber(error.getLineNumber()); locator.setColumnNumber(error.getColumnNumber()); try { errorReporter.reportError(locator, null, error.getMessage(), ErrorReporter.SEVERITY_ERROR, error.getException()); } catch (WSDLException e) { throw new SAXException("A problem occurred setting the error in the Woden error reporter wrapper.", e); } } /* (non-Javadoc) * @see org.xml.sax.ErrorHandler#fatalError(org.xml.sax.SAXParseException) */ public void fatalError(SAXParseException error) throws SAXException { ErrorLocatorImpl locator = new ErrorLocatorImpl(); locator.setLineNumber(error.getLineNumber()); locator.setColumnNumber(error.getColumnNumber()); try { errorReporter.reportError(locator, null, error.getMessage(), ErrorReporter.SEVERITY_FATAL_ERROR, error.getException()); } catch (WSDLException e) { throw new SAXException("A problem occurred setting the error in the Woden error reporter wrapper.", e); } } /* (non-Javadoc) * @see org.xml.sax.ErrorHandler#warning(org.xml.sax.SAXParseException) */ public void warning(SAXParseException warning) throws SAXException { ErrorLocatorImpl locator = new ErrorLocatorImpl(); locator.setLineNumber(warning.getLineNumber()); locator.setColumnNumber(warning.getColumnNumber()); try { errorReporter.reportError(locator, null, warning.getMessage(), ErrorReporter.SEVERITY_WARNING, warning.getException()); } catch (WSDLException e) { throw new SAXException("A problem occurred setting the error in the Woden error reporter wrapper.", e); } } } class WSDLEntityResolver implements org.xml.sax.EntityResolver { public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { // TODO Auto-generated method stub return null; } } }