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

ch.qos.logback.classic.net.SimpleSocketServer Maven / Gradle / Ivy

/**
 * Logback: the reliable, generic, fast and flexible logging framework.
 * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
 *
 * This program and the accompanying materials are dual-licensed under
 * either the terms of the Eclipse Public License v1.0 as published by
 * the Eclipse Foundation
 *
 *   or (per the licensee's choosing)
 *
 * under the terms of the GNU Lesser General Public License version 2.1
 * as published by the Free Software Foundation.
 */
package ch.qos.logback.classic.net;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

import javax.net.ServerSocketFactory;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;

/**
 * A simple {@link SocketNode} based server.
 * 
 * 
 *      <b>Usage:</b> java ch.qos.logback.classic.net.SimpleSocketServer port configFile
 * 
* * where port is a port number where the server listens and * configFile is an xml configuration file fed to * {@link JoranConfigurator}. * *
* * @author Ceki Gülcü * @author Sébastien Pennec * * @since 0.8.4 */ public class SimpleSocketServer extends Thread { Logger logger = LoggerFactory.getLogger(SimpleSocketServer.class); private final int port; private final LoggerContext lc; private boolean closed = false; private ServerSocket serverSocket; private List socketNodeList = new ArrayList(); // used for testing purposes private CountDownLatch latch; public static void main(String argv[]) throws Exception { doMain(SimpleSocketServer.class, argv); } protected static void doMain(Class serverClass, String argv[]) throws Exception { int port = -1; if (argv.length == 2) { port = parsePortNumber(argv[0]); } else { usage("Wrong number of arguments."); } String configFile = argv[1]; LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); configureLC(lc, configFile); SimpleSocketServer sss = new SimpleSocketServer(lc, port); sss.start(); } public SimpleSocketServer(LoggerContext lc, int port) { this.lc = lc; this.port = port; } public void run() { final String oldThreadName = Thread.currentThread().getName(); try { final String newThreadName = getServerThreadName(); Thread.currentThread().setName(newThreadName); logger.info("Listening on port " + port); serverSocket = getServerSocketFactory().createServerSocket(port); while (!closed) { logger.info("Waiting to accept a new client."); signalAlmostReadiness(); Socket socket = serverSocket.accept(); logger.info("Connected to client at " + socket.getInetAddress()); logger.info("Starting new socket node."); SocketNode newSocketNode = new SocketNode(this, socket, lc); synchronized (socketNodeList) { socketNodeList.add(newSocketNode); } final String clientThreadName = getClientThreadName(socket); new Thread(newSocketNode, clientThreadName).start(); } } catch (Exception e) { if (closed) { logger.info("Exception in run method for a closed server. This is normal."); } else { logger.error("Unexpected failure in run method", e); } } finally { Thread.currentThread().setName(oldThreadName); } } /** * Returns the name given to the server thread. */ protected String getServerThreadName() { return String.format("Logback %s (port %d)", getClass().getSimpleName(), port); } /** * Returns a name to identify each client thread. */ protected String getClientThreadName(Socket socket) { return String.format("Logback SocketNode (client: %s)", socket.getRemoteSocketAddress()); } /** * Gets the platform default {@link ServerSocketFactory}. *

* Subclasses may override to provide a custom server socket factory. */ protected ServerSocketFactory getServerSocketFactory() { return ServerSocketFactory.getDefault(); } /** * Signal another thread that we have established a connection * This is useful for testing purposes. */ void signalAlmostReadiness() { if (latch != null && latch.getCount() != 0) { // System.out.println("signalAlmostReadiness() with latch "+latch); latch.countDown(); } } /** * Used for testing purposes * @param latch */ void setLatch(CountDownLatch latch) { this.latch = latch; } /** * Used for testing purposes */ public CountDownLatch getLatch() { return latch; } public boolean isClosed() { return closed; } public void close() { closed = true; if (serverSocket != null) { try { serverSocket.close(); } catch (IOException e) { logger.error("Failed to close serverSocket", e); } finally { serverSocket = null; } } logger.info("closing this server"); synchronized (socketNodeList) { for (SocketNode sn : socketNodeList) { sn.close(); } } if (socketNodeList.size() != 0) { logger.warn("Was expecting a 0-sized socketNodeList after server shutdown"); } } public void socketNodeClosing(SocketNode sn) { logger.debug("Removing {}", sn); // don't allow simultaneous access to the socketNodeList // (e.g. removal whole iterating on the list causes // java.util.ConcurrentModificationException synchronized (socketNodeList) { socketNodeList.remove(sn); } } static void usage(String msg) { System.err.println(msg); System.err.println("Usage: java " + SimpleSocketServer.class.getName() + " port configFile"); System.exit(1); } static int parsePortNumber(String portStr) { try { return Integer.parseInt(portStr); } catch (java.lang.NumberFormatException e) { e.printStackTrace(); usage("Could not interpret port number [" + portStr + "]."); // we won't get here return -1; } } static public void configureLC(LoggerContext lc, String configFile) throws JoranException { JoranConfigurator configurator = new JoranConfigurator(); lc.reset(); configurator.setContext(lc); configurator.doConfigure(configFile); } }



© 2015 - 2024 Weber Informatics LLC | Privacy Policy