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

io.engineblock.activities.tcpserver.TCPServerActivity Maven / Gradle / Ivy

Go to download

A engineblock ActivityType (AT) driver module; Provides a diagnostic activity that logs input at some interval

There is a newer version: 2.11.04
Show newest version
/*
 *
 *    Copyright 2016 jshook
 *    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.
 * /
 */

package io.engineblock.activities.tcpserver;

import io.engineblock.activities.stdout.StdoutActivity;
import io.engineblock.activityimpl.ActivityDef;
import io.engineblock.util.SSLKsFactory;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ServerSocketFactory;
import javax.net.ssl.SSLServerSocketFactory;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;


public class TCPServerActivity extends StdoutActivity {

    private final static Logger logger = LoggerFactory.getLogger(TCPServerActivity.class);
    private final ServerSocketFactory socketFactory;
    private BlockingQueue queue = new LinkedBlockingQueue<>(10);
    private ServerSocket listenerSocket;
    private List managedShutdown = new ArrayList<>();


    public TCPServerActivity(ActivityDef activityDef) {
        super(activityDef);
        boolean sslEnabled = activityDef.getParams().getOptionalBoolean("ssl").orElse(false);

        if (sslEnabled) {
            socketFactory = SSLKsFactory.get().createSSLServerSocketFactory(activityDef);
        } else {
            socketFactory = ServerSocketFactory.getDefault();
        }
    }

    @Override
    public void onActivityDefUpdate(ActivityDef activityDef) {
        super.onActivityDefUpdate(activityDef);

    }

    @Override
    public void shutdownActivity() {
        super.shutdownActivity();
        for (Shutdown toClose : managedShutdown) {
            toClose.shutdown();
        }
    }

    @Override
    public synchronized void write(String statement) {
        while (true) {
            try {
                queue.put(statement);
                return;
            } catch (InterruptedException ignored) {
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }

    @Override
    protected synchronized Writer createPrintWriter() {

        String host = getActivityDef().getParams().getOptionalString("host").orElse("localhost");
        int port = getActivityDef().getParams().getOptionalInteger("port").orElse(12345);

        if (listenerSocket == null || listenerSocket.isClosed()) {
            try {
                InetAddress hostAddr = InetAddress.getByName(host);
                listenerSocket = socketFactory.createServerSocket(port, 10, hostAddr);
                if (socketFactory instanceof SSLServerSocketFactory) {
                    logger.info("SSL enabled on server socket " + listenerSocket);
                }
                SocketAcceptor socketAcceptor = new SocketAcceptor(queue, listenerSocket);
                managedShutdown.add(socketAcceptor);
                Thread acceptorThread = new Thread(socketAcceptor);
                acceptorThread.setDaemon(true);
                acceptorThread.setName("Listener/" + listenerSocket);
                acceptorThread.start();
            } catch (IOException e) {
                throw new RuntimeException("Error listening on listenerSocket:" + e, e);
            }
        }

        QueueWriterAdapter queueWriterAdapter = new QueueWriterAdapter(this.queue);
        logger.info("initialized queue writer:" + queueWriterAdapter);
        return queueWriterAdapter;

    }

    private static interface Shutdown {
        void shutdown();
    }

    public static class SocketWriter implements Runnable, Shutdown {
        private final BlockingQueue sourceQueue;
        private final OutputStream outputStream;
        private final OutputStreamWriter writer;
        private boolean running = true;


        public SocketWriter(BlockingQueue sourceQueue, Socket connectedSocket) {
            this.sourceQueue = sourceQueue;
            try {
                outputStream = connectedSocket.getOutputStream();
                this.writer = new OutputStreamWriter(outputStream);
                //connectedSocket.shutdownInput();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        public void shutdown() {
            this.running = false;
        }

        @Override
        public void run() {
            try (Writer writer = this.writer) {
                while (true) {
                    while (!sourceQueue.isEmpty() || running) {
                        try {
                            String data = sourceQueue.take();
                            writer.write(data);
                            writer.flush();
                        } catch (Exception e) {
                            throw new RuntimeException(e);
                        }
                    }
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException ignored) {
                    }
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

        }

    }

    public static class QueueWriterAdapter extends Writer {
        private BlockingQueue queue;

        public QueueWriterAdapter(BlockingQueue queue) {
            this.queue = queue;
        }

        @Override
        public synchronized void write(@NotNull char[] cbuf, int off, int len) {
            while (true) {
                try {
                    queue.put(new String(cbuf, off, len));
                    return;
                } catch (InterruptedException ignored) {
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }

        @Override
        public synchronized void flush() throws IOException {
        }

        @Override
        public synchronized void close() throws IOException {
            flush();
            queue = null;
        }

    }

    public class SocketAcceptor implements Runnable, Shutdown {
        private final BlockingQueue queue;
        private final ServerSocket serverSocket;
        private boolean running = true;

        public SocketAcceptor(BlockingQueue queue, ServerSocket serverSocket) {
            this.queue = queue;
            this.serverSocket = serverSocket;
        }

        public void shutdown() {
            this.running = false;
        }

        @Override
        public void run() {
            try (ServerSocket serverSocket = this.serverSocket) {
                while (running) {
                    serverSocket.setSoTimeout(1000);
                    serverSocket.setReuseAddress(true);
                    try {
                        Socket connectedSocket = serverSocket.accept();
                        SocketWriter writer = new SocketWriter(queue, connectedSocket);
                        TCPServerActivity.this.managedShutdown.add(writer);
                        Thread writerThread = new Thread(writer);
                        writerThread.setName("SocketWriter/" + connectedSocket);
                        writerThread.setDaemon(true);
                        writerThread.start();
                        logger.info("Started writer thread for " + connectedSocket);
                    } catch (SocketTimeoutException ignored) {
                    }
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }


}






© 2015 - 2025 Weber Informatics LLC | Privacy Policy