Package org.objectweb.celtix.wsdl

Source Code of org.objectweb.celtix.wsdl.EndpointReferenceUtils

package org.objectweb.celtix.wsdl;

import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.jws.WebService;
import javax.wsdl.Definition;
import javax.wsdl.Import;
import javax.wsdl.Port;
import javax.wsdl.Service;
import javax.wsdl.Types;
import javax.wsdl.WSDLException;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBElement;
import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.WebServiceProvider;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

import org.objectweb.celtix.common.logging.LogUtils;
import org.objectweb.celtix.jaxb.JAXBUtils;
import org.objectweb.celtix.ws.addressing.AttributedURIType;
import org.objectweb.celtix.ws.addressing.EndpointReferenceType;
import org.objectweb.celtix.ws.addressing.MetadataType;
import org.objectweb.celtix.ws.addressing.ObjectFactory;
import org.objectweb.celtix.ws.addressing.wsdl.AttributedQNameType;
import org.objectweb.celtix.ws.addressing.wsdl.ServiceNameType;

/**
* Provides utility methods for obtaining endpoint references, wsdl definitions, etc.
*/
public final class EndpointReferenceUtils {

    static WeakHashMap<Definition, Schema> schemaMap = new WeakHashMap<Definition, Schema>();

    private static final Logger LOG = LogUtils.getL7dLogger(EndpointReferenceUtils.class);

    private static final QName WSDL_LOCATION = new QName("http://www.w3.org/2006/01/wsdl-instance",
                                                         "wsdlLocation");
    private static final Transformer XML_TRANSFORMER;
    static {
        Transformer transformer = null;
        try {
            TransformerFactory tf = TransformerFactory.newInstance();
            transformer = tf.newTransformer();           
        } catch (TransformerConfigurationException tce) {
            throw new WebServiceException("Could not create transformer", tce);
        }
        XML_TRANSFORMER = transformer;
    }
   
    private EndpointReferenceUtils() {
        // Utility class - never constructed
    }
   
    /**
     * Sets the service and port name of the provided endpoint reference.
     * @param ref the endpoint reference.
     * @param serviceName the name of service.
     * @param portName the port name.
     */
    public static void setServiceAndPortName(EndpointReferenceType ref,
                                             QName serviceName,
                                             String portName)
        throws WebServiceException {
        if (null != serviceName) {
            ServiceNameType serviceNameType = new ServiceNameType();
            serviceNameType.setValue(serviceName);
            serviceNameType.setEndpointName(portName);
            org.objectweb.celtix.ws.addressing.wsdl.ObjectFactory objectFactory =
                new org.objectweb.celtix.ws.addressing.wsdl.ObjectFactory();
            JAXBElement<ServiceNameType> jaxbElement = objectFactory.createServiceName(serviceNameType);

            MetadataType mt = ref.getMetadata();
            if (null == mt) {
                mt = new MetadataType();
                ref.setMetadata(mt);
            }

            mt.getAny().add(jaxbElement);
        }
    }
   
    /**
     * Gets the service name of the provided endpoint reference.
     * @param ref the endpoint reference.
     * @return the service name.
     */
    public static QName getServiceName(EndpointReferenceType ref) {
        MetadataType metadata = ref.getMetadata();
        if (metadata != null) {
            for (Object obj : metadata.getAny()) {
                if (obj instanceof Element) {
                    Node node = (Element)obj;
                    if (node.getNamespaceURI().equals("http://www.w3.org/2005/08/addressing/wsdl")
                        && node.getLocalName().equals("ServiceName")) {
                        String content = node.getTextContent();
                        String namespaceURI = node.getFirstChild().getNamespaceURI();
                        String service = content;
                        if (content.contains(":")) {
                            namespaceURI = getNameSpaceUri(node, content, namespaceURI);
                            service = getService(content);
                        } else {
                            Node nodeAttr = node.getAttributes().getNamedItem("xmlns");
                            namespaceURI = nodeAttr.getNodeValue();
                        }
                       
                        return new QName(namespaceURI, service);
                    }
                } else if (obj instanceof JAXBElement) {
                    Object val = ((JAXBElement)obj).getValue();
                    if (val instanceof ServiceNameType) {
                        return ((ServiceNameType)val).getValue();
                    }
                } else if (obj instanceof ServiceNameType) {
                    return ((ServiceNameType)obj).getValue();
                }
            }
        }
        return null;
    }
   
    /**
     * Gets the port name of the provided endpoint reference.
     * @param ref the endpoint reference.
     * @return the port name.
     */
    public static String getPortName(EndpointReferenceType ref) {
        MetadataType metadata = ref.getMetadata();
        if (metadata != null) {
            for (Object obj : metadata.getAny()) {
                if (obj instanceof Element) {
                    Node node = (Element)obj;
                    if (node.getNamespaceURI().equals("http://www.w3.org/2005/08/addressing/wsdl")
                        && node.getNodeName().contains("ServiceName")) {
                        return node.getAttributes().getNamedItem("EndpointName").getTextContent();
                    }
                } else if (obj instanceof JAXBElement) {
                    Object val = ((JAXBElement)obj).getValue();
                    if (val instanceof ServiceNameType) {
                        return ((ServiceNameType)val).getEndpointName();
                    }
                } else if (obj instanceof ServiceNameType) {
                    return ((ServiceNameType)obj).getEndpointName();
                }
            }
        }
        return null;
    }
   
    public static void setInterfaceName(EndpointReferenceType ref, QName portTypeName) {
        if (null != portTypeName) {
            AttributedQNameType interfaceNameType = new AttributedQNameType();
           
            interfaceNameType.setValue(portTypeName);
           
            org.objectweb.celtix.ws.addressing.wsdl.ObjectFactory objectFactory =
                new org.objectweb.celtix.ws.addressing.wsdl.ObjectFactory();
            JAXBElement<AttributedQNameType> jaxbElement =
                objectFactory.createInterfaceName(interfaceNameType);

            MetadataType mt = ref.getMetadata();
            if (null == mt) {
                mt = new MetadataType();
                ref.setMetadata(mt);
            }
            mt.getAny().add(jaxbElement);
        }
    }
 
    public static QName getInterfaceName(EndpointReferenceType ref) {
        MetadataType metadata = ref.getMetadata();
        if (metadata != null) {
            for (Object obj : metadata.getAny()) {
                if (obj instanceof Element) {
                    Node node = (Element)obj;
                    System.out.println(node.getNamespaceURI() + ":" + node.getNodeName());
                    if (node.getNamespaceURI().equals("http://www.w3.org/2005/08/addressing/wsdl")
                        && node.getNodeName().contains("InterfaceName")) {
                       
                        String content = node.getTextContent();
                        String namespaceURI = node.getFirstChild().getNamespaceURI();
                        //String service = content;
                        if (content.contains(":")) {
                            namespaceURI = getNameSpaceUri(node, content, namespaceURI);
                            content = getService(content);
                        } else {
                            Node nodeAttr = node.getAttributes().getNamedItem("xmlns");
                            namespaceURI = nodeAttr.getNodeValue();
                        }

                        return new QName(namespaceURI, content);
                    }
                } else if (obj instanceof JAXBElement) {
                    Object val = ((JAXBElement)obj).getValue();
                    if (val instanceof AttributedQNameType) {
                        return ((AttributedQNameType)val).getValue();
                    }
                } else if (obj instanceof AttributedQNameType) {
                    return ((AttributedQNameType)obj).getValue();
                }
            }
        }

        return null;
    }
   
    private static void setWSDLLocation(EndpointReferenceType ref, String... wsdlLocation) {
       
        MetadataType metadata = ref.getMetadata();
        if (null == metadata) {
            metadata = new MetadataType();
            ref.setMetadata(metadata);
        }

        //wsdlLocation attribute is a list of anyURI.
        StringBuffer strBuf = new StringBuffer();
        for (String str : wsdlLocation) {
            strBuf.append(str);
            strBuf.append(" ");
        }

        metadata.getOtherAttributes().put(WSDL_LOCATION, strBuf.toString().trim());
    }
   
    public static String getWSDLLocation(EndpointReferenceType ref) {
        String wsdlLocation = null;
        MetadataType metadata = ref.getMetadata();

        if (metadata != null) {
            wsdlLocation = metadata.getOtherAttributes().get(WSDL_LOCATION);
        }

        if (null == wsdlLocation) {
            return null;
        }

        //TODO The wsdlLocation inserted should be a valid URI
        //before doing a split. So temporarily return the string
        //return wsdlLocation.split(" ");
        return wsdlLocation;
    }

    /**
     * Sets the metadata on the provided endpoint reference.
     * @param ref the endpoint reference.
     * @param the list of metadata source.
     */
    public static void setMetadata(EndpointReferenceType ref, List<Source> metadata) {
        if (null != ref) {
            MetadataType mt = ref.getMetadata();
            if (null == mt) {
                mt = new MetadataType();
                ref.setMetadata(mt);
            }
            List<Object> anyList = mt.getAny();
            try {
                for (Source source : metadata) {
                    Node node = null;
                    boolean doTransform = true;
                    if (source instanceof StreamSource) {
                        StreamSource ss = (StreamSource)source;
                        if (null == ss.getInputStream()
                            && null == ss.getReader()) {
                            setWSDLLocation(ref, ss.getSystemId());
                            doTransform = false;
                        }
                    } else if (source instanceof DOMSource) {
                        node = ((DOMSource)node).getNode();
                        doTransform = false;
                    }
                   
                    if (doTransform) {
                        DOMResult domResult = new DOMResult();
                        domResult.setSystemId(source.getSystemId());
                       
                        XML_TRANSFORMER.transform(source, domResult);
   
                        node = domResult.getNode();
                    }
                   
                    if (null != node) {
                        if (node instanceof Document) {
                            ((Document)node).setDocumentURI(source.getSystemId());
                            node =  node.getFirstChild();
                        }
                       
                        while (node.getNodeType() != Node.ELEMENT_NODE) {
                            node = node.getNextSibling();
                        }
                       
                        anyList.add(node);
                    }
                }
            } catch (TransformerException te) {
                throw new WebServiceException("Populating metadata in EPR failed", te);
            }
        }
    }
  
    /**
     * Gets the WSDL definition for the provided endpoint reference.
     * @param manager - the WSDL manager
     * @param ref - the endpoint reference
     * @return Definition the wsdl definition
     * @throws WSDLException
     */
    public static Definition getWSDLDefinition(WSDLManager manager, EndpointReferenceType ref)
        throws WSDLException {

        if (null == manager) {
            return null;
        }

        MetadataType metadata = ref.getMetadata();
        String location = getWSDLLocation(ref);

        if (null != location) {
            //Pick up the first url to obtain the wsdl defintion
            return manager.getDefinition(location);
        }

        for (Object obj : metadata.getAny()) {
            if (obj instanceof Element) {
                Element el = (Element)obj;
                if ("http://schemas.xmlsoap.org/wsdl/".equals(el.getNamespaceURI())
                    && "definitions".equals(el.getLocalName())) {
                    return manager.getDefinition(el);
                }
            }
        }

        QName portTypeName = getInterfaceName(ref);
        if (null != portTypeName) {
           
            StringBuffer seiName = new StringBuffer();
            seiName.append(JAXBUtils.namespaceURIToPackage(portTypeName.getNamespaceURI()));
            seiName.append(".");
            seiName.append(JAXBUtils.nameToIdentifier(portTypeName.getLocalPart(),
                                                      JAXBUtils.IdentifierType.INTERFACE));
           
            Class<?> sei = null;
            try {
                sei = Class.forName(seiName.toString(), true,
                                    manager.getClass().getClassLoader());
            } catch (ClassNotFoundException ex) {
                LOG.log(Level.INFO, "SEI_LOAD_FAILURE_MSG", ex);
                return null;
            }
            Definition def = manager.getDefinition(sei);
            if (def == null && sei.getInterfaces().length > 0) {
                sei = sei.getInterfaces()[0];
                def = manager.getDefinition(sei);
            }
            return def;
        }
        return null;
    }

    private static List<javax.wsdl.extensions.schema.Schema> getSchemas(Definition definition) {
        Types types = definition.getTypes();
        List<javax.wsdl.extensions.schema.Schema> schemaList =
            new ArrayList<javax.wsdl.extensions.schema.Schema>();
        if (types != null) {
            for (Object o : types.getExtensibilityElements()) {
                if (o instanceof javax.wsdl.extensions.schema.Schema) {
                    javax.wsdl.extensions.schema.Schema s =
                        (javax.wsdl.extensions.schema.Schema)o;
                    schemaList.add(s);
                }
            }
        }

        Map wsdlImports = definition.getImports();
        for (Object o : wsdlImports.values()) {
            if (o instanceof List) {
                for (Object p : (List)o) {
                    if (p instanceof Import) {
                        schemaList.addAll(getSchemas(((Import)p).getDefinition()));
                    }
                }
            }
        }
        return schemaList;
    }

    public static Schema getSchema(WSDLManager manager, EndpointReferenceType ref) {
        Definition definition;
        try {
            definition = getWSDLDefinition(manager, ref);
        } catch (javax.wsdl.WSDLException wsdlEx) {
            return null;
        }
        if (definition == null) {
            return null;
        }
        synchronized (schemaMap) {
            if (schemaMap.containsKey(definition)) {
                return schemaMap.get(definition);
            }
        }
        Schema schema = schemaMap.get(definition);
        if (schema == null) {
            List<javax.wsdl.extensions.schema.Schema> schemas = getSchemas(definition);
            SchemaFactory factory = SchemaFactory.newInstance(
                XMLConstants.W3C_XML_SCHEMA_NS_URI);
            List<Source> schemaSources = new ArrayList<Source>();
            for (javax.wsdl.extensions.schema.Schema s : schemas) {
                Source source = new DOMSource(s.getElement());
                if (source != null) {
                    schemaSources.add(source);
                }
            }
            try {
                schema = factory.newSchema(schemaSources.toArray(
                    new Source[schemaSources.size()]));
                if (schema != null) {
                    synchronized (schemaMap) {
                        schemaMap.put(definition, schema);
                    }
                    LOG.log(Level.FINE, "Obtained schema from wsdl definition");
                }
            } catch (SAXException ex) {
                // Something not right with the schema from the wsdl.
                LOG.log(Level.WARNING, "SAXException for newSchema()", ex);
            }
        }
        return schema;
    }
   
    /**
     * Gets the WSDL port for the provided endpoint reference.
     * @param manager - the WSDL manager
     * @param ref - the endpoint reference
     * @return Port the wsdl port
     * @throws WSDLException
     */
    public static Port getPort(WSDLManager manager, EndpointReferenceType ref) throws WSDLException {

        Definition def = getWSDLDefinition(manager, ref);
        if (def == null) {
            throw new WSDLException(WSDLException.OTHER_ERROR, "unable to find definition for reference");
        }

        MetadataType metadata = ref.getMetadata();
        for (Object obj : metadata.getAny()) {
           
            if (obj instanceof JAXBElement) {
                Object jaxbVal = ((JAXBElement)obj).getValue();

                if (jaxbVal instanceof ServiceNameType) {
                    Port port = null;
                    ServiceNameType snt = (ServiceNameType)jaxbVal;
                    LOG.log(Level.FINEST, "found service name ", snt.getEndpointName());
                    Service service = def.getService(snt.getValue());
                    if (service == null) {
                        service = (Service)def.getServices().values().iterator().next();
                        if (service == null) {
                            return null;
                        }
                    }
                    String endpoint = snt.getEndpointName();
                    if ("".equals(endpoint) && service.getPorts().size() == 1) {
                        port = (Port)service.getPorts().values().iterator().next();
                    } else {
                        port = service.getPort(endpoint);
                    }
                    // FIXME this needs to be looked at service.getPort(endpoint)
                    //should not return null when endpoint is valid
                    if (port == null) {
                        port = (Port)service.getPorts().values().iterator().next();
                    }
                    return port;
                }
            }
        }

        if (def.getServices().size() == 1) {
            Service service = (Service)def.getServices().values().iterator().next();
            if (service.getPorts().size() == 1) {
                return (Port)service.getPorts().values().iterator().next();
            }
        }
       
        QName serviceName = getServiceName(ref);
        if (null != serviceName) {
            Service service = def.getService(serviceName);
            if (service == null) {
                throw new WSDLException(WSDLException.OTHER_ERROR, "Cannot find service for " + serviceName);
            }
            if (service.getPorts().size() == 1) {
                return (Port)service.getPorts().values().iterator().next();
            }
            String str = getPortName(ref);
            LOG.log(Level.FINE, "getting port " + str + " from service " + service.getQName());
            Port port = service.getPort(str);
            if (port == null) {
                throw new WSDLException(WSDLException.OTHER_ERROR, "unable to find port " + str);
            }
            return port;
        }
        // TODO : throw exception here
        return null;
    }

    /**
     * Get the address from the provided endpoint reference.
     * @param ref - the endpoint reference
     * @return String the address of the endpoint
     */
    public static String getAddress(EndpointReferenceType ref) {
        AttributedURIType a = ref.getAddress();
        if (null != a) {
            return a.getValue();
        }
        // should wsdl be parsed for an address now?
        return null;
    }

    /**
     * Set the address of the provided endpoint reference.
     * @param ref - the endpoint reference
     * @param address - the address
     */
    public static void setAddress(EndpointReferenceType ref, String address) {
        AttributedURIType a = new ObjectFactory().createAttributedURIType();
        a.setValue(address);
        ref.setAddress(a);
    }
    /**
     * Create an endpoint reference for the provided wsdl, service and portname.
     * @param wsdlUrl - url of the wsdl that describes the service.
     * @param serviceName - the <code>QName</code> of the service.
     * @param portName - the name of the port.
     * @return EndpointReferenceType - the endpoint reference
     */
    public static EndpointReferenceType getEndpointReference(URL wsdlUrl,
                                                             QName serviceName,
                                                             String portName) {
        EndpointReferenceType reference = new EndpointReferenceType();
        reference.setMetadata(new MetadataType());
        setServiceAndPortName(reference, serviceName, portName);
        //TODO To Ensure it is a valid URI syntax.
        setWSDLLocation(reference, wsdlUrl.toString());

        return reference;
    }
   
    /**
     * Create an endpoint reference for the provided .
     * @param address - address URI
     * @return EndpointReferenceType - the endpoint reference
     */
    public static EndpointReferenceType getEndpointReference(String address) {

        EndpointReferenceType reference = new EndpointReferenceType();
        setAddress(reference, address);
        return reference;
    }

    /**
     * Get the WebService for the provided class.  If the class
     * itself does not have a WebService annotation, this method
     * is called recursively on the class's interfaces and superclass.
     * @param cls - the Class .
     * @return WebService - the web service
     */
    public static WebService getWebServiceAnnotation(Class<?> cls) {
        if (cls == null) {
            return null;
        }
        WebService ws = cls.getAnnotation(WebService.class);
        if (null != ws) {
            return ws;
        }
        for (Class<?> inf : cls.getInterfaces()) {
            ws = getWebServiceAnnotation(inf);
            if (null != ws) {
                return ws;
            }
        }

        return getWebServiceAnnotation(cls.getSuperclass());
    }

    /**
     * Gets an endpoint reference for the provided implementor object.
     * @param manager - the wsdl manager.
     * @param implementor - the service implementor.
     * @return EndpointReferenceType - the endpoint reference
     * @throws WSDLException
     */
    public static EndpointReferenceType getEndpointReference(WSDLManager manager,
                                                                 Object implementor) {
        return getEndpointReference(manager, implementor.getClass());
    }

    /**
     * Gets an endpoint reference for the provided implementor object.
     * @param manager - the wsdl manager.
     * @param implementor - the service implementor.
     * @return EndpointReferenceType - the endpoint reference
     * @throws WSDLException
     */
    public static EndpointReferenceType getEndpointReference(WSDLManager manager,
                                                                 Class<?> implementorClass) {

        WebService ws = getWebServiceAnnotation(implementorClass);

        WebServiceProvider wsp = null;
        if (null == ws) {
            wsp = implementorClass.getAnnotation(WebServiceProvider.class);
            if (null == wsp) {
                return null;
            }
        }

        EndpointReferenceType reference = new EndpointReferenceType();
        reference.setMetadata(new MetadataType());
        String serviceName = (null != ws) ? ws.serviceName() : wsp.serviceName();
        String targetNamespace = (null != ws) ? ws.targetNamespace() : wsp.targetNamespace();
        String portName = (null != ws) ? ws.portName() : wsp.portName();
        String url = (null != ws) ? ws.wsdlLocation() : wsp.wsdlLocation();
        String className = (null != ws) ? ws.endpointInterface() : null;
    
        QName portTypeName = null;
        if (null != className && !"".equals(className)) {
            Class<?> seiClazz = null;
            try {
                seiClazz = Class.forName(className);
            } catch (ClassNotFoundException cnfe) {
                LOG.log(Level.SEVERE, "SEI_LOAD_FAILURE_MSG", cnfe);
                throw new WebServiceException("endpointInterface element in WebService annotation invalid",
                                              cnfe);
            }
           
            if (!seiClazz.isInterface()) {
                throw new WebServiceException("endpointInterface element does not refer to a java interface");
            }
           
            WebService seiws = seiClazz.getAnnotation(WebService.class);
            if (null == seiws) {
                throw new WebServiceException("SEI should have a WebService Annotation");
            }

            if ("".equals(url)) {
                url = seiws.wsdlLocation();
            }

            //WebService.name maps to wsdl:portType name.
            portTypeName = new QName(ws.targetNamespace(), seiws.name());

            //ServiceName,portName,endpointInterface not allowed on the WebService annotation
            // of a SEI, Section 3.2 JSR181.
            // set interfaceName using WebService.targetNamespace of SEI only.
        } else {

            if (null != ws) {
                className = ws.name();
            }
            if (null == className || "".equals(className)) {
                className = implementorClass.getSimpleName();
            }
            portTypeName = new QName(targetNamespace, className);
        }

        setInterfaceName(reference, portTypeName);
        // set serviceName, portName and targetNamespace
        if (!"".equals(serviceName)) {
            setServiceAndPortName(reference, new QName(targetNamespace, serviceName),
                                  portName);
        }

        if (null != url && url.length() > 0) {
            //REVISIT Resolve the url for all cases
            URL wsdlUrl = implementorClass.getResource(url);
            if (wsdlUrl != null) {
                url = wsdlUrl.toExternalForm();
            }
        }
        // set wsdlLocation
        if (!"".equals(url)) {
            setWSDLLocation(reference, url);
        }

        if (LOG.isLoggable(Level.FINE)) {
            LOG.fine("created endpoint reference with");
            LOG.fine("    service name: " + getServiceName(reference));
            LOG.fine("    wsdl location: " + getWSDLLocation(reference));
            LOG.fine("    sei class: " + getInterfaceName(reference));
        }
        return reference;
    }
   
    private static String getNameSpaceUri(Node node, String content, String namespaceURI) {
        if (namespaceURI == null) {
            namespaceURI =  node.lookupNamespaceURI(content.substring(0,
                                                                  content.indexOf(":")));
        }
        return namespaceURI;
    }

    private static String getService(String content) {
        return content.substring(content.indexOf(":") + 1, content.length());
    }   
}
TOP

Related Classes of org.objectweb.celtix.wsdl.EndpointReferenceUtils

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.