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
* 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);
}
}