All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.tools.ws.wsdl.parser.Internalizer Maven / Gradle / Ivy

Go to download

Open source Reference Implementation of JSR-224: Java API for XML Web Services

There is a newer version: 4.0.3
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 * 
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License. You can obtain
 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
 * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
 * Sun designates this particular file as subject to the "Classpath" exception
 * as provided by Sun in the GPL Version 2 section of the License file that
 * accompanied this code.  If applicable, add the following below the License
 * Header, with the fields enclosed by brackets [] replaced by your own
 * identifying information: "Portions Copyrighted [year]
 * [name of copyright owner]"
 * 
 * Contributor(s):
 * 
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */
package com.sun.tools.ws.wsdl.parser;

import com.sun.istack.NotNull;
import com.sun.istack.Nullable;
import com.sun.istack.SAXParseException2;
import com.sun.tools.ws.resources.WsdlMessages;
import com.sun.tools.ws.wscompile.ErrorReceiver;
import com.sun.tools.ws.wscompile.WsimportOptions;
import com.sun.tools.ws.wsdl.document.jaxws.JAXWSBindingsConstants;
import com.sun.tools.xjc.util.DOMUtils;
import com.sun.xml.bind.v2.util.EditDistance;
import com.sun.xml.ws.util.JAXWSUtils;
import com.sun.xml.ws.util.DOMUtil;
import org.w3c.dom.*;
import org.xml.sax.SAXParseException;

import javax.xml.namespace.NamespaceContext;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;


/**
 * Internalizes external binding declarations.
 * @author Vivek Pandey
 */
public class Internalizer {
    private static final XPathFactory xpf = XPathFactory.newInstance();
    private final XPath xpath = xpf.newXPath();
    private final WsimportOptions options;
    private final DOMForest forest;
    private final ErrorReceiver errorReceiver;


    public Internalizer(DOMForest forest, WsimportOptions options, ErrorReceiver errorReceiver) {
        this.forest = forest;
        this.options = options;
        this.errorReceiver = errorReceiver;
    }

    public void transform(){
        Map targetNodes = new HashMap();
        for(Element jaxwsBinding : forest.outerMostBindings){
            buildTargetNodeMap(jaxwsBinding, jaxwsBinding, targetNodes );
        }
        for(Element jaxwsBinding : forest.outerMostBindings){
            move(jaxwsBinding, targetNodes );
        }
    }

    /**
     * Validates attributes of a <JAXWS:bindings> element.
     */
    private void validate( Element bindings ) {
        NamedNodeMap atts = bindings.getAttributes();
        for( int i=0; i result ) {
        // start by the inherited target
        Node target = inheritedTarget;

        validate(bindings); // validate this node

        // look for @wsdlLocation
        if( bindings.getAttributeNode("wsdlLocation")!=null ) {
            String wsdlLocation = bindings.getAttribute("wsdlLocation");

            try {
                // absolutize this URI.
                // TODO: use the URI class
                // TODO: honor xml:base
                wsdlLocation = new URL(new URL(forest.getSystemId(bindings.getOwnerDocument())),
                        wsdlLocation ).toExternalForm();
            } catch( MalformedURLException e ) {
                wsdlLocation = JAXWSUtils.absolutize(JAXWSUtils.getFileOrURLName(wsdlLocation));
            }

            //target = wsdlDocuments.get(wsdlLocation);
            target = forest.get(wsdlLocation);
            if(target==null) {
                reportError(bindings, WsdlMessages.INTERNALIZER_INCORRECT_SCHEMA_REFERENCE(wsdlLocation, EditDistance.findNearest(wsdlLocation, forest.listSystemIDs())));
                return; // abort processing this 
            }
        }

        //if the target node is xs:schema, declare the jaxb version on it as latter on it will be
        //required by the inlined schema bindings

        Element element = DOMUtil.getFirstElementChild(target);
        if (element != null && element.getNamespaceURI().equals(Constants.NS_WSDL) && element.getLocalName().equals("definitions")) {
            //get all schema elements
            Element type = DOMUtils.getFirstChildElement(element, Constants.NS_WSDL, "types");
            if(type != null){
                for (Element schemaElement : DOMUtils.getChildElements(type, Constants.NS_XSD, "schema")) {
                    if (!schemaElement.hasAttributeNS(Constants.NS_XMLNS, "jaxb")) {
                        schemaElement.setAttributeNS(Constants.NS_XMLNS, "xmlns:jaxb", JAXWSBindingsConstants.NS_JAXB_BINDINGS);
                    }

                    //add jaxb:bindings version info. Lets put it to 1.0, may need to change latter
                    if (!schemaElement.hasAttributeNS(JAXWSBindingsConstants.NS_JAXB_BINDINGS, "version")) {
                        schemaElement.setAttributeNS(JAXWSBindingsConstants.NS_JAXB_BINDINGS, "jaxb:version", JAXWSBindingsConstants.JAXB_BINDING_VERSION);
                    }
                }
            }
        }


        boolean hasNode = true;        
        if((isJAXWSBindings(bindings) || isJAXBBindings(bindings)) && bindings.getAttributeNode("node")!=null ) {
            target = evaluateXPathNode(bindings, target, bindings.getAttribute("node"), new NamespaceContextImpl(bindings));
        }else if(isJAXWSBindings(bindings) && (bindings.getAttributeNode("node")==null) && !isTopLevelBinding(bindings)) {
            hasNode = false;
        }else if(isGlobalBinding(bindings) && !isWSDLDefinition(target) && isTopLevelBinding(bindings.getParentNode())){
            target = getWSDLDefintionNode(bindings, target);
        }

        //if target is null it means the xpath evaluation has some problem,
        // just return
        if(target == null)
            return;

        // update the result map
        if(hasNode)
            result.put( bindings, target );

        // look for child  and process them recursively
        Element[] children = getChildElements( bindings);
        for (Element child : children)
            buildTargetNodeMap(child, target, result);
    }

    private Node getWSDLDefintionNode(Node bindings, Node target){
        return evaluateXPathNode(bindings, target, "wsdl:definitions",
            new NamespaceContext(){
                public String getNamespaceURI(String prefix){
                    return "http://schemas.xmlsoap.org/wsdl/";
                }
                public String getPrefix(String nsURI){
                    throw new UnsupportedOperationException();
                }
                public Iterator getPrefixes(String namespaceURI) {
                    throw new UnsupportedOperationException();
                }});
    }

    private boolean isWSDLDefinition(Node target){
        if(target == null)
            return false;
        String localName = target.getLocalName();
        String nsURI = target.getNamespaceURI();
        return fixNull(localName).equals("definitions") && fixNull(nsURI).equals("http://schemas.xmlsoap.org/wsdl/");
    }

    private boolean isTopLevelBinding(Node node){
        if(node instanceof Document)
            node = ((Document)node).getDocumentElement();
        return ((node != null) && (((Element)node).getAttributeNode("wsdlLocation") != null));
    }

    private boolean isJAXWSBindings(Node bindings){
        return (bindings.getNamespaceURI().equals(JAXWSBindingsConstants.NS_JAXWS_BINDINGS) && bindings.getLocalName().equals("bindings"));
    }

    private boolean isJAXBBindings(Node bindings){
        return (bindings.getNamespaceURI().equals(JAXWSBindingsConstants.NS_JAXB_BINDINGS) && bindings.getLocalName().equals("bindings"));
    }

    private boolean isGlobalBinding(Node bindings){
        if(bindings.getNamespaceURI() == null){
            errorReceiver.warning(forest.locatorTable.getStartLocation((Element) bindings), WsdlMessages.INVALID_CUSTOMIZATION_NAMESPACE(bindings.getLocalName()));
            return false;
        }
        return  (bindings.getNamespaceURI().equals(JAXWSBindingsConstants.NS_JAXWS_BINDINGS) &&
                (bindings.getLocalName().equals("package") ||
                bindings.getLocalName().equals("enableAsyncMapping") ||
                bindings.getLocalName().equals("enableAdditionalSOAPHeaderMapping") ||
                bindings.getLocalName().equals("enableWrapperStyle") ||
                bindings.getLocalName().equals("enableMIMEContent")));
    }

    private static Element[] getChildElements(Element parent) {
        ArrayList a = new ArrayList();
        NodeList children = parent.getChildNodes();
        for( int i=0; i
        }

        if( nlst.getLength()==0 ) {
            reportError((Element) bindings, WsdlMessages.INTERNALIZER_X_PATH_EVALUATES_TO_NO_TARGET(expression));
            return null; // abort
        }

        if( nlst.getLength()!=1 ) {
            reportError((Element) bindings, WsdlMessages.INTERNALIZER_X_PATH_EVAULATES_TO_TOO_MANY_TARGETS(expression, nlst.getLength()));
            return null; // abort
        }

        Node rnode = nlst.item(0);
        if(!(rnode instanceof Element )) {
            reportError((Element) bindings, WsdlMessages.INTERNALIZER_X_PATH_EVALUATES_TO_NON_ELEMENT(expression));
            return null; // abort
        }
        return rnode;
    }

    /**
     * Moves JAXWS customizations under their respective target nodes.
     */
    private void move( Element bindings, Map targetNodes ) {
        Node target = targetNodes.get(bindings);
        if(target==null)
            // this must be the result of an error on the external binding.
            // recover from the error by ignoring this node
            return;

        Element[] children = DOMUtils.getChildElements(bindings);

        for (Element item : children) {
            if ("bindings".equals(item.getLocalName())){
            // process child  recursively
                move(item, targetNodes);
            }else if(isGlobalBinding(item)){
                target = targetNodes.get(item);
                moveUnder(item,(Element)target);
            }else {
                if (!(target instanceof Element)) {
                    return; // abort
                }
                // move this node under the target
                moveUnder(item,(Element)target);
            }
        }
    }

    private boolean isJAXBBindingElement(Element e){
        return fixNull(e.getNamespaceURI()).equals(JAXWSBindingsConstants.NS_JAXB_BINDINGS);
    }

    private boolean isJAXWSBindingElement(Element e){
        return fixNull(e.getNamespaceURI()).equals(JAXWSBindingsConstants.NS_JAXWS_BINDINGS);
    }

    /**
     * Moves the "decl" node under the "target" node.
     *
     * @param decl
     *      A JAXWS customization element (e.g., <JAXWS:class>)
     *
     * @param target
     *      XML wsdl element under which the declaration should move.
     *      For example, <xs:element>
     */
    private void moveUnder( Element decl, Element target ) {

        //if there is @node on decl and has a child element jaxb:bindings, move it under the target
        //Element jaxb = getJAXBBindingElement(decl);
        if(isJAXBBindingElement(decl)){
            //add jaxb namespace declaration
            if(!target.hasAttributeNS(Constants.NS_XMLNS, "jaxb")){
                target.setAttributeNS(Constants.NS_XMLNS, "xmlns:jaxb", JAXWSBindingsConstants.NS_JAXB_BINDINGS);
            }

            //add jaxb:bindings version info. Lets put it to 1.0, may need to change latter
            if(!target.hasAttributeNS(JAXWSBindingsConstants.NS_JAXB_BINDINGS, "version")){
                target.setAttributeNS(JAXWSBindingsConstants.NS_JAXB_BINDINGS, "jaxb:version", JAXWSBindingsConstants.JAXB_BINDING_VERSION);
            }

            // HACK: allow XJC extension all the time. This allows people to specify
            // the  in the external bindings. Otherwise users lack the ability
            // to specify jaxb:extensionBindingPrefixes, so it won't work.
            //
            // the current workaround is still problematic in the sense that
            // it can't support user-defined extensions. This needs more careful thought.

            //JAXB doesn't allow writing jaxb:extensionbindingPrefix anywhere other than root element so lets write only on 
            if(target.getLocalName().equals("schema") && target.getNamespaceURI().equals(Constants.NS_XSD)&& !target.hasAttributeNS(JAXWSBindingsConstants.NS_JAXB_BINDINGS, "extensionBindingPrefixes")){
                target.setAttributeNS(JAXWSBindingsConstants.NS_JAXB_BINDINGS, "jaxb:extensionBindingPrefixes", "xjc");
                target.setAttributeNS(Constants.NS_XMLNS, "xmlns:xjc", JAXWSBindingsConstants.NS_XJC_BINDINGS);
            }

            //insert xs:annotation/xs:appinfo where in jaxb:binding will be put
            target = refineSchemaTarget(target);
            copyInscopeNSAttributes(decl);
        }else if(isJAXWSBindingElement(decl)){
            //add jaxb namespace declaration
            if(!target.hasAttributeNS(Constants.NS_XMLNS, "JAXWS")){
                target.setAttributeNS(Constants.NS_XMLNS, "xmlns:JAXWS", JAXWSBindingsConstants.NS_JAXWS_BINDINGS);
            }

            //insert xs:annotation/xs:appinfo where in jaxb:binding will be put
            target = refineWSDLTarget(target);
            copyInscopeNSAttributes(decl);
        }else{
            return;
        }

        // finally move the declaration to the target node.
        if( target.getOwnerDocument()!=decl.getOwnerDocument() ) {
            // if they belong to different DOM documents, we need to clone them
            decl = (Element)target.getOwnerDocument().importNode(decl,true);

        }

        target.appendChild( decl );
    }

    /**
     *  Copy in-scope namespace declarations of the decl node
     *  to the decl node itself so that this move won't change
     *  the in-scope namespace bindings.
     */
    private void copyInscopeNSAttributes(Element e){
        Element p = e;
        Set inscopes = new HashSet();
        while(true) {
            NamedNodeMap atts = p.getAttributes();
            for( int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy