What this is
This file is included in the DevDaily.com
"Java Source Code
Warehouse" project. The intent of this project is to help you "Learn
Java by Example" TM.
Other links
The source code
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software
* License version 1.1, a copy of which has been included with this
* distribution in the LICENSE.txt file. */
package org.apache.log4j.net;
import java.net.Socket;
import java.net.ServerSocket;
import java.net.InetAddress;
import java.io.File;
import java.util.Hashtable;
import org.apache.log4j.*;
import org.apache.log4j.spi.*;
/**
A {@link SocketNode} based server that uses a different hierarchy
for each client.
Usage: java org.apache.log4j.net.SocketServer port configFile configDir
where port is a part number where the server listens,
configFile is a configuration file fed to the {@link PropertyConfigurator} and
configDir is a path to a directory containing configuration files, possibly one for each client host.
The configFile is used to configure the log4j
default hierarchy that the SocketServer will use to
report on its actions.
When a new connection is opened from a previously unknown
host, say foo.bar.net , then the
SocketServer will search for a configuration file
called foo.bar.net.lcf under the directory
configDir that was passed as the third argument. If
the file can be found, then a new hierarchy is instantiated and
configured using the configuration file
foo.bar.net.lcf . If and when the host
foo.bar.net opens another connection to the server,
then the previously configured hierarchy is used.
In case there is no file called foo.bar.net.lcf
under the directory configDir , then the
generic hierarchy is used. The generic hierarchy is
configured using a configuration file called
generic.lcf under the configDir
directory. If no such file exists, then the generic hierarchy will be
identical to the log4j default hierarchy.
Having different client hosts log using different hierarchies
ensures the total independence of the clients with respect to
their logging settings.
Currently, the hierarchy that will be used for a given request
depends on the IP address of the client host. For example, two
separate applicatons running on the same host and logging to the
same server will share the same hierarchy. This is perfectly safe
except that it might not provide the right amount of independence
between applications. The SocketServer is intended
as an example to be enhanced in order to implement more elaborate
policies.
@author Ceki Gülcü
@since 1.0 */
public class SocketServer {
static String GENERIC = "generic";
static String CONFIG_FILE_EXT = ".lcf";
static Category cat = Category.getInstance(SocketServer.class);
static SocketServer server;
static int port;
// key=inetAddress, value=hierarchy
Hashtable hierarchyMap;
LoggerRepository genericHierarchy;
File dir;
public
static
void main(String argv[]) {
if(argv.length == 3)
init(argv[0], argv[1], argv[2]);
else
usage("Wrong number of arguments.");
try {
cat.info("Listening on port " + port);
ServerSocket serverSocket = new ServerSocket(port);
while(true) {
cat.info("Waiting to accept a new client.");
Socket socket = serverSocket.accept();
InetAddress inetAddress = socket.getInetAddress();
cat.info("Connected to client at " + inetAddress);
LoggerRepository h = (LoggerRepository) server.hierarchyMap.get(inetAddress);
if(h == null) {
h = server.configureHierarchy(inetAddress);
}
cat.info("Starting new socket node.");
new Thread(new SocketNode(socket, h)).start();
}
}
catch(Exception e) {
e.printStackTrace();
}
}
static
void usage(String msg) {
System.err.println(msg);
System.err.println(
"Usage: java " +SocketServer.class.getName() + " port configFile directory");
System.exit(1);
}
static
void init(String portStr, String configFile, String dirStr) {
try {
port = Integer.parseInt(portStr);
}
catch(java.lang.NumberFormatException e) {
e.printStackTrace();
usage("Could not interpret port number ["+ portStr +"].");
}
PropertyConfigurator.configure(configFile);
File dir = new File(dirStr);
if(!dir.isDirectory()) {
usage("["+dirStr+"] is not a directory.");
}
server = new SocketServer(dir);
}
public
SocketServer(File directory) {
this.dir = directory;
hierarchyMap = new Hashtable(11);
}
// This method assumes that there is no hiearchy for inetAddress
// yet. It will configure one and return it.
LoggerRepository configureHierarchy(InetAddress inetAddress) {
cat.info("Locating configuration file for "+inetAddress);
// We assume that the toSting method of InetAddress returns is in
// the format hostname/d1.d2.d3.d4 e.g. torino/192.168.1.1
String s = inetAddress.toString();
int i = s.indexOf("/");
if(i == -1) {
cat.warn("Could not parse the inetAddress ["+inetAddress+
"]. Using default hierarchy.");
return genericHierarchy();
} else {
String key = s.substring(0, i);
File configFile = new File(dir, key+CONFIG_FILE_EXT);
if(configFile.exists()) {
Hierarchy h = new Hierarchy(new RootCategory((Level) Priority.DEBUG));
hierarchyMap.put(inetAddress, h);
new PropertyConfigurator().doConfigure(configFile.getAbsolutePath(), h);
return h;
} else {
cat.warn("Could not find config file ["+configFile+"].");
return genericHierarchy();
}
}
}
LoggerRepository genericHierarchy() {
if(genericHierarchy == null) {
File f = new File(dir, GENERIC+CONFIG_FILE_EXT);
if(f.exists()) {
genericHierarchy = new Hierarchy(new RootCategory((Level) Priority.DEBUG));
new PropertyConfigurator().doConfigure(f.getAbsolutePath(), genericHierarchy);
} else {
cat.warn("Could not find config file ["+f+
"]. Will use the default hierarchy.");
genericHierarchy = LogManager.getLoggerRepository();
}
}
return genericHierarchy;
}
}
|