JAL-3032 adds Java 8 functionality (1/2)
[jalview.git] / srcjar2 / org / apache / log4j / net / SocketServer.java
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  * 
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  * 
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 package org.apache.log4j.net;
19
20 import java.io.File;
21 import java.net.InetAddress;
22 import java.net.ServerSocket;
23 import java.net.Socket;
24 import java.util.Hashtable;
25
26 import org.apache.log4j.Hierarchy;
27 import org.apache.log4j.Level;
28 import org.apache.log4j.LogManager;
29 import org.apache.log4j.Logger;
30 import org.apache.log4j.PropertyConfigurator;
31 import org.apache.log4j.spi.LoggerRepository;
32 import org.apache.log4j.spi.RootLogger;
33
34
35 /**
36    A {@link SocketNode} based server that uses a different hierarchy
37    for each client.
38
39    <pre>
40      <b>Usage:</b> java org.apache.log4j.net.SocketServer port configFile configDir
41
42      where <b>port</b> is a part number where the server listens,
43            <b>configFile</b> is a configuration file fed to the {@link PropertyConfigurator} and
44            <b>configDir</b> is a path to a directory containing configuration files, possibly one for each client host.
45      </pre>
46
47      <p>The <code>configFile</code> is used to configure the log4j
48      default hierarchy that the <code>SocketServer</code> will use to
49      report on its actions.
50
51      <p>When a new connection is opened from a previously unknown
52      host, say <code>foo.bar.net</code>, then the
53      <code>SocketServer</code> will search for a configuration file
54      called <code>foo.bar.net.lcf</code> under the directory
55      <code>configDir</code> that was passed as the third argument. If
56      the file can be found, then a new hierarchy is instantiated and
57      configured using the configuration file
58      <code>foo.bar.net.lcf</code>. If and when the host
59      <code>foo.bar.net</code> opens another connection to the server,
60      then the previously configured hierarchy is used.
61
62      <p>In case there is no file called <code>foo.bar.net.lcf</code>
63      under the directory <code>configDir</code>, then the
64      <em>generic</em> hierarchy is used. The generic hierarchy is
65      configured using a configuration file called
66      <code>generic.lcf</code> under the <code>configDir</code>
67      directory. If no such file exists, then the generic hierarchy will be
68      identical to the log4j default hierarchy.
69
70      <p>Having different client hosts log using different hierarchies
71      ensures the total independence of the clients with respect to
72      their logging settings.
73
74      <p>Currently, the hierarchy that will be used for a given request
75      depends on the IP address of the client host. For example, two
76      separate applications running on the same host and logging to the
77      same server will share the same hierarchy. This is perfectly safe
78      except that it might not provide the right amount of independence
79      between applications. The <code>SocketServer</code> is intended
80      as an example to be enhanced in order to implement more elaborate
81      policies.
82
83
84     @author  Ceki G&uuml;lc&uuml;
85
86     @since 1.0 */
87
88 public class SocketServer  {
89
90   static String GENERIC = "generic";
91   static String CONFIG_FILE_EXT = ".lcf";
92
93   static Logger cat = Logger.getLogger(SocketServer.class);
94   static SocketServer server;
95   static int port;
96
97   // key=inetAddress, value=hierarchy
98   Hashtable hierarchyMap;
99   LoggerRepository genericHierarchy;
100   File dir;
101
102   public
103   static
104   void main(String argv[]) {
105     if(argv.length == 3) {
106         init(argv[0], argv[1], argv[2]);
107     } else {
108         usage("Wrong number of arguments.");
109     }
110
111     try {
112       cat.info("Listening on port " + port);
113       ServerSocket serverSocket = new ServerSocket(port);
114       while(true) {
115         cat.info("Waiting to accept a new client.");
116         Socket socket = serverSocket.accept();
117         InetAddress inetAddress =  socket.getInetAddress();
118         cat.info("Connected to client at " + inetAddress);
119
120         LoggerRepository h = (LoggerRepository) server.hierarchyMap.get(inetAddress);
121         if(h == null) {
122           h = server.configureHierarchy(inetAddress);
123         }
124
125         cat.info("Starting new socket node.");
126         new Thread(new SocketNode(socket, h)).start();
127       }
128     }
129     catch(Exception e) {
130       e.printStackTrace();
131     }
132   }
133
134
135   static
136   void  usage(String msg) {
137     System.err.println(msg);
138     System.err.println(
139       "Usage: java " +SocketServer.class.getName() + " port configFile directory");
140     System.exit(1);
141   }
142
143   static
144   void init(String portStr, String configFile, String dirStr) {
145     try {
146       port = Integer.parseInt(portStr);
147     }
148     catch(java.lang.NumberFormatException e) {
149       e.printStackTrace();
150       usage("Could not interpret port number ["+ portStr +"].");
151     }
152
153     PropertyConfigurator.configure(configFile);
154
155     File dir = new File(dirStr);
156     if(!dir.isDirectory()) {
157       usage("["+dirStr+"] is not a directory.");
158     }
159     server = new SocketServer(dir);
160   }
161
162
163   public
164   SocketServer(File directory) {
165     this.dir = directory;
166     hierarchyMap = new Hashtable(11);
167   }
168
169   // This method assumes that there is no hiearchy for inetAddress
170   // yet. It will configure one and return it.
171   LoggerRepository configureHierarchy(InetAddress inetAddress) {
172     cat.info("Locating configuration file for "+inetAddress);
173     // We assume that the toSting method of InetAddress returns is in
174     // the format hostname/d1.d2.d3.d4 e.g. torino/192.168.1.1
175     String s = inetAddress.toString();
176     int i = s.indexOf("/");
177     if(i == -1) {
178       cat.warn("Could not parse the inetAddress ["+inetAddress+
179                "]. Using default hierarchy.");
180       return genericHierarchy();
181     } else {
182       String key = s.substring(0, i);
183
184       File configFile = new File(dir, key+CONFIG_FILE_EXT);
185       if(configFile.exists()) {
186         Hierarchy h = new Hierarchy(new RootLogger(Level.DEBUG));
187         hierarchyMap.put(inetAddress, h);
188
189         new PropertyConfigurator().doConfigure(configFile.getAbsolutePath(), h);
190
191         return h;
192       } else {
193         cat.warn("Could not find config file ["+configFile+"].");
194         return genericHierarchy();
195       }
196     }
197   }
198
199   LoggerRepository  genericHierarchy() {
200     if(genericHierarchy == null) {
201       File f = new File(dir, GENERIC+CONFIG_FILE_EXT);
202       if(f.exists()) {
203         genericHierarchy = new Hierarchy(new RootLogger(Level.DEBUG));
204         new PropertyConfigurator().doConfigure(f.getAbsolutePath(), genericHierarchy);
205       } else {
206         cat.warn("Could not find config file ["+f+
207                  "]. Will use the default hierarchy.");
208         genericHierarchy = LogManager.getLoggerRepository();
209       }
210     }
211     return genericHierarchy;
212   }
213 }