org.seedstack.ws.jms.internal.WSJmsPlugin.java Source code

Java tutorial

Introduction

Here is the source code for org.seedstack.ws.jms.internal.WSJmsPlugin.java

Source

/**
 * Copyright (c) 2013-2016, The SeedStack authors <http://seedstack.org>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
package org.seedstack.ws.jms.internal;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import io.nuun.kernel.api.plugin.InitState;
import io.nuun.kernel.api.plugin.PluginException;
import io.nuun.kernel.api.plugin.context.InitContext;
import org.apache.commons.lang.StringUtils;
import org.seedstack.jms.internal.JmsPlugin;
import org.seedstack.jms.spi.ConnectionDefinition;
import org.seedstack.jms.spi.JmsFactory;
import org.seedstack.jms.spi.MessageListenerInstanceDefinition;
import org.seedstack.seed.SeedException;
import org.seedstack.seed.core.internal.AbstractSeedPlugin;
import org.seedstack.ws.internal.EndpointDefinition;
import org.seedstack.ws.internal.WSPlugin;
import org.seedstack.ws.jms.WebServicesJmsConfig;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Session;
import javax.naming.NamingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * This plugin provides JMS transport integration for WS support.
 */
public class WSJmsPlugin extends AbstractSeedPlugin {
    private static final List<String> SUPPORTED_BINDINGS = ImmutableList.of("http://www.w3.org/2010/soapjms/");
    private static final String LISTENER_NAME_PATTERN = "ws-%s-listener";
    private static final String ANONYMOUS_CONNECTION_PATTERN = "ws-anon-connection-%d";
    private final Set<WSJmsMessageListener> wsJmsMessageListeners = new HashSet<>();
    private LoadingCache<SoapJmsUri, Connection> connectionCache;
    private JmsPlugin jmsPlugin;

    @Override
    public String name() {
        return "wsJms";
    }

    @Override
    public Collection<Class<?>> dependencies() {
        return Lists.newArrayList(WSPlugin.class, JmsPlugin.class);
    }

    @Override
    public InitState initialize(InitContext initContext) {
        jmsPlugin = initContext.dependency(JmsPlugin.class);
        WSPlugin wsPlugin = initContext.dependency(WSPlugin.class);
        final WebServicesJmsConfig webServicesJmsConfig = getConfiguration(WebServicesJmsConfig.class);

        WebServicesJmsConfig.JmsConfig.CacheConfig cacheConfig = webServicesJmsConfig.jms().connectionCache();
        int cacheSize = cacheConfig.getMaxSize();
        connectionCache = CacheBuilder.newBuilder().maximumSize(cacheSize)
                .concurrencyLevel(cacheConfig.getConcurrencyLevel()).initialCapacity(cacheConfig.getInitialSize())
                .build(new CacheLoader<SoapJmsUri, Connection>() {
                    private AtomicInteger atomicInteger = new AtomicInteger(0);

                    @Override
                    public Connection load(SoapJmsUri soapJmsUri) throws NamingException, JMSException {
                        String lookupVariant = soapJmsUri.getLookupVariant();
                        JmsFactory jmsFactory = jmsPlugin.getJmsFactory();
                        Connection connection;

                        if (SoapJmsUri.JNDI_LOOKUP_VARIANT.equals(lookupVariant)) {
                            String jndiConnectionFactoryName = soapJmsUri.getParameter("jndiConnectionFactoryName");
                            if (StringUtils.isBlank(jndiConnectionFactoryName)) {
                                throw new IllegalArgumentException(
                                        "Missing jndiConnectionFactoryName parameter for JMS URI "
                                                + soapJmsUri.toString());
                            }

                            String connectionName = soapJmsUri.getConnectionName();
                            if (connectionName == null) {
                                connectionName = String.format(ANONYMOUS_CONNECTION_PATTERN,
                                        atomicInteger.getAndIncrement());
                            }

                            ConnectionDefinition connectionDefinition = jmsFactory.createConnectionDefinition(
                                    connectionName,
                                    soapJmsUri.getConfiguration(webServicesJmsConfig).jms().getConnection(),
                                    (ConnectionFactory) SoapJmsUri.getContext(soapJmsUri)
                                            .lookup(jndiConnectionFactoryName));

                            connection = jmsFactory.createConnection(connectionDefinition);
                            jmsPlugin.registerConnection(connection, connectionDefinition);
                        } else if (SoapJmsUri.SEED_QUEUE_LOOKUP_VARIANT.equals(lookupVariant)
                                || SoapJmsUri.SEED_TOPIC_LOOKUP_VARIANT.equals(lookupVariant)) {
                            String connectionName = soapJmsUri.getConnectionName();

                            if (StringUtils.isBlank(connectionName)) {
                                throw new IllegalArgumentException(
                                        "Missing connectionName parameter for JMS URI " + soapJmsUri.toString());
                            }

                            connection = jmsPlugin.getConnection(connectionName);
                        } else {
                            throw new IllegalArgumentException("Unsupported lookup variant " + lookupVariant
                                    + " for JMS URI " + soapJmsUri.toString());
                        }

                        if (connection == null) {
                            throw new PluginException(
                                    "Unable to resolve connection for JMS URI " + soapJmsUri.toString());
                        }

                        return connection;
                    }
                });

        for (Map.Entry<String, EndpointDefinition> endpointEntry : wsPlugin
                .getEndpointDefinitions(SUPPORTED_BINDINGS).entrySet()) {
            EndpointDefinition endpointDefinition = endpointEntry.getValue();
            String endpointName = endpointEntry.getKey();
            String serviceName = endpointDefinition.getServiceName().getLocalPart();
            String portName = endpointDefinition.getPortName().getLocalPart();
            String serviceNameAndServicePort = serviceName + "-" + portName;

            SoapJmsUri uri;
            try {
                uri = SoapJmsUri.parse(new URI(endpointDefinition.getUrl()));
                uri.setEndpointName(endpointName);
            } catch (URISyntaxException e) {
                throw new PluginException("Unable to parse endpoint URI", e);
            }

            WebServicesJmsConfig.JmsEndpointConfig endpointConfiguration = uri
                    .getConfiguration(webServicesJmsConfig);
            Connection connection;
            try {
                connection = connectionCache.get(uri);
            } catch (Exception e) {
                throw new PluginException("Unable to create JMS connection for WS " + serviceNameAndServicePort, e);
            }

            Session session;
            try {
                session = connection.createSession(endpointConfiguration.jms().isTransactional(),
                        Session.AUTO_ACKNOWLEDGE);
            } catch (JMSException e) {
                throw new PluginException("Unable to create JMS session for WS " + serviceNameAndServicePort, e);
            }

            Destination destination;
            try {
                destination = SoapJmsUri.getDestination(uri, session);
            } catch (Exception e) {
                throw new PluginException("Unable to create JMS destination for WS " + serviceNameAndServicePort,
                        e);
            }

            WSJmsMessageListener messageListener = new WSJmsMessageListener(uri,
                    new JmsAdapter(wsPlugin.createWSEndpoint(endpointDefinition, null)), session);

            String messageListenerName = String.format(LISTENER_NAME_PATTERN, endpointName);
            try {
                jmsPlugin.registerMessageListener(new MessageListenerInstanceDefinition(messageListenerName,
                        uri.getConnectionName(), session, destination, endpointConfiguration.jms().getSelector(),
                        messageListener, endpointConfiguration.jms().getMessagePoller()));
            } catch (Exception e) {
                throw SeedException.wrap(e, WSJmsErrorCodes.UNABLE_TO_REGISTER_MESSAGE_LISTENER)
                        .put("messageListenerName", messageListenerName);
            }
            wsJmsMessageListeners.add(messageListener);
        }

        return InitState.INITIALIZED;
    }

    @Override
    public Object nativeUnitModule() {
        return new WSJmsModule(wsJmsMessageListeners, connectionCache);
    }

    @Override
    public void stop() {
        if (connectionCache != null) {
            connectionCache.invalidateAll();
            connectionCache.cleanUp();
        }
    }
}