Package org.apache.woden.internal

Source Code of org.apache.woden.internal.DOMWSDLReader$WSDLEntityResolver

/**
* 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 &lt;import&gt; or &lt;include&gt; 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;
    }
     
    }
   
}
TOP

Related Classes of org.apache.woden.internal.DOMWSDLReader$WSDLEntityResolver

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.