org.codehaus.stomp.tcp.TcpTransportServer.java Source code

Java tutorial

Introduction

Here is the source code for org.codehaus.stomp.tcp.TcpTransportServer.java

Source

/**
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.codehaus.stomp.tcp;

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.jms.JMSException;
import javax.net.ServerSocketFactory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.stomp.jms.StompConnect;

/**
 * @version $Revision: 52 $
 */
public class TcpTransportServer implements Runnable {
    private static final Log log = LogFactory.getLog(TcpTransportServer.class);
    private StompConnect stompHandlerFactory;
    private ServerSocket serverSocket;
    private int backlog = 5000;
    private ServerSocketFactory serverSocketFactory;
    private boolean daemon = true;
    private Thread runner;
    private URI connectURI;
    private URI bindLocation;
    private List<TcpTransport> connections = new CopyOnWriteArrayList<TcpTransport>();
    private AtomicBoolean stopped = new AtomicBoolean(false);

    public TcpTransportServer(StompConnect stompHandlerFactory, URI location,
            ServerSocketFactory serverSocketFactory) throws IOException, URISyntaxException {
        this.stompHandlerFactory = stompHandlerFactory;
        this.connectURI = location;
        this.bindLocation = location;
        this.serverSocketFactory = serverSocketFactory;
    }

    /**
     * @return pretty print of this
     */
    public String toString() {
        return bindLocation.toString();
    }

    /**
     * pull Sockets from the ServerSocket
     */
    public void run() {
        while (!stopped.get()) {
            Socket socket = null;
            try {
                socket = serverSocket.accept();
                if (socket != null) {
                    if (stopped.get()) {
                        socket.close();
                    } else {
                        TcpTransport transport = new TcpTransport(socket);
                        stompHandlerFactory.assignProtocolConverter(transport);
                        transport.start();
                        connections.add(transport);
                    }
                }
            } catch (SocketTimeoutException ste) {
                // expect this to happen
            } catch (Exception e) {
                if (!stopped.get()) {
                    log.error("Received accept error: " + e, e);
                    try {
                        stop();
                    } catch (Exception e1) {
                        log.error("Failed to shut down: " + e, e);
                    }
                }
            }
        }
    }

    public void start() throws IOException {
        URI bind = bindLocation;

        String host = bind.getHost();
        host = (host == null || host.length() == 0) ? "localhost" : host;
        InetAddress addr = InetAddress.getByName(host);

        try {
            this.serverSocket = serverSocketFactory.createServerSocket(bind.getPort(), backlog, addr);
            this.serverSocket.setSoTimeout(2000);
        } catch (IOException e) {
            throw new IOException("Failed to bind to server socket: " + bind + " due to: " + e, e);
        }
        try {
            connectURI = new URI(bind.getScheme(), bind.getUserInfo(), bind.getHost(), serverSocket.getLocalPort(),
                    bind.getPath(), bind.getQuery(), bind.getFragment());
        } catch (URISyntaxException e) {
            throw new IOException(e.getMessage(), e);
        }

        log.info("Listening for connections at: " + connectURI);
        runner = new Thread(this, "StompConnect Server Thread: " + toString());
        runner.setDaemon(daemon);
        runner.start();
    }

    public void stop() throws InterruptedException, IOException, JMSException, URISyntaxException {
        stopped.set(true);

        // lets stop accepting new connections first
        if (serverSocket != null) {
            serverSocket.close();
        }

        // now lets close all the connections
        try {
            for (TcpTransport connection : connections) {
                connection.stop();
            }
        } finally {
            connections.clear();
        }

        // lets join the server thread in case its blocked a little while
        if (runner != null) {
            log.debug("Attempting to join with runner");
            runner.join();
            log.debug("Joined with runner");
            runner = null;
        }
    }
}