alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Glassfish example source code file (WSDLConverter.java)

This example Glassfish source code file (WSDLConverter.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Glassfish tags/keywords

arraylist, dom, exception, exception, io, list, list, map, qname, qname, soapaddress, soapbinding, soapbody, string, string, util, wsdlconverter

The Glassfish WSDLConverter.java source code

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2010 Oracle and/or its affiliates. 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_1_1.html
 * or packager/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 packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [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.enterprise.jbi.serviceengine.util.soap;

import com.ibm.wsdl.extensions.soap.SOAPAddressImpl;
import com.ibm.wsdl.extensions.soap.SOAPBindingImpl;
import com.ibm.wsdl.extensions.soap.SOAPBodyImpl;
import com.ibm.wsdl.extensions.soap.SOAPFaultImpl;
import com.ibm.wsdl.extensions.soap.SOAPHeaderImpl;
import com.ibm.wsdl.extensions.soap.SOAPOperationImpl;
import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.wsdl.Binding;
import javax.wsdl.BindingFault;
import javax.wsdl.BindingInput;
import javax.wsdl.BindingOperation;
import javax.wsdl.BindingOutput;
import javax.wsdl.Definition;
import javax.wsdl.Fault;
import javax.wsdl.Message;
import javax.wsdl.Operation;
import javax.wsdl.Part;
import javax.wsdl.Port;
import javax.wsdl.PortType;
import javax.wsdl.Service;
import javax.wsdl.extensions.ElementExtensible;
import javax.wsdl.extensions.ExtensibilityElement;
import javax.wsdl.extensions.ExtensionRegistry;
import javax.wsdl.extensions.soap.SOAPAddress;
import javax.wsdl.extensions.soap.SOAPBinding;
import javax.wsdl.extensions.soap.SOAPBody;
import javax.wsdl.extensions.soap.SOAPFault;
import javax.wsdl.extensions.soap.SOAPHeader;
import javax.wsdl.extensions.soap.SOAPOperation;
import javax.wsdl.factory.WSDLFactory;
import javax.wsdl.xml.WSDLReader;
import javax.wsdl.xml.WSDLWriter;
import javax.xml.namespace.QName;
import org.w3c.dom.Element;

/**
 *
 * Converts any non-SOAP WSDL to a SOAP WSDL.
 *
 * If the original WSDL is a SOAP WSDL then it is not modified.
 *
 * @author bhavanishankar@dev.java.net
 */
public class WSDLConverter {
    
    ExtensionRegistry extnReg;
    WSDLReader wsdlReader;
    WSDLWriter wsdlWriter;
    
    public static final String SOAP_NS = "http://schemas.xmlsoap.org/wsdl/soap/";
    public static final String SOAP_PREFIX = "soap";
    public static final String SOAP_BINDING_SUFFIX = "binding";
    public static final String SOAP_OPERATION_SUFFIX = "operation";
    public static final String SOAP_ADDRESS_SUFFIX = "address";
    public static final String SOAP_BODY_SUFFIX = "body";
    public static final String SOAP_HEADER_SUFFIX = "header";
    public static final String SOAP_FAULT_SUFFIX = "fault";
    
    public static final String SOAP_HTTP_TRANSPORT_URI = "http://schemas.xmlsoap.org/soap/http";
    public static final String SOAP_ADDRESS_LOCATION = "REPLACE_WITH_ACTUAL_URL";
    
    public static final String RPC_STYLE = "rpc";
    public static final String DOCUMENT_STYLE = "document";
    public static final String USE_LITERAL = "literal";
    
    public WSDLConverter() throws Exception {
        
        WSDLFactory factory = WSDLFactory.newInstance();
        wsdlReader = factory.newWSDLReader();
        wsdlWriter = factory.newWSDLWriter();
        
        extnReg = new ExtensionRegistry();
        
        extnReg.mapExtensionTypes(Binding.class,
                new QName(SOAP_NS,SOAP_BINDING_SUFFIX),
                SOAPBindingImpl.class);
        
        extnReg.mapExtensionTypes(ExtensibilityElement.class,
                new QName(SOAP_NS,SOAP_OPERATION_SUFFIX),
                SOAPOperationImpl.class);
        
        extnReg.mapExtensionTypes(ExtensibilityElement.class,
                new QName(SOAP_NS,SOAP_ADDRESS_SUFFIX),
                SOAPAddressImpl.class);
        
        extnReg.mapExtensionTypes(SOAPBody.class,
                new QName(SOAP_NS,SOAP_BODY_SUFFIX),
                SOAPBodyImpl.class);
        
        extnReg.mapExtensionTypes(SOAPHeader.class,
                new QName(SOAP_NS,SOAP_HEADER_SUFFIX),
                SOAPHeaderImpl.class);
        
        extnReg.mapExtensionTypes(SOAPFault.class,
                new QName(SOAP_NS,SOAP_FAULT_SUFFIX),
                SOAPFaultImpl.class);
        
    }
    
    private SOAPBinding createSoapBinding() throws Exception {
        SOAPBinding soapBinding = (SOAPBinding)extnReg.createExtension(Binding.class,
                new QName(SOAP_NS,SOAP_BINDING_SUFFIX));
        soapBinding.setTransportURI(SOAP_HTTP_TRANSPORT_URI);
        return soapBinding;
    }
    
    private SOAPAddress createSoapAddress() throws Exception {
        SOAPAddress soapAddress = (SOAPAddress)extnReg.createExtension(ExtensibilityElement.class,
                new QName(SOAP_NS,SOAP_ADDRESS_SUFFIX));
        soapAddress.setLocationURI(SOAP_ADDRESS_LOCATION);
        return soapAddress;
    }
    
    private SOAPOperation createSoapOperation() throws Exception {
        SOAPOperation soapOperation = (SOAPOperation)extnReg.createExtension(
                ExtensibilityElement.class,
                new QName(SOAP_NS, SOAP_OPERATION_SUFFIX));
        return soapOperation;
    }
    
    private SOAPBody createSoapBody() throws Exception {
        SOAPBody soapBody = (SOAPBody)extnReg.createExtension(
                SOAPBody.class,
                new QName(SOAP_NS, SOAP_BODY_SUFFIX));
        soapBody.setUse(USE_LITERAL);
        return soapBody;
    }
    
    private SOAPHeader createSoapHeader() throws Exception {
        SOAPHeader soapHeader = (SOAPHeader)extnReg.createExtension(
                SOAPHeader.class,
                new QName(SOAP_NS, SOAP_HEADER_SUFFIX));
        soapHeader.setUse(USE_LITERAL);
        return soapHeader;
    }
    
    private SOAPFault createSoapFault() throws Exception {
        SOAPFault soapFault = (SOAPFault)extnReg.createExtension(
                SOAPFault.class,
                new QName(SOAP_NS, SOAP_FAULT_SUFFIX));
        soapFault.setUse(USE_LITERAL);
        return soapFault;
    }
    
    /**
     * Style can be calculated by looking into how the input/output parts are defined.
     * Style can not be calculated by looking into fault.
     *
     * WS-I Basic Profile 1.0 :
     *
     * R2203   An rpc-literal binding in a DESCRIPTION MUST refer,
     * in its soapbind:body element(s), only to wsdl:part element(s)
     * that have been defined using the type attribute.
     *
     * R2204   A document-literal binding in a DESCRIPTION MUST refer,
     * in each of its soapbind:body element(s), only to wsdl:part element(s)
     * that have been defined using the element attribute.
     *
     */
    private String getStyle(Operation portTypeOperation) {
        try {
            if(portTypeOperation.getInput() != null) {
                List<Part> parts = portTypeOperation.getInput().getMessage().getOrderedParts(null);
                for(Part p : parts) {
                    if(p.getTypeName() != null) {
                        return RPC_STYLE;
                    }
                }
            }
            if(portTypeOperation.getOutput() != null) {
                List<Part> parts = portTypeOperation.getOutput().getMessage().getOrderedParts(null);
                for(Part p : parts) {
                    if(p.getTypeName() != null) {
                        return RPC_STYLE;
                    }
                }
            }
        } catch(Exception ex) {
            ex.printStackTrace();
        }
        return DOCUMENT_STYLE;
    }
    
    private void processElement(
            ElementExtensible elementExtensible,
            Message message,
            String style) throws Exception {
        if(RPC_STYLE.equals(style)) {
            SOAPBody soapBody = createSoapBody();
            /**
             * namespace needs to be set in <soap:body> only for 'rpc' style.
             *
             * WS-I Basic Profile 1.0 :
             *
             * R2716   A document-literal binding in a DESCRIPTION MUST NOT have
             * the namespace  attribute specified on contained soapbind:body,
             * soapbind:header, soapbind:headerfault and  soapbind:fault elements.
             *
             * R2717 : An rpc-literal binding in a DESCRIPTION MUST have
             * the namespace attribute specified, the value of which MUST
             * be an absolute URI, on contained  soapbind:body elements.
             *
             * R2726   An rpc-literal binding in a DESCRIPTION MUST NOT have
             * the namespace attribute specified on contained soapbind:header,
             * soapbind:headerfault and soapbind:fault elements.
             *
             */
            soapBody.setNamespaceURI(
                    message.getQName().getNamespaceURI());
            elementExtensible.addExtensibilityElement(soapBody);
        } else {
            List<Part> orderedParts = message.getOrderedParts(null);
            boolean partBoundToBody = false; // only one part can be bound to <soap:body>.
            for(int i=orderedParts.size()-1; i>=0; i--) {
                Part p = orderedParts.get(i);
                if( (p.getElementName().getLocalPart().equals
                        (message.getQName().getLocalPart())) // wrapped doc/literal
                        || (i==0 && !partBoundToBody) // bare doc/literal
                        ) {
                    partBoundToBody = true;
                    SOAPBody soapBody = createSoapBody();
                    List<String> parts = new ArrayList();
                    parts.add(p.getName());
                    soapBody.setParts(parts);
                    elementExtensible.addExtensibilityElement(soapBody);
                } else {
                    SOAPHeader soapHeader = createSoapHeader();
                    soapHeader.setPart(p.getName());
                    soapHeader.setMessage(message.getQName());
                    elementExtensible.addExtensibilityElement(soapHeader);
                }
            }
        }
        //return elementExtensible;
    }
    
    /**
     * Converts all <wsdl:service> sections.
     */
    private boolean convertServices(Definition defn) throws Exception  {
        
        boolean wsdlModified = false;
        
        Map<QName,Service> services = defn.getServices();
        
        if(services == null || services.isEmpty()) {
            return wsdlModified;
        }
        
        Service[] originalServices = services.values().toArray(new Service[0]);
        
        for(Service originalService : originalServices) {
            
            Map<String,Port> originalPorts = originalService.getPorts();
            
            boolean isSOAP = false;
            Service newService = defn.createService();
            
            for(String key : originalPorts.keySet()) {
                
                Port originalPort = originalPorts.get(key);
                
                /**
                 * Step1. Skip if it is already SOAP
                 */
                List<ExtensibilityElement> extList = originalPort.getExtensibilityElements();
                for(ExtensibilityElement extElem : extList) {
                    if(extElem instanceof SOAPAddress) {
                        isSOAP = true;
                        break;
                    }
                }
                if(isSOAP) {
                    continue;
                }
                
                wsdlModified = true;
                
                /**
                 * Step2. Collect the required information from
                 * the existing <wsdl:port>
                 */
                String originalPortName = originalPort.getName();
                Element originalPortDocElem = originalPort.getDocumentationElement();
                Binding originalBinding = originalPort.getBinding();
                
                /**
                 * Step3. Create a new port and add it to <wsdl:service>
                 *
                 *  <wsdl:port name="#name" binding="#tns:binding">
                 *      <soap:address location="REPLACE_WITH_ACTUAL_URL"/>
                 *  </wsdl:port>
                 *
                 */
                Port newPort = defn.createPort();
                // Add -> name="#name"
                newPort.setName(originalPortName);
                
                // Add -> binding="#tns:binding"
                // Since 'originalBinding' might have been deleted already, so get the binding from defn
                newPort.setBinding(defn.getBinding(originalBinding.getQName()));
                newPort.setDocumentationElement(originalPortDocElem);
                
                // Add -> <soap:address location="REPLACE_WITH_ACTUAL_URL"/>
                SOAPAddress soapAddress = createSoapAddress();
                
                //sa.setRequired(true);
                newPort.addExtensibilityElement(soapAddress);
                
                /**
                 * Step4. Add the newly created <wsdl:port> to .
                 */
                newService.setQName(originalService.getQName());
                newService.addPort(newPort);
            }
            
            if(!isSOAP) {
                defn.removeService(originalService.getQName());
                defn.addService(newService);
            }
        }
        return wsdlModified;
    }
    
    /**
     * Converts all <wsdl:binding> sections.
     */
    private boolean convertBindings(Definition defn) throws Exception {
        
        boolean wsdlModified = false;
        
        Map<QName,Binding> bindings = defn.getBindings();
        
        if(bindings == null || bindings.isEmpty()) {
            return wsdlModified;
        }
        
        Binding[] originalBindings = bindings.values().toArray(new Binding[0]);
        
        for(Binding originalBinding : originalBindings) {
            
            /**
             * Step 1. Skip if it is already SOAP
             */
            boolean isSOAP = false;
            
            List<ExtensibilityElement> extList = originalBinding.getExtensibilityElements();
            for(ExtensibilityElement extElem : extList) {
                if(extElem instanceof SOAPBinding) {
                    isSOAP = true;
                    break;
                }
            }
            
            if(isSOAP) {
                continue;
            }
            
            wsdlModified = true;
            
            /**
             * Step 2. Collect the required information from
             * the existing <wsdl:port>
             */
            
            PortType p = originalBinding.getPortType();
            QName originalBindingQname = originalBinding.getQName();
            List<BindingOperation> originalBindingOps = originalBinding.getBindingOperations();
            
            
            /**
             * Step 3. Create a new binding
             *
             *  <wsdl:binding name="#name" type="#type">
             *      <soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
             *      <wsdl:operation name="#operation1">
             *          <soap:operation/>
             *          <wsdl:input>
             *              <soap:body use="literal" namespace="#namespace"/>
             *          </wsdl:input>
             *          <wsdl:output>
             *              <soap:body use="literal" namespace="#namespace"/>
             *          </wsdl:output>
             *          <wsdl:fault name="#faultname">
             *              <soap:fault name="#faultname" use="literal"/>
             *          </wsdl:fault>
             *          ...more faults...
             *      </wsdl:operation>
             *      ...more operations...
             *  </wsdl:binding>
             *
             */
            Binding newBinding = defn.createBinding();
            // Add -> name="#name"
            newBinding.setQName(originalBindingQname);
            // Add -> type="#type"
            newBinding.setPortType(p);
            newBinding.setUndefined(false);
            
            // Add -> <soap:binding tranport="http://schemas.xmlsoap.org/soap/http"
            SOAPBinding soapBinding = createSoapBinding();
            newBinding.addExtensibilityElement(soapBinding);
            
            /**
             * Add ->
             *
             *  <wsdl:operation name="#operation1">
             *      ....
             *  </wsdl:operation>
             *  ... more operations...
             *
             */
            String style = null;
            
            for(BindingOperation originalBindingOp : originalBindingOps) {
                BindingOperation newBindingOp = defn.createBindingOperation();
                
                newBindingOp.setOperation(originalBindingOp.getOperation());
                Operation portTypeOperation = newBindingOp.getOperation();
                
                /**
                 *
                 * Style should be set in <soap:binding/>, not in 
                 *
                 * WS-I Basic Profile 1.0 :
                 *
                 * 5.6.3 Consistency of style Attribute :
                 *
                 * The style, "document" or "rpc", of an interaction is specified
                 * at the wsdl:operation level, permitting wsdl:bindings whose wsdl:operations
                 * have different styles. This has led to interoperability problems.
                 *
                 * R2705 A wsdl:binding in a DESCRIPTION MUST use either be a rpc-literal binding
                 * or a document-literal binding.
                 *
                 */
                if(style == null) {
                    style = getStyle(portTypeOperation);
                    if(RPC_STYLE.equals(style)) { // default style is 'document', no need to set.
                        soapBinding.setStyle(style);
                    }
                }
                
                // Add > name="#operation".
                newBindingOp.setName(originalBindingOp.getName());
                newBindingOp.setDocumentationElement(originalBindingOp.getDocumentationElement());
                
                // Add -> <soap:operation/>
                SOAPOperation soapOperation = createSoapOperation();
                newBindingOp.addExtensibilityElement(soapOperation);
                
                // Add -> <wsdl:input>
                if(portTypeOperation.getInput() != null) {
                    BindingInput newBindingInput = defn.createBindingInput();
                    processElement(
                            newBindingInput,
                            portTypeOperation.getInput().getMessage(),
                            style);
                    newBindingOp.setBindingInput(newBindingInput);
                }
                
                // Add -> <wsdl:output>
                if(portTypeOperation.getOutput() != null) {
                    BindingOutput newBindingOutput = defn.createBindingOutput();
                    processElement(
                            newBindingOutput,
                            portTypeOperation.getOutput().getMessage(),
                            style);
                    newBindingOp.setBindingOutput(newBindingOutput);
                }
                
                // Add -> <wsdl:fault name="faultname">....more faults...
                if(portTypeOperation.getFaults() != null) {
                    Map<String,Fault> faults = portTypeOperation.getFaults();
                    for(String faultName : faults.keySet()) {
                        BindingFault newBindingFault = defn.createBindingFault();
                        newBindingFault.setName(faultName);
                        
                        SOAPFault soapFault = createSoapFault();
                        soapFault.setName(faultName);
                        
                        newBindingFault.addExtensibilityElement(soapFault);
                        newBindingOp.addBindingFault(newBindingFault);
                    }
                }
                
                newBinding.addBindingOperation(newBindingOp);
            }
            
            /**
             * Step4. Replace the existing <wsdl:binding> with new one.
             */
            defn.removeBinding(originalBindingQname);
            defn.addBinding(newBinding);
        }
        
        return wsdlModified;
    }
    
    private void writeWSDL(Definition defn, String wsdl) throws Exception {
        
        defn.addNamespace(SOAP_PREFIX, SOAP_NS);
        /**
         * Take care of i18n while creating a FileWriter.
         */
        FileWriter fw = new FileWriter(wsdl);
        wsdlWriter.writeWSDL(defn, fw);
        fw.close();
    }
    
    public boolean convert(String wsdl) throws Exception {
        
        String wsdlLocationUri = new File(wsdl).toURI().toString();
        
        Definition defn = wsdlReader.readWSDL(wsdlLocationUri);
        
        boolean wsdlModified = false;
        /**
         * Modify the <wsdl:binding> sections.
         */
        wsdlModified = convertBindings(defn);
        
        /**
         * Modify the <wsdl:service> sections.
         */
        wsdlModified = convertServices(defn);
        
        if(wsdlModified) {
            System.out.println("Modified WSDL : " + wsdl);
            writeWSDL(defn, wsdl);
        }
        
        return wsdlModified;
    }
    
    List<String> listWSDLs(File baseDir) {
        List<String> files = new ArrayList();
        for(File f : baseDir.listFiles()) {
            if(f.isDirectory()) {
                files.addAll(listWSDLs(f));
            } else if(f.getAbsolutePath().endsWith("wsdl")) {
                files.add(f.getAbsolutePath());
            }
        }
        return files;
    }
    
    public List<String> convertAllWSDLs(String baseDir) {
        List<String> convertedWSDLs = new ArrayList();
        List<String> wsdls = listWSDLs(new File(baseDir));
        for(String wsdl : wsdls) {
            try {
                if(convert(wsdl)) {
                    convertedWSDLs.add(wsdl.substring(baseDir.length() + 1));
                }
            } catch(Exception ex) {
                ex.printStackTrace();
            }
        }
        System.out.println("BaseDir = " + baseDir + ", Converted WSDLs = " + convertedWSDLs);
        return convertedWSDLs;
    }
    
    public static List<String> convertWSDLs(String baseDir) {
        try {
            WSDLConverter converter = new WSDLConverter();
            return converter.convertAllWSDLs(baseDir);
        } catch(Exception ex) {
            ex.printStackTrace();
        }
        return new ArrayList<String>();
    }
    
    void print(String s) {
        System.out.println(s);
    }
    
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws Exception {
        
        convertWSDLs("/tmp/wsdl");//System.getProperty("java.io.tmpdir"));
        
    }
    
    
}

Other Glassfish examples (source code examples)

Here is a short list of links related to this Glassfish WSDLConverter.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.