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

Java example source code file (DeploymentDescriptorParser.java)

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

Learn more about this Java project at its project page.

Java - Java tags/keywords

adapterfactory, attributes, class, externalmetadatafeature, list, locatablewebserviceexception, log, logging, malformedurlexception, net, network, notnull, qname, sddocumentsource, serverrtexception, string, util, web\-inf\/wsdl, xml, xmlstreamreader

The DeploymentDescriptorParser.java Java example source code

/*
 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.xml.internal.ws.transport.http;

import com.oracle.webservices.internal.api.databinding.DatabindingModeFeature;
import com.oracle.webservices.internal.api.databinding.ExternalMetadataFeature;
import com.sun.istack.internal.NotNull;
import com.sun.xml.internal.ws.api.BindingID;
import com.sun.xml.internal.ws.api.WSBinding;
import com.sun.xml.internal.ws.api.databinding.MetadataReader;
import com.sun.xml.internal.ws.api.server.Container;
import com.sun.xml.internal.ws.api.server.SDDocumentSource;
import com.sun.xml.internal.ws.api.server.WSEndpoint;
import com.sun.xml.internal.ws.api.streaming.XMLStreamReaderFactory;
import com.sun.xml.internal.ws.binding.WebServiceFeatureList;

import com.sun.xml.internal.ws.handler.HandlerChainsModel;
import com.sun.xml.internal.ws.resources.ServerMessages;
import com.sun.xml.internal.ws.resources.WsservletMessages;
import com.sun.xml.internal.ws.server.EndpointFactory;
import com.sun.xml.internal.ws.server.ServerRtException;
import com.sun.xml.internal.ws.streaming.Attributes;
import com.sun.xml.internal.ws.streaming.TidyXMLStreamReader;
import com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil;
import com.sun.xml.internal.ws.util.HandlerAnnotationInfo;
import com.sun.xml.internal.ws.util.exception.LocatableWebServiceException;
import com.sun.xml.internal.ws.util.xml.XmlUtil;
import org.xml.sax.EntityResolver;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.WebServiceFeature;
import javax.xml.ws.http.HTTPBinding;
import javax.xml.ws.soap.MTOMFeature;
import javax.xml.ws.soap.SOAPBinding;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Parses {@code sun-jaxws.xml} into {@link WSEndpoint}.
 * <p/>
 * <p/>
 * Since {@code sun-jaxws.xml} captures more information than what {@link WSEndpoint}
 * represents (in particular URL pattern and name), this class
 * takes a parameterization 'A' so that the user of this parser can choose to
 * create another type that wraps {@link WSEndpoint}.
 * <p/>
 * {@link HttpAdapter} and its derived type is used for this often,
 * but it can be anything.
 *
 * @author WS Development Team
 * @author Kohsuke Kawaguchi
 */
public class DeploymentDescriptorParser<A> {

    public static final String NS_RUNTIME = "http://java.sun.com/xml/ns/jax-ws/ri/runtime";
    public static final String JAXWS_WSDL_DD_DIR = "WEB-INF/wsdl";

    public static final QName QNAME_ENDPOINTS = new QName(NS_RUNTIME, "endpoints");
    public static final QName QNAME_ENDPOINT = new QName(NS_RUNTIME, "endpoint");
    public static final QName QNAME_EXT_METADA = new QName(NS_RUNTIME, "external-metadata");

    public static final String ATTR_FILE = "file";
    public static final String ATTR_RESOURCE = "resource";

    public static final String ATTR_VERSION = "version";
    public static final String ATTR_NAME = "name";
    public static final String ATTR_IMPLEMENTATION = "implementation";
    public static final String ATTR_WSDL = "wsdl";
    public static final String ATTR_SERVICE = "service";
    public static final String ATTR_PORT = "port";
    public static final String ATTR_URL_PATTERN = "url-pattern";
    public static final String ATTR_ENABLE_MTOM = "enable-mtom";
    public static final String ATTR_MTOM_THRESHOLD_VALUE = "mtom-threshold-value";
    public static final String ATTR_BINDING = "binding";
    public static final String ATTR_DATABINDING = "databinding";

    public static final List<String> ATTRVALUE_SUPPORTED_VERSIONS = Arrays.asList("2.0", "2.1");

    private static final Logger logger = Logger.getLogger(com.sun.xml.internal.ws.util.Constants.LoggingDomain + ".server.http");

    private final Container container;
    private final ClassLoader classLoader;
    private final ResourceLoader loader;
    private final AdapterFactory<A> adapterFactory;

    /**
     * Endpoint names that are declared.
     * Used to catch double definitions.
     */
    private final Set<String> names = new HashSet();

    /**
     * WSDL/schema documents collected from /WEB-INF/wsdl. Keyed by the system ID.
     */
    private final Map<String, SDDocumentSource> docs = new HashMap();

    /**
     * @param cl             Used to load service implementations.
     * @param loader         Used to locate resources, in particular WSDL.
     * @param container      Optional {@link Container} that {@link WSEndpoint}s receive.
     * @param adapterFactory Creates {@link HttpAdapter} (or its derived class.)
     */
    public DeploymentDescriptorParser(ClassLoader cl, ResourceLoader loader, Container container,
                                      AdapterFactory<A> adapterFactory) throws MalformedURLException {
        classLoader = cl;
        this.loader = loader;
        this.container = container;
        this.adapterFactory = adapterFactory;

        collectDocs("/WEB-INF/wsdl/");
        logger.log(Level.FINE, "war metadata={0}", docs);
    }

    /**
     * Parses the {@code sun-jaxws.xml} file and configures
     * a set of {@link HttpAdapter}s.
     */
    public @NotNull List<A> parse(String systemId, InputStream is) {
        XMLStreamReader reader = null;
        try {
            reader = new TidyXMLStreamReader(
                    XMLStreamReaderFactory.create(systemId, is, true), is);
            XMLStreamReaderUtil.nextElementContent(reader);
            return parseAdapters(reader);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (XMLStreamException e) {
                    throw new ServerRtException("runtime.parser.xmlReader", e);
                }
            }
            try {
                is.close();
            } catch (IOException e) {
                // ignore
            }
        }
    }

    /**
     * Parses the {@code sun-jaxws.xml} file and configures
     * a set of {@link HttpAdapter}s.
     */
    public @NotNull List<A> parse(File f) throws IOException {
        FileInputStream in = new FileInputStream(f);
        try {
            return parse(f.getPath(), in);
        } finally {
            in.close();
        }
    }

    /**
     * Get all the WSDL & schema documents recursively.
     */
    private void collectDocs(String dirPath) throws MalformedURLException {
        Set<String> paths = loader.getResourcePaths(dirPath);
        if (paths != null) {
            for (String path : paths) {
                if (path.endsWith("/")) {
                    if (path.endsWith("/CVS/") || path.endsWith("/.svn/")) {
                        continue;
                    }
                    collectDocs(path);
                } else {
                    URL res = loader.getResource(path);
                    docs.put(res.toString(), SDDocumentSource.create(res));
                }
            }
        }
    }


    private List<A> parseAdapters(XMLStreamReader reader) {
        if (!reader.getName().equals(QNAME_ENDPOINTS)) {
            failWithFullName("runtime.parser.invalidElement", reader);
        }

        List<A> adapters = new ArrayList();

        Attributes attrs = XMLStreamReaderUtil.getAttributes(reader);
        String version = getMandatoryNonEmptyAttribute(reader, attrs, ATTR_VERSION);
        if (!ATTRVALUE_SUPPORTED_VERSIONS.contains(version)) {
            failWithLocalName("runtime.parser.invalidVersionNumber", reader, version);
        }

        while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {

            if (reader.getName().equals(QNAME_ENDPOINT)) {
                attrs = XMLStreamReaderUtil.getAttributes(reader);

                String name = getMandatoryNonEmptyAttribute(reader, attrs, ATTR_NAME);
                if (!names.add(name)) {
                    logger.warning(
                            WsservletMessages.SERVLET_WARNING_DUPLICATE_ENDPOINT_NAME(/*name*/));
                }

                String implementationName =
                        getMandatoryNonEmptyAttribute(reader, attrs, ATTR_IMPLEMENTATION);
                Class<?> implementorClass = getImplementorClass(implementationName, reader);

                MetadataReader metadataReader = null;
                ExternalMetadataFeature externalMetadataFeature = null;

                // parse subelements to instantiate externalMetadataReader, if necessary ...
                XMLStreamReaderUtil.nextElementContent(reader);
                if (reader.getEventType() != XMLStreamConstants.END_ELEMENT) {
                    externalMetadataFeature = configureExternalMetadataReader(reader);
                    if (externalMetadataFeature != null) {
                        metadataReader = externalMetadataFeature.getMetadataReader(implementorClass.getClassLoader(), false);
                    }
                }

                QName serviceName = getQNameAttribute(attrs, ATTR_SERVICE);
                if (serviceName == null) {
                    serviceName = EndpointFactory.getDefaultServiceName(implementorClass, metadataReader);
                }

                QName portName = getQNameAttribute(attrs, ATTR_PORT);
                if (portName == null) {
                    portName = EndpointFactory.getDefaultPortName(serviceName, implementorClass, metadataReader);
                }

                //get enable-mtom attribute value
                String enable_mtom = getAttribute(attrs, ATTR_ENABLE_MTOM);
                String mtomThreshold = getAttribute(attrs, ATTR_MTOM_THRESHOLD_VALUE);
                String dbMode = getAttribute(attrs, ATTR_DATABINDING);
                String bindingId = getAttribute(attrs, ATTR_BINDING);
                if (bindingId != null) {
                    // Convert short-form tokens to API's binding ids
                    bindingId = getBindingIdForToken(bindingId);
                }
                WSBinding binding = createBinding(bindingId, implementorClass, enable_mtom, mtomThreshold, dbMode);
                if (externalMetadataFeature != null) {
                        binding.getFeatures().mergeFeatures(new WebServiceFeature[]{externalMetadataFeature},
                        true);
                }

                String urlPattern = getMandatoryNonEmptyAttribute(reader, attrs, ATTR_URL_PATTERN);

                // TODO use 'docs' as the metadata. If wsdl is non-null it's the primary.
                boolean handlersSetInDD = setHandlersAndRoles(binding, reader, serviceName, portName);

                EndpointFactory.verifyImplementorClass(implementorClass, metadataReader);
                SDDocumentSource primaryWSDL = getPrimaryWSDL(reader, attrs, implementorClass, metadataReader);

                WSEndpoint<?> endpoint = WSEndpoint.create(
                        implementorClass, !handlersSetInDD,
                        null,
                        serviceName, portName, container, binding,
                        primaryWSDL, docs.values(), createEntityResolver(), false
                );
                adapters.add(adapterFactory.createAdapter(name, urlPattern, endpoint));
            } else {
                failWithLocalName("runtime.parser.invalidElement", reader);
            }
        }
        return adapters;
    }

    /**
     * @param ddBindingId   binding id explicitlyspecified in the DeploymentDescriptor or parameter
     * @param implClass     Endpoint Implementation class
     * @param mtomEnabled   represents mtom-enabled attribute in DD
     * @param mtomThreshold threshold value specified in DD
     * @return is returned with only MTOMFeature set resolving the various precendece rules
     */
    private static WSBinding createBinding(String ddBindingId, Class implClass,
                                           String mtomEnabled, String mtomThreshold, String dataBindingMode) {
        // Features specified through DD
        WebServiceFeatureList features;

        MTOMFeature mtomfeature = null;
        if (mtomEnabled != null) {
            if (mtomThreshold != null) {
                mtomfeature = new MTOMFeature(Boolean.valueOf(mtomEnabled),
                        Integer.valueOf(mtomThreshold));
            } else {
                mtomfeature = new MTOMFeature(Boolean.valueOf(mtomEnabled));
            }
        }

        BindingID bindingID;
        if (ddBindingId != null) {
            bindingID = BindingID.parse(ddBindingId);
            features = bindingID.createBuiltinFeatureList();

            if (checkMtomConflict(features.get(MTOMFeature.class), mtomfeature)) {
                throw new ServerRtException(ServerMessages.DD_MTOM_CONFLICT(ddBindingId, mtomEnabled));
            }
        } else {
            bindingID = BindingID.parse(implClass);
            // Since bindingID is coming from implclass,
            // mtom through Feature annotation or DD takes precendece

            features = new WebServiceFeatureList();
            if (mtomfeature != null) {  // this wins over MTOM setting in bindingID
                features.add(mtomfeature);
            }
            features.addAll(bindingID.createBuiltinFeatureList());
        }

        if (dataBindingMode != null) {
            features.add(new DatabindingModeFeature(dataBindingMode));
        }

        return bindingID.createBinding(features.toArray());
    }

    private static boolean checkMtomConflict(MTOMFeature lhs, MTOMFeature rhs) {
        if (lhs == null || rhs == null) {
            return false;
        }
        return lhs.isEnabled() ^ rhs.isEnabled();
    }

    /**
     * JSR-109 defines short-form tokens for standard binding Ids. These are
     * used only in DD. So stand alone deployment descirptor should also honor
     * these tokens. This method converts the tokens to API's standard
     * binding ids
     *
     * @param lexical binding attribute value from DD. Always not null
     * @return returns corresponding API's binding ID or the same lexical
     */
    public static @NotNull String getBindingIdForToken(@NotNull String lexical) {
        if (lexical.equals("##SOAP11_HTTP")) {
            return SOAPBinding.SOAP11HTTP_BINDING;
        } else if (lexical.equals("##SOAP11_HTTP_MTOM")) {
            return SOAPBinding.SOAP11HTTP_MTOM_BINDING;
        } else if (lexical.equals("##SOAP12_HTTP")) {
            return SOAPBinding.SOAP12HTTP_BINDING;
        } else if (lexical.equals("##SOAP12_HTTP_MTOM")) {
            return SOAPBinding.SOAP12HTTP_MTOM_BINDING;
        } else if (lexical.equals("##XML_HTTP")) {
            return HTTPBinding.HTTP_BINDING;
        }
        return lexical;
    }

    /**
     * Creates a new "Adapter".
     * <p/>
     * Normally 'A' would be {@link HttpAdapter} or some derived class.
     * But the parser doesn't require that to be of any particular type.
     */
    public static interface AdapterFactory<A> {
        A createAdapter(String name, String urlPattern, WSEndpoint<?> endpoint);
    }

    /**
     * Checks the deployment descriptor or {@link @WebServiceProvider} annotation
     * to see if it points to any WSDL. If so, returns the {@link SDDocumentSource}.
     *
     * @return The pointed WSDL, if any. Otherwise null.
     */
    private SDDocumentSource getPrimaryWSDL(XMLStreamReader xsr, Attributes attrs, Class<?> implementorClass, MetadataReader metadataReader) {

        String wsdlFile = getAttribute(attrs, ATTR_WSDL);
        if (wsdlFile == null) {
            wsdlFile = EndpointFactory.getWsdlLocation(implementorClass, metadataReader);
        }

        if (wsdlFile != null) {
            if (!wsdlFile.startsWith(JAXWS_WSDL_DD_DIR)) {
                logger.log(Level.WARNING, "Ignoring wrong wsdl={0}. It should start with {1}. Going to generate and publish a new WSDL.", new Object[]{wsdlFile, JAXWS_WSDL_DD_DIR});
                return null;
            }

            URL wsdl;
            try {
                wsdl = loader.getResource('/' + wsdlFile);
            } catch (MalformedURLException e) {
                throw new LocatableWebServiceException(
                        ServerMessages.RUNTIME_PARSER_WSDL_NOT_FOUND(wsdlFile), e, xsr);
            }
            if (wsdl == null) {
                throw new LocatableWebServiceException(
                        ServerMessages.RUNTIME_PARSER_WSDL_NOT_FOUND(wsdlFile), xsr);
            }
            SDDocumentSource docInfo = docs.get(wsdl.toExternalForm());
            assert docInfo != null;
            return docInfo;
        }

        return null;
    }

    /**
     * Creates an {@link EntityResolver} that consults {@code /WEB-INF/jax-ws-catalog.xml}.
     */
    private EntityResolver createEntityResolver() {
        try {
            return XmlUtil.createEntityResolver(loader.getCatalogFile());
        } catch (MalformedURLException e) {
            throw new WebServiceException(e);
        }
    }

    protected String getAttribute(Attributes attrs, String name) {
        String value = attrs.getValue(name);
        if (value != null) {
            value = value.trim();
        }
        return value;
    }

    protected QName getQNameAttribute(Attributes attrs, String name) {
        String value = getAttribute(attrs, name);
        if (value == null || value.equals("")) {
            return null;
        } else {
            return QName.valueOf(value);
        }
    }

    protected String getNonEmptyAttribute(XMLStreamReader reader, Attributes attrs, String name) {
        String value = getAttribute(attrs, name);
        if (value != null && value.equals("")) {
            failWithLocalName(
                    "runtime.parser.invalidAttributeValue",
                    reader,
                    name);
        }
        return value;
    }

    protected String getMandatoryAttribute(XMLStreamReader reader, Attributes attrs, String name) {
        String value = getAttribute(attrs, name);
        if (value == null) {
            failWithLocalName("runtime.parser.missing.attribute", reader, name);
        }
        return value;
    }

    protected String getMandatoryNonEmptyAttribute(XMLStreamReader reader, Attributes attributes,
                                                   String name) {
        String value = getAttribute(attributes, name);
        if (value == null) {
            failWithLocalName("runtime.parser.missing.attribute", reader, name);
        } else if (value.equals("")) {
            failWithLocalName(
                    "runtime.parser.invalidAttributeValue",
                    reader,
                    name);
        }
        return value;
    }

    /**
     * Parses the handler and role information and sets it
     * on the {@link WSBinding}.
     *
     * @return true if <handler-chains> element present in DD
     *         false otherwise.
     */
    protected boolean setHandlersAndRoles(WSBinding binding, XMLStreamReader reader, QName serviceName, QName portName) {

        if (reader.getEventType() == XMLStreamConstants.END_ELEMENT ||
                !reader.getName().equals(HandlerChainsModel.QNAME_HANDLER_CHAINS)) {
            return false;
        }

        HandlerAnnotationInfo handlerInfo = HandlerChainsModel.parseHandlerFile(
                reader, classLoader, serviceName, portName, binding);

        binding.setHandlerChain(handlerInfo.getHandlers());
        if (binding instanceof SOAPBinding) {
            ((SOAPBinding) binding).setRoles(handlerInfo.getRoles());
        }

        // move past </handler-chains>
        XMLStreamReaderUtil.nextContent(reader);
        return true;
    }

    protected ExternalMetadataFeature configureExternalMetadataReader(XMLStreamReader reader) {

        ExternalMetadataFeature.Builder featureBuilder = null;
        while (QNAME_EXT_METADA.equals(reader.getName())) {

            if (reader.getEventType() == XMLStreamConstants.START_ELEMENT) {
                Attributes attrs = XMLStreamReaderUtil.getAttributes(reader);
                String file = getAttribute(attrs, ATTR_FILE);
                if (file != null) {
                    if (featureBuilder == null) {
                        featureBuilder = ExternalMetadataFeature.builder();
                    }
                    featureBuilder.addFiles(new File(file));
                }

                String res = getAttribute(attrs, ATTR_RESOURCE);
                if (res != null) {
                    if (featureBuilder == null) {
                        featureBuilder = ExternalMetadataFeature.builder();
                    }
                    featureBuilder.addResources(res);
                }
            }

            XMLStreamReaderUtil.nextElementContent(reader);
        }

        return buildFeature(featureBuilder);
    }

    private ExternalMetadataFeature buildFeature(ExternalMetadataFeature.Builder builder) {
        return builder != null ? builder.build() : null;
    }

    protected static void fail(String key, XMLStreamReader reader) {
        logger.log(Level.SEVERE, "{0}{1}", new Object[]{key, reader.getLocation().getLineNumber()});
        throw new ServerRtException(
                key,
                Integer.toString(reader.getLocation().getLineNumber()));
    }

    protected static void failWithFullName(String key, XMLStreamReader reader) {
        throw new ServerRtException(
                key,
                reader.getLocation().getLineNumber(),
                reader.getName());
    }

    protected static void failWithLocalName(String key, XMLStreamReader reader) {
        throw new ServerRtException(
                key,
                reader.getLocation().getLineNumber(),
                reader.getLocalName());
    }

    protected static void failWithLocalName(String key, XMLStreamReader reader, String arg) {
        throw new ServerRtException(
                key,
                reader.getLocation().getLineNumber(),
                reader.getLocalName(),
                arg);
    }

    protected Class loadClass(String name) {
        try {
            return Class.forName(name, true, classLoader);
        } catch (ClassNotFoundException e) {
            logger.log(Level.SEVERE, e.getMessage(), e);
            throw new ServerRtException(
                    "runtime.parser.classNotFound",
                    name);
        }
    }


    /**
     * Loads the class of the given name.
     *
     * @param xsr Used to report the source location information if there's any error.
     */
    private Class getImplementorClass(String name, XMLStreamReader xsr) {
        try {
            return Class.forName(name, true, classLoader);
        } catch (ClassNotFoundException e) {
            logger.log(Level.SEVERE, e.getMessage(), e);
            throw new LocatableWebServiceException(
                    ServerMessages.RUNTIME_PARSER_CLASS_NOT_FOUND(name), e, xsr);
        }
    }

}
... 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.