Package org.apache.tuscany.sca.interfacedef.wsdl.java2wsdl

Source Code of org.apache.tuscany.sca.interfacedef.wsdl.java2wsdl.WSDLLocatorImpl

/*
* 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.tuscany.sca.interfacedef.wsdl.java2wsdl;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.wsdl.Binding;
import javax.wsdl.BindingOperation;
import javax.wsdl.BindingOutput;
import javax.wsdl.Definition;
import javax.wsdl.Input;
import javax.wsdl.Message;
import javax.wsdl.OperationType;
import javax.wsdl.Output;
import javax.wsdl.Part;
import javax.wsdl.Port;
import javax.wsdl.PortType;
import javax.wsdl.Service;
import javax.wsdl.Types;
import javax.wsdl.WSDLException;
import javax.wsdl.extensions.ExtensibilityElement;
import javax.wsdl.extensions.UnknownExtensibilityElement;
import javax.wsdl.extensions.schema.Schema;
import javax.wsdl.xml.WSDLLocator;
import javax.wsdl.xml.WSDLReader;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;

import org.apache.tuscany.sca.interfacedef.DataType;
import org.apache.tuscany.sca.interfacedef.Operation;
import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract;
import org.apache.tuscany.sca.interfacedef.util.XMLType;
import org.apache.tuscany.sca.interfacedef.wsdl.DefaultWSDLFactory;
import org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition;
import org.apache.tuscany.sca.interfacedef.wsdl.WSDLFactory;
import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterface;
import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterfaceContract;
import org.apache.tuscany.sca.interfacedef.wsdl.XSDefinition;
import org.apache.tuscany.sca.interfacedef.wsdl.impl.InvalidWSDLException;
import org.apache.tuscany.sca.interfacedef.wsdl.impl.WSDLOperationIntrospectorImpl;
import org.apache.tuscany.sca.interfacedef.wsdl.xml.WSDLModelResolver;
import org.apache.tuscany.sca.interfacedef.wsdl.xml.XMLDocumentHelper;
import org.apache.ws.commons.schema.XmlSchema;
import org.apache.ws.commons.schema.XmlSchemaCollection;
import org.apache.ws.java2wsdl.Java2WSDLBuilder;
import org.osoa.sca.annotations.OneWay;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;

/**
* Utility methods to create WSDL objects from Java interfaces
*/
public class Java2WSDLHelper {

    private static void register(Map<String, String> map, DataType type) {
        if (type == null) {
            return;
        }
        Package pkg = type.getPhysical().getPackage();
        if (pkg != null) {
            String pkgName = pkg.getName();
            Object logical = type.getLogical();
            if (logical instanceof XMLType) {
                QName typeName = ((XMLType)logical).getTypeName();
                if (typeName != null && !XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(typeName.getNamespaceURI())) {
                    map.put(pkgName, typeName.getNamespaceURI());
                }
            }
        }
    }

    /**
     * Create a WSDLInterfaceContract from a JavaInterfaceContract
     */
    public static WSDLInterfaceContract createWSDLInterfaceContract(JavaInterfaceContract contract) {
        return createWSDLInterfaceContract(contract, false);
    }
   
    /**
     * Create a WSDLInterfaceContract from a JavaInterfaceContract
     */
    public static WSDLInterfaceContract createWSDLInterfaceContract(JavaInterfaceContract contract,
                                                                    boolean requiresSOAP12) {
        JavaInterface iface = (JavaInterface)contract.getInterface();
       
        // Create a package2ns map
        Map<String, String> pkg2nsMap = new HashMap<String, String>();
        for (Operation op : iface.getOperations()) {
            DataType<List<DataType>> inputType = op.getInputType();
            for (DataType t : inputType.getLogical()) {
                register(pkg2nsMap, t);
            }
            DataType outputType = op.getOutputType();
            register(pkg2nsMap, outputType);
        }

        Definition def = createDefinition(pkg2nsMap, iface.getJavaClass(), requiresSOAP12);

        DefaultWSDLFactory wsdlFactory = new DefaultWSDLFactory();

        WSDLInterfaceContract wsdlContract = wsdlFactory.createWSDLInterfaceContract();
        WSDLInterface wsdlInterface = wsdlFactory.createWSDLInterface();

        wsdlContract.setInterface(wsdlInterface);
        WSDLDefinition wsdlDefinition = new DefaultWSDLFactory().createWSDLDefinition();
        wsdlDefinition.setDefinition(def);
        wsdlInterface.setWsdlDefinition(wsdlDefinition);
        wsdlInterface.setRemotable(true);
        wsdlInterface.setConversational(contract.getInterface().isConversational());
        wsdlInterface.setUnresolved(false);
        wsdlInterface.setRemotable(true);
        PortType portType = (PortType)def.getAllPortTypes().values().iterator().next();
        wsdlInterface.setPortType(portType);

        readInlineSchemas(wsdlFactory, wsdlDefinition, def, new XmlSchemaCollection());

        try {
            for (Operation op : iface.getOperations()) {
                javax.wsdl.Operation wsdlOp = portType.getOperation(op.getName(), null, null);
                WSDLOperationIntrospectorImpl opx =
                    new WSDLOperationIntrospectorImpl(wsdlFactory, wsdlOp, wsdlDefinition, null, null);
               
                wsdlInterface.getOperations().add(opx.getOperation());

                /*
                Operation clonedOp = (Operation)op.clone();
                clonedOp.setDataBinding(null);

                if (clonedOp.getInputType().getLogical().isEmpty()) {
                    // null args case needs a single input type for the wrapper
                    clonedOp.setInputType(opx.getInputType());
                }
                for (DataType<?> dt : clonedOp.getInputType().getLogical()) {
                    dt.setDataBinding(null);
                }

                if (clonedOp.getOutputType() != null) {
                    clonedOp.getOutputType().setDataBinding(null);
                }
                for (DataType<?> dt : clonedOp.getFaultTypes()) {
                    dt.setDataBinding(null);
                }
                clonedOp.setWrapperStyle(true);
                clonedOp.setWrapper(opx.getWrapper().getWrapperInfo());

                wsdlInterface.getOperations().add(clonedOp);
                */
            }
        } catch (InvalidWSDLException e) {
            throw new RuntimeException(e);
        }

        return wsdlContract;
    }

    private static Document promote(Element element) {
        Document doc = (Document)element.getOwnerDocument().cloneNode(false);
        Element schema = (Element)doc.importNode(element, true);
        doc.appendChild(schema);
        Node parent = element.getParentNode();
        while (parent instanceof Element) {
            Element root = (Element)parent;
            NamedNodeMap nodeMap = root.getAttributes();
            for (int i = 0; i < nodeMap.getLength(); i++) {
                Attr attr = (Attr)nodeMap.item(i);
                String name = attr.getName();
                if ("xmlns".equals(name) || name.startsWith("xmlns:")) {
                    if (schema.getAttributeNode(name) == null) {
                        schema.setAttributeNodeNS((Attr)doc.importNode(attr, true));
                    }
                }
            }
            parent = parent.getParentNode();
        }
        doc.setDocumentURI(element.getOwnerDocument().getDocumentURI());
        return doc;
    }

    /**
     * Populate the inline schemas including those from the imported definitions
     *
     * @param definition
     * @param schemaCollection
     */
    private static void readInlineSchemas(WSDLFactory wsdlFactory,
                                          WSDLDefinition wsdlDefinition,
                                          Definition definition,
                                          XmlSchemaCollection schemaCollection) {
        Types types = definition.getTypes();
        if (types != null) {
            int index = 0;
            for (Object ext : types.getExtensibilityElements()) {
                ExtensibilityElement extElement = (ExtensibilityElement)ext;
                Element element = null;
                if (WSDLModelResolver.XSD_QNAME_LIST.contains(extElement.getElementType())) {
                    if (extElement instanceof Schema) {
                        element = ((Schema)extElement).getElement();
                    } else if (extElement instanceof UnknownExtensibilityElement) {
                        element = ((UnknownExtensibilityElement)extElement).getElement();
                    }
                }
                if (element != null) {
                    Document doc = promote(element);
                    XSDefinition xsDefinition = wsdlFactory.createXSDefinition();
                    xsDefinition.setUnresolved(true);
                    xsDefinition.setNamespace(element.getAttribute("targetNamespace"));
                    xsDefinition.setDocument(doc);
                    xsDefinition.setLocation(URI.create(doc.getDocumentURI() + "#" + index));
                    loadXSD(schemaCollection, xsDefinition);
                    wsdlDefinition.getXmlSchemas().add(xsDefinition);
                    index++;
                }
            }
        }
        for (Object imports : definition.getImports().values()) {
            List impList = (List)imports;
            for (Object i : impList) {
                javax.wsdl.Import anImport = (javax.wsdl.Import)i;
                // Read inline schemas
                if (anImport.getDefinition() != null) {
                    readInlineSchemas(wsdlFactory, wsdlDefinition, anImport.getDefinition(), schemaCollection);
                }
            }
        }
    }

    private static void loadXSD(XmlSchemaCollection schemaCollection, XSDefinition definition) {
        if (definition.getSchema() != null) {
            return;
        }
        if (definition.getDocument() != null) {
            String uri = null;
            if (definition.getLocation() != null) {
                uri = definition.getLocation().toString();
            }
            XmlSchema schema = schemaCollection.read(definition.getDocument(), uri, null);
            definition.setSchemaCollection(schemaCollection);
            definition.setSchema(schema);
        }
    }

    /**
     * Create a WSDL4J Definition object from a Java interface
     */
    protected static Definition createDefinition(Map map, Class<?> javaInterface, boolean requiresSOAP12) {

        String className = javaInterface.getName();
        ClassLoader cl = javaInterface.getClassLoader();
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        Java2WSDLBuilder builder = new Java2WSDLBuilder(os, className, cl);
        if (map != null) {
            builder.setPkg2nsMap(map);
        }

        try {
            builder.generateWSDL();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        try {

            WSDLReader reader = javax.wsdl.factory.WSDLFactory.newInstance().newWSDLReader();
            reader.setFeature("javax.wsdl.verbose", false);
            reader.setFeature("javax.wsdl.importDocuments", true);

            WSDLLocatorImpl locator = new WSDLLocatorImpl(new ByteArrayInputStream(os.toByteArray()));
            Definition definition = reader.readWSDL(locator);

            processSOAPVersion(definition, requiresSOAP12);
            processNoArgAndVoidReturnMethods(definition, javaInterface);

            return definition;

        } catch (WSDLException e) {
            throw new RuntimeException(e);
        }
    }

    private static void processSOAPVersion(Definition definition, boolean requiresSOAP12) {
        if (requiresSOAP12) {
            removePort(definition, "SOAP11port_http");
        } else {
            removePort(definition, "SOAP12port_http");
        }
    }

    private static void removePort(Definition definition, String portNameSuffix) {
        Service service = (Service)definition.getServices().values().iterator().next();
        Map<?, ?> ports = service.getPorts();
        for (Object o : ports.keySet()) {
            if (((String)o).endsWith(portNameSuffix)) {
                Port p = (Port)ports.remove(o);
                definition.removeBinding(p.getBinding().getQName());
                break;
            }
        }
    }

    private static void processNoArgAndVoidReturnMethods(Definition definition, Class javaInterface) {
        String namespaceURI = definition.getTargetNamespace();
        String prefix = definition.getPrefix(namespaceURI);
        String xsPrefix = definition.getPrefix("http://www.w3.org/2001/XMLSchema");
        PortType portType = (PortType)definition.getAllPortTypes().values().iterator().next();

        Element schema = null;
        Document document = null;
        Types types = definition.getTypes();
        if (types != null) {
            for (Object ext : types.getExtensibilityElements()) {
                if (ext instanceof Schema) {
                    Element element = ((Schema)ext).getElement();
                    if (element.getAttribute("targetNamespace").equals(namespaceURI)) {
                        schema = element;
                        document = schema.getOwnerDocument();
                        break;
                    }
                }
            }
        }
        if (document == null) {
            return;
        }

        // look at each operation in the port type to see if it needs fixing up
        for (Object oper : portType.getOperations()) {
            javax.wsdl.Operation operation = (javax.wsdl.Operation)oper;
            String opName = operation.getName();

            // if input message has no parts, add one containing an empty wrapper
            Input input = operation.getInput();
            if (input != null) {
                Message inputMsg = input.getMessage();
                if (inputMsg.getParts().isEmpty()) {
                    // create wrapper element and add it to the schema DOM
                    Element wrapper =
                        document.createElementNS("http://www.w3.org/2001/XMLSchema", xsPrefix + ":element");
                    wrapper.setAttribute("name", opName);
                    schema.appendChild(wrapper);
                    Element complexType =
                        document.createElementNS("http://www.w3.org/2001/XMLSchema", xsPrefix + ":complexType");
                    wrapper.appendChild(complexType);

                    // create new part for the wrapper and add it to the message
                    Part part = definition.createPart();
                    part.setName("parameters");
                    part.setElementName(new QName(namespaceURI, opName, prefix));
                    inputMsg.addPart(part);
                }
            }

            // if two-way operation has no output message, add one containing an empty wrapper
            if (input != null && operation.getOutput() == null) {
                boolean isOneWay = false;
                Method[] methods = javaInterface.getMethods();
                for (Method method : methods) {
                    if (method.getName().equals(opName) && method.getAnnotation(OneWay.class) != null) {
                        isOneWay = true;
                    }
                }
                if (!isOneWay) {
                    // create wrapper element and add it to the schema DOM
                    String msgName = opName + "Response";
                    Element wrapper =
                        document.createElementNS("http://www.w3.org/2001/XMLSchema", xsPrefix + ":element");
                    wrapper.setAttribute("name", msgName);
                    schema.appendChild(wrapper);
                    Element complexType =
                        document.createElementNS("http://www.w3.org/2001/XMLSchema", xsPrefix + ":complexType");
                    wrapper.appendChild(complexType);

                    // create new part for the wrapper
                    Part part = definition.createPart();
                    part.setName("parameters");
                    part.setElementName(new QName(namespaceURI, msgName, prefix));

                    // create new message for the part
                    Message outputMsg = definition.createMessage();
                    outputMsg.setQName(new QName(namespaceURI, msgName, prefix));
                    outputMsg.addPart(part);
                    outputMsg.setUndefined(false);
                    definition.addMessage(outputMsg);

                    // create output element for the operation
                    Output output = definition.createOutput();
                    output.setMessage(outputMsg);
                    output.setExtensionAttribute(new QName("http://www.w3.org/2006/05/addressing/wsdl", "Action"),
                                                 new QName("urn:" + msgName));
                    operation.setOutput(output);
                    operation.setStyle(OperationType.REQUEST_RESPONSE);

                    // add binding output element to bindings for this port type
                    for (Object bindObj : definition.getAllBindings().values()) {
                        Binding binding = (Binding)bindObj;
                        if (binding.getPortType().equals(portType)) {
                            BindingOperation op = binding.getBindingOperation(opName, null, null);
                            if (op != null && op.getBindingInput() != null && op.getBindingOutput() == null) {
                                BindingOutput bindingOut = definition.createBindingOutput();
                                for (Object extObj : op.getBindingInput().getExtensibilityElements()) {
                                    bindingOut.addExtensibilityElement((ExtensibilityElement)extObj);
                                }
                                op.setBindingOutput(bindingOut);
                            }
                        }
                    }
                }
            }
        }

    }

}

class WSDLLocatorImpl implements WSDLLocator {
    private InputStream inputStream;
    private String base = "http://";
    private String latestImportURI;

    public WSDLLocatorImpl(InputStream is) {
        this.inputStream = is;
    }

    public void close() {
        try {
            inputStream.close();
        } catch (IOException e) {
            // Ignore
        }
    }

    public InputSource getBaseInputSource() {
        try {
            return XMLDocumentHelper.getInputSource(new URL(base), inputStream);
        } catch (IOException e) {
            throw new IllegalArgumentException(e);
        }
    }

    public String getBaseURI() {
        return base;
    }

    public InputSource getImportInputSource(String parentLocation, String importLocation) {
        return null;
    }

    public String getLatestImportURI() {
        return latestImportURI;
    }

}
TOP

Related Classes of org.apache.tuscany.sca.interfacedef.wsdl.java2wsdl.WSDLLocatorImpl

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.