Initial import
[jpf-core.git] / src / main / gov / nasa / jpf / util / LogHandler.java
1 /*
2  * Copyright (C) 2014, United States Government, as represented by the
3  * Administrator of the National Aeronautics and Space Administration.
4  * All rights reserved.
5  *
6  * The Java Pathfinder core (jpf-core) platform is licensed under the
7  * Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  * 
10  *        http://www.apache.org/licenses/LICENSE-2.0. 
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and 
16  * limitations under the License.
17  */
18 package gov.nasa.jpf.util;
19
20 import gov.nasa.jpf.Config;
21
22 import java.io.File;
23 import java.io.FileOutputStream;
24 import java.io.IOException;
25 import java.io.OutputStream;
26 import java.io.PrintWriter;
27 import java.net.ConnectException;
28 import java.net.Socket;
29 import java.net.UnknownHostException;
30 import java.util.logging.Formatter;
31 import java.util.logging.Handler;
32 import java.util.logging.LogRecord;
33 import java.util.logging.Logger;
34
35 /**
36  * log handler class that deals with output selection and formatting. This is the
37  * only handler we use for our own logging. We do our own little formatting
38  * on the fly
39  */
40 public class LogHandler extends Handler {
41
42   static class DefaultFormatter extends Formatter {
43     boolean format;
44     boolean showName;
45     boolean showLevel;
46     //..and potentially more
47     
48     DefaultFormatter (Config conf) {
49       showName = conf.getBoolean("log.show_name", false);
50       showLevel = conf.getBoolean("log.show_level", true);
51       format = showName || showLevel;
52     }
53
54     DefaultFormatter (boolean showName, boolean showLevel){
55       this.showName = showName;
56       this.showLevel = showLevel;
57       format = showName || showLevel;
58     }
59
60     // we might want to parameterize this
61     @Override
62         public String format (LogRecord r) {
63       if (format) {
64         StringBuilder sb = new StringBuilder();
65         sb.append('[');
66         if (showLevel) {          
67           sb.append(r.getLevel().getName());
68         }
69         if (showName) {
70           if (showLevel) {
71             sb.append(":");
72           }
73           sb.append(r.getLoggerName());
74         }
75         sb.append("] ");
76         
77         String msg = r.getMessage();
78         Object[] params = r.getParameters();
79         
80         if (params == null){
81           sb.append(msg);
82         } else {
83           sb.append(String.format(msg,params));
84         }
85         
86         return sb.toString();
87         
88       } else { // raw
89         return r.getMessage();
90       }
91     }
92   }
93   
94   public static String LOG_HOST = "localhost";
95   public static int LOG_PORT = 20000;
96   
97   File file;
98   Socket socket;
99   OutputStream ostream;
100   
101   PrintWriter out;
102   
103   public LogHandler (Config conf) {
104     LOG_HOST = conf.getString("log.host", LOG_HOST);
105     LOG_PORT = conf.getInt("log.port", LOG_PORT);
106     
107     String output = conf.getString("log.output", "out");
108     
109     if (output.matches("[a-zA-Z0-9.]*:[0-9]*")) { // we assume that's a hostname:port spec
110       int idx = output.indexOf(':');
111       String host = output.substring(0, idx);
112       String port = output.substring(idx+1, output.length());
113       ostream = connectSocket( host, port);
114     } else if (output.equalsIgnoreCase("socket")){
115       ostream = connectSocket( LOG_HOST, Integer.toString(LOG_PORT));
116     } else if (output.equalsIgnoreCase("out") || output.equals("System.out")) {
117       ostream = System.out;
118     } else if (output.equalsIgnoreCase("err") || output.equals("System.err")) {
119       ostream = System.err;
120     } else {
121       ostream = openFile(output);
122     }
123     
124     if (ostream == null) {
125       ostream = System.out;
126     }
127     
128     setFormatter(new DefaultFormatter(conf));
129     setOutput(ostream);
130   }
131
132   protected LogHandler() {
133     // for derived classes
134   }
135
136   OutputStream connectSocket (String host, String portSpec) {
137     int port = -1;
138     
139     if ((host == null) || (host.length() == 0)) {
140       host = LOG_HOST;
141     }
142     
143     if (portSpec != null) {
144       try {
145         port = Integer.parseInt(portSpec);
146       } catch (NumberFormatException x) {
147         // just catch it
148       }
149     }
150     if (port == -1) {
151       port = LOG_PORT;
152     }
153     
154     
155     try {
156       socket = new Socket(host, port);
157       return socket.getOutputStream();
158     } catch (UnknownHostException uhx) {
159       //System.err.println("unknown log host: " + host);
160     } catch (ConnectException cex) {
161       //System.err.println("no log host detected);
162     } catch (IOException iox) {
163       //System.err.println(iox);
164     }
165
166     return null;
167   }
168   
169   OutputStream openFile (String fileName) {
170     file = new File(fileName);
171     
172     try {
173       if (file.exists()) {
174         file.delete();
175       }
176       file.createNewFile();
177       return new FileOutputStream(file);
178     } catch (IOException iox) {
179       // just catch it
180     }
181     
182     return null;
183   }
184   
185   public void setOutput (OutputStream ostream) {
186     out = new PrintWriter(ostream, true);
187   }
188   
189   @Override
190   public void close () throws SecurityException {
191     if ((ostream != System.err) && (ostream != System.out)) {
192       out.close();
193     }
194     
195     if (socket != null) {
196       try {
197         socket.close();
198       } catch (IOException iox) {
199         // not much we can do
200       }
201     }
202   }
203
204   @Override
205   public void flush () {
206     out.flush();
207   }
208
209   @Override
210   public void publish (LogRecord r) {
211     String msg = getFormatter().format(r);
212     out.println(msg);
213   }
214
215   public void printStatus (Logger log) {   
216     if (socket != null) {
217       log.config("logging to socket: " + socket);
218     } else if (file != null) {
219       log.config("logging to file: " + file.getAbsolutePath());
220     } else if (ostream == System.err) {
221       log.config("logging to System.err");
222     } else if (ostream == System.out) {
223       log.config("logging to System.out");
224     } else {
225       log.warning("unknown log destination");
226     }
227   }
228
229
230   // a dfault handler that doesn't need Config
231   public static class DefaultConsoleHandler extends LogHandler {
232     public DefaultConsoleHandler() {
233       ostream = System.out;
234
235       setFormatter(new DefaultFormatter(false,true));
236       setOutput(ostream);
237     }
238   }
239 }