com.esri.geoevent.transport.websocket.WebsocketInboundTransport.java Source code

Java tutorial

Introduction

Here is the source code for com.esri.geoevent.transport.websocket.WebsocketInboundTransport.java

Source

/*
  Copyright 1995-2017 Esri
    
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
    
   http://www.apache.org/licenses/LICENSE-2.0
    
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
    
  For additional information, contact:
  Environmental Systems Research Institute, Inc.
  Attn: Contracts Dept
  380 New York Street
  Redlands, California, USA 92373
    
  email: contracts@esri.com
 */

package com.esri.geoevent.transport.websocket;

import java.net.ProtocolException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.utils.URIBuilder;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;

import com.esri.ges.core.component.ComponentException;
import com.esri.ges.core.component.RunningException;
import com.esri.ges.core.component.RunningState;
import com.esri.ges.core.property.Property;
import com.esri.ges.framework.i18n.BundleLogger;
import com.esri.ges.framework.i18n.BundleLoggerFactory;
import com.esri.ges.transport.InboundTransportBase;
import com.esri.ges.transport.TransportDefinition;

public class WebsocketInboundTransport extends InboundTransportBase {

    private static final BundleLogger LOGGER = BundleLoggerFactory.getLogger(WebsocketInboundTransport.class);
    private static final String URI_PROPERTY_NAME = "URI";

    private static final int DEFAULT_UNSECURE_PORT = 80;
    private static final int DEFAULT_SECURE_PORT = 443;

    // default is 10 minutes
    public static final int MAX_IDLE_TIME = 10 * 60 * 1000;

    public static final int MAX_TEXT_MESSAGE_SIZE = 10 * 1024;
    public static final int MAX_BINARY_MESSAGE_SIZE = 64 * 1024;

    private WebsocketInboundSocket socket;
    private URI uri;
    private ByteBuffer buffer = ByteBuffer.allocate(1024);
    private Charset charset;

    public WebsocketInboundTransport(TransportDefinition definition) throws ComponentException {
        super(definition);
        charset = StandardCharsets.UTF_8;
    }

    public void start() throws RunningException {
        switch (getRunningState()) {
        case STARTING:
        case STARTED:
            return;
        default:
        }

        setRunningState(RunningState.STARTING);
        Thread thread = new Thread() {
            @Override
            public void run() {
                setup();
            }
        };
        thread.start();
    }

    public synchronized void setup() {
        try {
            Property prop = getProperty(URI_PROPERTY_NAME);
            uri = getURI(prop.getValueAsString());
            socket = connect();
            setRunningState(RunningState.STARTED);
        } catch (ProtocolException error) {
            String errorMessage = LOGGER.translate("CANNOT_CONNECT", getProperty(URI_PROPERTY_NAME));
            LOGGER.error(errorMessage);
            LOGGER.info(error.getMessage(), error);
            setRunningState(RunningState.ERROR);
        } catch (Exception ex) {
            String errorMessage = LOGGER.translate("INIT_ERROR", ex.getMessage());
            LOGGER.error(errorMessage);
            LOGGER.info(ex.getMessage(), ex);
            setRunningState(RunningState.ERROR);
        }
    }

    private WebsocketInboundSocket connect() throws Exception {
        WebSocketClient wsc = null;

        String uriStr = uri.toString();
        if (uriStr.toLowerCase().startsWith("wss://")) {
            SslContextFactory sslContextFactory = new SslContextFactory();
            sslContextFactory.setTrustAll(true);
            wsc = new WebSocketClient(sslContextFactory);
        } else {
            wsc = new WebSocketClient();
        }

        wsc.setMaxIdleTimeout(MAX_IDLE_TIME);
        wsc.setMaxTextMessageBufferSize(MAX_TEXT_MESSAGE_SIZE);

        WebsocketInboundSocket ws = new WebsocketInboundSocket(this);

        try {
            wsc.start();
            ClientUpgradeRequest request = new ClientUpgradeRequest();
            Session session = wsc.connect(ws, uri, request).get();
            session.setIdleTimeout(MAX_IDLE_TIME);
        } catch (Throwable t) {
            LOGGER.error("WEBSOCKET_ERROR", t);
        }
        return ws;
    }

    public void reconnect() {
        setRunningState(RunningState.ERROR);
        while (getRunningState() != RunningState.STOPPING && getRunningState() != RunningState.STOPPED) {
            try {
                socket = connect();
                if (socket.isConnected()) {
                    setRunningState(RunningState.STARTED);
                    LOGGER.info("SOCKET_RECONNECTED");
                    return;
                }
            } catch (Exception ex) {
                LOGGER.debug("RECONNECT_ERROR", ex);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                }
            }
        }
    }

    private URI getURI(String uriString) throws URISyntaxException {
        // check the port - default to 80 for unsecure and 443 for secure connections
        URIBuilder uriBuilder = new URIBuilder(uriString);
        if (uriBuilder.getPort() == -1 || uriBuilder.getPort() == 0) {
            if (StringUtils.isNotEmpty(uriBuilder.getScheme())) {
                if (uriBuilder.getScheme().equalsIgnoreCase("wss")) {
                    uriBuilder.setPort(DEFAULT_SECURE_PORT);
                } else if (uriBuilder.getScheme().equalsIgnoreCase("ws")) {
                    uriBuilder.setPort(DEFAULT_UNSECURE_PORT);
                }
            }
        }
        return uriBuilder.build();
    }

    public void receive(String dataString) {
        buffer.clear();
        buffer = charset.encode(dataString);
        byteListener.receive(buffer, null);
    }

    public synchronized void stop() {
        if (getRunningState() == RunningState.STOPPING || getRunningState() == RunningState.STOPPED)
            return;
        setRunningState(RunningState.STOPPING);

        if (socket != null) {
            socket.close();
            socket = null;
        }
        setRunningState(RunningState.STOPPED);
    }

    @Override
    public boolean isClusterable() {
        return false;
    }
}