All Downloads are FREE. Search and download functionalities are using the official Maven repository.

quickfix.mina.initiator.AbstractSocketInitiator Maven / Gradle / Ivy

/*******************************************************************************
 * Copyright (c) quickfixengine.org  All rights reserved.
 *
 * This file is part of the QuickFIX FIX Engine
 *
 * This file may be distributed under the terms of the quickfixengine.org
 * license as defined by quickfixengine.org and appearing in the file
 * LICENSE included in the packaging of this file.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE.
 *
 * See http://www.quickfixengine.org/LICENSE for licensing information.
 *
 * Contact [email protected] if any conditions of this licensing
 * are not clear to you.
 ******************************************************************************/

package quickfix.mina.initiator;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.buffer.SimpleBufferAllocator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import quickfix.Application;
import quickfix.ConfigError;
import quickfix.DefaultSessionFactory;
import quickfix.FieldConvertError;
import quickfix.Initiator;
import quickfix.LogFactory;
import quickfix.MessageFactory;
import quickfix.MessageStoreFactory;
import quickfix.Session;
import quickfix.SessionFactory;
import quickfix.SessionID;
import quickfix.SessionSettings;
import quickfix.field.converter.BooleanConverter;
import quickfix.mina.EventHandlingStrategy;
import quickfix.mina.NetworkingOptions;
import quickfix.mina.ProtocolFactory;
import quickfix.mina.SessionConnector;
import quickfix.mina.ssl.SSLConfig;
import quickfix.mina.ssl.SSLSupport;

import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * Abstract base class for socket initiators.
 */
public abstract class AbstractSocketInitiator extends SessionConnector implements Initiator {

    protected final Logger log = LoggerFactory.getLogger(getClass());
    private final Set initiators = new HashSet<>();

    protected AbstractSocketInitiator(Application application,
            MessageStoreFactory messageStoreFactory, SessionSettings settings,
            LogFactory logFactory, MessageFactory messageFactory) throws ConfigError {
        this(settings, new DefaultSessionFactory(application, messageStoreFactory, logFactory,
                messageFactory));
    }

    protected AbstractSocketInitiator(SessionSettings settings, SessionFactory sessionFactory)
            throws ConfigError {
        super(settings, sessionFactory);
        IoBuffer.setAllocator(new SimpleBufferAllocator());
        IoBuffer.setUseDirectBuffer(false);
    }

    protected void createSessionInitiators()
            throws ConfigError {
        try {
            // QFJ698: clear() is needed on restart, otherwise the set gets filled up with
            // more and more initiators which are not equal because the local port differs
            initiators.clear();
            createSessions();
            SessionSettings settings = getSettings();
            for (final Session session : getSessionMap().values()) {
                final SessionID sessionID = session.getSessionID();
                final int[] reconnectingIntervals = getReconnectIntervalInSeconds(sessionID);

                final SocketAddress[] socketAddresses = getSocketAddresses(sessionID);
                if (socketAddresses.length == 0) {
                    throw new ConfigError("Must specify at least one socket address");
                }

                SocketAddress localAddress = getLocalAddress(settings, sessionID);

                final NetworkingOptions networkingOptions = new NetworkingOptions(getSettings()
                        .getSessionProperties(sessionID, true));

                boolean sslEnabled = false;
                SSLConfig sslConfig = null;
                if (getSettings().isSetting(sessionID, SSLSupport.SETTING_USE_SSL)
                        && BooleanConverter.convert(getSettings().getString(sessionID, SSLSupport.SETTING_USE_SSL))) {
                    sslEnabled = true;
                    sslConfig = SSLSupport.getSslConfig(getSettings(), sessionID);
                }

                String proxyUser = null;
                String proxyPassword = null;
                String proxyHost = null;

                String proxyType = null;
                String proxyVersion = null;

                String proxyWorkstation = null;
                String proxyDomain = null;

                int proxyPort = -1;

                if (getSettings().isSetting(sessionID, Initiator.SETTING_PROXY_TYPE)) {
                    proxyType = settings.getString(sessionID, Initiator.SETTING_PROXY_TYPE);
                    if (getSettings().isSetting(sessionID, Initiator.SETTING_PROXY_VERSION)) {
                        proxyVersion = settings.getString(sessionID,
                                                          Initiator.SETTING_PROXY_VERSION);
                    }

                    if (getSettings().isSetting(sessionID, Initiator.SETTING_PROXY_USER)) {
                        proxyUser = settings.getString(sessionID, Initiator.SETTING_PROXY_USER);
                        proxyPassword = settings.getString(sessionID,
                                                           Initiator.SETTING_PROXY_PASSWORD);
                    }
                    if (getSettings().isSetting(sessionID, Initiator.SETTING_PROXY_WORKSTATION)
                            && getSettings().isSetting(sessionID, Initiator.SETTING_PROXY_DOMAIN)) {
                        proxyWorkstation = settings.getString(sessionID,
                                                              Initiator.SETTING_PROXY_WORKSTATION);
                        proxyDomain = settings.getString(sessionID, Initiator.SETTING_PROXY_DOMAIN);
                    }

                    proxyHost = settings.getString(sessionID, Initiator.SETTING_PROXY_HOST);
                    proxyPort = (int) settings.getLong(sessionID, Initiator.SETTING_PROXY_PORT);
                }

                final IoSessionInitiator ioSessionInitiator = new IoSessionInitiator(session,
                        socketAddresses, localAddress, reconnectingIntervals,
                        getScheduledExecutorService(), networkingOptions,
                        getEventHandlingStrategy(), getIoFilterChainBuilder(), sslEnabled, sslConfig,
                        proxyType, proxyVersion, proxyHost, proxyPort, proxyUser, proxyPassword, proxyDomain, proxyWorkstation);

                initiators.add(ioSessionInitiator);
            }
        } catch (final FieldConvertError e) {
            throw new ConfigError(e);
        }
    }

    // QFJ-482
    private SocketAddress getLocalAddress(SessionSettings settings, final SessionID sessionID)
            throws ConfigError, FieldConvertError {
        // Check if use of socket local/bind address
        SocketAddress localAddress = null;
        if (settings.isSetting(sessionID, Initiator.SETTING_SOCKET_LOCAL_HOST)) {
            String host = settings.getString(sessionID, Initiator.SETTING_SOCKET_LOCAL_HOST);
            if ("localhost".equals(host)) {
                throw new ConfigError(Initiator.SETTING_SOCKET_LOCAL_HOST + " cannot be \"localhost\"!");
            }
            int port = 0;
            if (settings.isSetting(sessionID, Initiator.SETTING_SOCKET_LOCAL_PORT)) {
                port = (int) settings.getLong(sessionID, Initiator.SETTING_SOCKET_LOCAL_PORT);
            }
            localAddress = ProtocolFactory.createSocketAddress(ProtocolFactory.SOCKET, host, port);
            if (log.isInfoEnabled()) {
                log.info("Using initiator local host: " + localAddress);
            }
        }
        return localAddress;
    }

    private void createSessions() throws ConfigError, FieldConvertError {
        final SessionSettings settings = getSettings();
        boolean continueInitOnError = false;
        if (settings.isSetting(SessionFactory.SETTING_CONTINUE_INIT_ON_ERROR)) {
            continueInitOnError = settings.getBool(SessionFactory.SETTING_CONTINUE_INIT_ON_ERROR);
        }

        final Map initiatorSessions = new HashMap<>();
        for (final Iterator i = settings.sectionIterator(); i.hasNext();) {
            final SessionID sessionID = i.next();
            if (isInitiatorSession(sessionID)) {
                try {
                    final Session quickfixSession = createSession(sessionID);
                    initiatorSessions.put(sessionID, quickfixSession);
                } catch (final Throwable e) {
                    if (continueInitOnError) {
                        log.error("error during session initialization, continuing...", e);
                    } else {
                        throw e instanceof ConfigError ? (ConfigError) e : new ConfigError(
                                "error during session initialization", e);
                    }
                }
            }
        }
        if (initiatorSessions.isEmpty()) {
            throw new ConfigError("no initiators in settings");
        }
        setSessions(initiatorSessions);
    }

    private int[] getReconnectIntervalInSeconds(SessionID sessionID) throws ConfigError {
        final SessionSettings settings = getSettings();
        if (settings.isSetting(sessionID, Initiator.SETTING_RECONNECT_INTERVAL)) {
            try {
                final String raw = settings.getString(sessionID,
                        Initiator.SETTING_RECONNECT_INTERVAL);
                final int[] ret = SessionSettings.parseSettingReconnectInterval(raw);
                if (ret != null) {
                    return ret;
                }
            } catch (final Throwable e) {
                throw new ConfigError(e);
            }
        }
        return new int[] { 30 };
    }

    private SocketAddress[] getSocketAddresses(SessionID sessionID) throws ConfigError {
        final SessionSettings settings = getSettings();
        final ArrayList addresses = new ArrayList<>();
        for (int index = 0;; index++) {
            try {
                final String protocolKey = Initiator.SETTING_SOCKET_CONNECT_PROTOCOL
                        + (index == 0 ? "" : Integer.toString(index));
                final String hostKey = Initiator.SETTING_SOCKET_CONNECT_HOST
                        + (index == 0 ? "" : Integer.toString(index));
                final String portKey = Initiator.SETTING_SOCKET_CONNECT_PORT
                        + (index == 0 ? "" : Integer.toString(index));
                int transportType = ProtocolFactory.SOCKET;
                if (settings.isSetting(sessionID, protocolKey)) {
                    try {
                        transportType = ProtocolFactory.getTransportType(settings.getString(sessionID, protocolKey));
                    } catch (final IllegalArgumentException e) {
                        // Unknown transport type
                        throw new ConfigError(e);
                    }
                }
                if (settings.isSetting(sessionID, portKey)) {
                    String host;
                    if (!isHostRequired(transportType)) {
                        host = "localhost";
                    } else {
                        host = settings.getString(sessionID, hostKey);
                    }
                    final int port = (int) settings.getLong(sessionID, portKey);
                    addresses.add(ProtocolFactory.createSocketAddress(transportType, host, port));
                } else {
                    break;
                }
            } catch (final FieldConvertError e) {
                throw (ConfigError) new ConfigError(e.getMessage()).initCause(e);
            }
        }

        return addresses.toArray(new SocketAddress[addresses.size()]);
    }

    private boolean isHostRequired(int transportType) {
        return transportType != ProtocolFactory.VM_PIPE;
    }

    private boolean isInitiatorSession(Object sectionKey) throws ConfigError, FieldConvertError {
        final SessionSettings settings = getSettings();
        return !settings.isSetting((SessionID) sectionKey, SessionFactory.SETTING_CONNECTION_TYPE)
                || settings.getString((SessionID) sectionKey,
                        SessionFactory.SETTING_CONNECTION_TYPE).equals("initiator");
    }

    protected void startInitiators() {
        startSessionTimer();
        for (final IoSessionInitiator initiator : initiators) {
            initiator.start();
        }
    }

    protected void stopInitiators() {
        for (final IoSessionInitiator initiator : initiators) {
            initiator.stop();
        }
        super.stopSessionTimer();
    }

    public Set getInitiators() {
        return Collections.unmodifiableSet(initiators);
    }

    public int getQueueSize() {
        final EventHandlingStrategy ehs = getEventHandlingStrategy();
        return ehs == null ? 0 : ehs.getQueueSize();
    }

    protected abstract EventHandlingStrategy getEventHandlingStrategy();
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy