PageRenderTime 40ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-1-pre5/org/gjt/sp/util/Log.java

#
Java | 356 lines | 219 code | 36 blank | 101 comment | 29 complexity | 79ef69ab4e8baf70cc836d715d601caa MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. /*
  2. * Log.java - A class for logging events
  3. * Copyright (C) 1999, 2000 Slava Pestov
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License
  7. * as published by the Free Software Foundation; either version 2
  8. * of the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18. */
  19. package org.gjt.sp.util;
  20. import javax.swing.text.*;
  21. import java.io.*;
  22. import java.util.StringTokenizer;
  23. /**
  24. * This class provides methods for logging events. It has the same
  25. * purpose as System.out.println() and such, but more powerful.
  26. * All events are logged to a Swing document and optionally a stream,
  27. * and those with a high urgency (warnings and errors) are also printed
  28. * to the standard error stream. This class can also optionally redirect
  29. * standard output and error to the log.
  30. * @author Slava Pestov
  31. * @version $Id: Log.java 3945 2001-12-25 03:06:50Z spestov $
  32. */
  33. public class Log
  34. {
  35. /**
  36. * The maximum number of log messages that will be kept in memory.
  37. * @since jEdit 2.6pre5
  38. */
  39. public static final int MAXLINES = 500;
  40. /**
  41. * Debugging message urgency. Should be used for messages only
  42. * useful when debugging a problem.
  43. * @since jEdit 2.2pre2
  44. */
  45. public static final int DEBUG = 1;
  46. /**
  47. * Message urgency. Should be used for messages which give more
  48. * detail than notices.
  49. * @since jEdit 2.2pre2
  50. */
  51. public static final int MESSAGE = 3;
  52. /**
  53. * Notice urgency. Should be used for messages that directly
  54. * affect the user.
  55. * @since jEdit 2.2pre2
  56. */
  57. public static final int NOTICE = 5;
  58. /**
  59. * Warning urgency. Should be used for messages that warrant
  60. * attention.
  61. * @since jEdit 2.2pre2
  62. */
  63. public static final int WARNING = 7;
  64. /**
  65. * Error urgency. Should be used for messages that signal a
  66. * failure.
  67. * @since jEdit 2.2pre2
  68. */
  69. public static final int ERROR = 9;
  70. /**
  71. * Initializes the log.
  72. * @param stdio If true, standard output and error will be
  73. * sent to the log
  74. * @param level Messages with this log level or higher will
  75. * be printed to the system console
  76. * @param stream The stream to save log data to
  77. * @since jEdit 3.2pre4
  78. */
  79. public static void init(boolean stdio, int level)
  80. {
  81. if(stdio)
  82. {
  83. if(System.out == realOut && System.err == realErr)
  84. {
  85. System.setOut(createPrintStream(NOTICE,null));
  86. System.setErr(createPrintStream(ERROR,null));
  87. }
  88. }
  89. Log.level = level;
  90. // Log some stuff
  91. log(MESSAGE,Log.class,"When reporting bugs, please"
  92. + " include the following information:");
  93. String[] props = {
  94. "java.version", "java.vm.version", "java.runtime.version",
  95. "java.vendor", "java.compiler", "os.name", "os.version",
  96. "os.arch", "user.home", "java.home",
  97. "java.class.path",
  98. };
  99. for(int i = 0; i < props.length; i++)
  100. {
  101. log(MESSAGE,Log.class,
  102. props[i] + "=" + System.getProperty(props[i]));
  103. }
  104. }
  105. /**
  106. * Writes all currently logged messages to this stream if there was no
  107. * stream set previously, and sets the stream to write future log
  108. * messages to.
  109. * @param stream The writer
  110. * @since jEdit 3.2pre4
  111. */
  112. public static void setLogWriter(Writer stream)
  113. {
  114. if(Log.stream == null && stream != null)
  115. {
  116. try
  117. {
  118. stream.write(logDocument.getText(0,
  119. logDocument.getLength()));
  120. stream.flush();
  121. }
  122. catch(Exception e)
  123. {
  124. // do nothing, who cares
  125. }
  126. }
  127. Log.stream = stream;
  128. }
  129. /**
  130. * Returns the document where the most recent messages are stored.
  131. * The document of a Swing text area can be set to this to graphically
  132. * view log messages.
  133. * @since jEdit 2.2pre2
  134. */
  135. public static Document getLogDocument()
  136. {
  137. return logDocument;
  138. }
  139. /**
  140. * Flushes the log stream.
  141. * @since jEdit 2.6pre5
  142. */
  143. public static void flushStream()
  144. {
  145. if(stream != null)
  146. {
  147. try
  148. {
  149. stream.flush();
  150. }
  151. catch(IOException io)
  152. {
  153. io.printStackTrace(realErr);
  154. }
  155. }
  156. }
  157. /**
  158. * Closes the log stream. Should be done before your program exits.
  159. * @since jEdit 2.6pre5
  160. */
  161. public static void closeStream()
  162. {
  163. if(stream != null)
  164. {
  165. try
  166. {
  167. stream.close();
  168. stream = null;
  169. }
  170. catch(IOException io)
  171. {
  172. io.printStackTrace(realErr);
  173. }
  174. }
  175. }
  176. /**
  177. * Logs a message. This method is threadsafe.
  178. * @param urgency The urgency
  179. * @param source The object that logged this message.
  180. * @param message The message. This can either be a string or
  181. * an exception
  182. *
  183. * @since jEdit 2.2pre2
  184. */
  185. public static void log(int urgency, Object source, Object message)
  186. {
  187. String _source;
  188. if(source == null)
  189. {
  190. _source = Thread.currentThread().getName();
  191. if(_source == null)
  192. {
  193. _source = Thread.currentThread().getClass().getName();
  194. }
  195. }
  196. else if(source instanceof Class)
  197. _source = ((Class)source).getName();
  198. else
  199. _source = source.getClass().getName();
  200. int index = _source.lastIndexOf('.');
  201. if(index != -1)
  202. _source = _source.substring(index+1);
  203. if(message instanceof Throwable)
  204. {
  205. _logException(urgency,source,(Throwable)message);
  206. }
  207. else
  208. {
  209. String _message = String.valueOf(message);
  210. // If multiple threads log stuff, we don't want
  211. // the output to get mixed up
  212. synchronized(LOCK)
  213. {
  214. StringTokenizer st = new StringTokenizer(
  215. _message,"\r\n");
  216. while(st.hasMoreTokens())
  217. {
  218. _log(urgency,_source,st.nextToken());
  219. }
  220. }
  221. }
  222. }
  223. // private members
  224. private static Object LOCK = new Object();
  225. private static Document logDocument;
  226. private static int level = WARNING;
  227. private static Writer stream;
  228. private static String lineSep;
  229. private static PrintStream realOut;
  230. private static PrintStream realErr;
  231. static
  232. {
  233. level = WARNING;
  234. realOut = System.out;
  235. realErr = System.err;
  236. logDocument = new PlainDocument();
  237. lineSep = System.getProperty("line.separator");
  238. }
  239. private static PrintStream createPrintStream(final int urgency,
  240. final Object source)
  241. {
  242. return new PrintStream(new OutputStream() {
  243. public void write(int b)
  244. {
  245. byte[] barray = { (byte)b };
  246. write(barray,0,1);
  247. }
  248. public void write(byte[] b, int off, int len)
  249. {
  250. String str = new String(b,off,len);
  251. log(urgency,source,str);
  252. }
  253. });
  254. }
  255. private static void _logException(final int urgency,
  256. final Object source,
  257. final Throwable message)
  258. {
  259. PrintStream out = createPrintStream(urgency,source);
  260. synchronized(LOCK)
  261. {
  262. message.printStackTrace(out);
  263. }
  264. }
  265. private static void _log(int urgency, String source, String message)
  266. {
  267. String urgencyString = "[" + urgencyToString(urgency) + "] ";
  268. String fullMessage = urgencyString + source + ": " + message;
  269. try
  270. {
  271. logDocument.insertString(logDocument.getLength(),
  272. fullMessage,null);
  273. logDocument.insertString(logDocument.getLength(),
  274. "\n",null);
  275. Element map = logDocument.getDefaultRootElement();
  276. int lines = map.getElementCount();
  277. if(lines > MAXLINES)
  278. {
  279. Element first = map.getElement(0);
  280. Element last = map.getElement(lines - MAXLINES);
  281. logDocument.remove(first.getStartOffset(),
  282. last.getEndOffset());
  283. }
  284. if(stream != null)
  285. {
  286. stream.write(fullMessage);
  287. stream.write(lineSep);
  288. }
  289. }
  290. catch(Exception e)
  291. {
  292. e.printStackTrace(realErr);
  293. }
  294. message = urgencyString + message + '\n';
  295. if(urgency >= level)
  296. {
  297. if(urgency == ERROR)
  298. realErr.print(message);
  299. else
  300. realOut.print(message);
  301. }
  302. }
  303. private static String urgencyToString(int urgency)
  304. {
  305. switch(urgency)
  306. {
  307. case DEBUG:
  308. return "debug";
  309. case MESSAGE:
  310. return "message";
  311. case NOTICE:
  312. return "notice";
  313. case WARNING:
  314. return "warning";
  315. case ERROR:
  316. return "error";
  317. }
  318. throw new IllegalArgumentException("Invalid urgency: " + urgency);
  319. }
  320. }