1. /*
  2. * Copyright 2002,2004 The Apache Software Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. */
  17. package org.apache.tools.ant.listener;
  18. import java.io.FileInputStream;
  19. import java.io.IOException;
  20. import java.io.InputStream;
  21. import java.io.PrintStream;
  22. import java.util.Properties;
  23. import org.apache.tools.ant.DefaultLogger;
  24. import org.apache.tools.ant.Project;
  25. /**
  26. * Uses ANSI Color Code Sequences to colorize messages
  27. * sent to the console.
  28. *
  29. * If used with the -logfile option, the output file
  30. * will contain all the necessary escape codes to
  31. * display the text in colorized mode when displayed
  32. * in the console using applications like cat, more,
  33. * etc.
  34. *
  35. * This is designed to work on terminals that support ANSI
  36. * color codes. It works on XTerm, ETerm, Mindterm, etc.
  37. * It also works on Win9x (with ANSI.SYS loaded.)
  38. *
  39. * NOTE:
  40. * It doesn't work on WinNT's COMMAND.COM even with
  41. * ANSI.SYS loaded.
  42. *
  43. * The default colors used for differentiating
  44. * the message levels can be changed by editing the
  45. * /org/apache/tools/ant/listener/defaults.properties
  46. * file.
  47. * This file contains 5 key/value pairs:
  48. * AnsiColorLogger.ERROR_COLOR=2;31
  49. * AnsiColorLogger.WARNING_COLOR=2;35
  50. * AnsiColorLogger.INFO_COLOR=2;36
  51. * AnsiColorLogger.VERBOSE_COLOR=2;32
  52. * AnsiColorLogger.DEBUG_COLOR=2;34
  53. *
  54. * Another option is to pass a system variable named
  55. * ant.logger.defaults, with value set to the path of
  56. * the file that contains user defined Ansi Color
  57. * Codes, to the <B>java</B> command using -D option.
  58. *
  59. * To change these colors use the following chart:
  60. *
  61. * <B>ANSI COLOR LOGGER CONFIGURATION</B>
  62. *
  63. * Format for AnsiColorLogger.*=
  64. * Attribute;Foreground;Background
  65. *
  66. * Attribute is one of the following:
  67. * 0 -> Reset All Attributes (return to normal mode)
  68. * 1 -> Bright (Usually turns on BOLD)
  69. * 2 -> Dim
  70. * 3 -> Underline
  71. * 5 -> link
  72. * 7 -> Reverse
  73. * 8 -> Hidden
  74. *
  75. * Foreground is one of the following:
  76. * 30 -> Black
  77. * 31 -> Red
  78. * 32 -> Green
  79. * 33 -> Yellow
  80. * 34 -> Blue
  81. * 35 -> Magenta
  82. * 36 -> Cyan
  83. * 37 -> White
  84. *
  85. * Background is one of the following:
  86. * 40 -> Black
  87. * 41 -> Red
  88. * 42 -> Green
  89. * 43 -> Yellow
  90. * 44 -> Blue
  91. * 45 -> Magenta
  92. * 46 -> Cyan
  93. * 47 -> White
  94. *
  95. */
  96. public final class AnsiColorLogger extends DefaultLogger {
  97. // private static final int ATTR_NORMAL = 0;
  98. // private static final int ATTR_BRIGHT = 1;
  99. private static final int ATTR_DIM = 2;
  100. // private static final int ATTR_UNDERLINE = 3;
  101. // private static final int ATTR_BLINK = 5;
  102. // private static final int ATTR_REVERSE = 7;
  103. // private static final int ATTR_HIDDEN = 8;
  104. // private static final int FG_BLACK = 30;
  105. private static final int FG_RED = 31;
  106. private static final int FG_GREEN = 32;
  107. // private static final int FG_YELLOW = 33;
  108. private static final int FG_BLUE = 34;
  109. private static final int FG_MAGENTA = 35;
  110. private static final int FG_CYAN = 36;
  111. // private static final int FG_WHITE = 37;
  112. // private static final int BG_BLACK = 40;
  113. // private static final int BG_RED = 41;
  114. // private static final int BG_GREEN = 42;
  115. // private static final int BG_YELLOW = 44;
  116. // private static final int BG_BLUE = 44;
  117. // private static final int BG_MAGENTA = 45;
  118. // private static final int BG_CYAN = 46;
  119. // private static final int BG_WHITE = 47;
  120. private static final String PREFIX = "\u001b[";
  121. private static final String SUFFIX = "m";
  122. private static final char SEPARATOR = ';';
  123. private static final String END_COLOR = PREFIX + SUFFIX;
  124. private String errColor
  125. = PREFIX + ATTR_DIM + SEPARATOR + FG_RED + SUFFIX;
  126. private String warnColor
  127. = PREFIX + ATTR_DIM + SEPARATOR + FG_MAGENTA + SUFFIX;
  128. private String infoColor
  129. = PREFIX + ATTR_DIM + SEPARATOR + FG_CYAN + SUFFIX;
  130. private String verboseColor
  131. = PREFIX + ATTR_DIM + SEPARATOR + FG_GREEN + SUFFIX;
  132. private String debugColor
  133. = PREFIX + ATTR_DIM + SEPARATOR + FG_BLUE + SUFFIX;
  134. private boolean colorsSet = false;
  135. /**
  136. * Set the colors to use from a property file specified by the
  137. * special ant property ant.logger.defaults
  138. */
  139. private final void setColors() {
  140. String userColorFile = System.getProperty("ant.logger.defaults");
  141. String systemColorFile =
  142. "/org/apache/tools/ant/listener/defaults.properties";
  143. InputStream in = null;
  144. try {
  145. Properties prop = new Properties();
  146. if (userColorFile != null) {
  147. in = new FileInputStream(userColorFile);
  148. } else {
  149. in = getClass().getResourceAsStream(systemColorFile);
  150. }
  151. if (in != null) {
  152. prop.load(in);
  153. }
  154. String err = prop.getProperty("AnsiColorLogger.ERROR_COLOR");
  155. String warn = prop.getProperty("AnsiColorLogger.WARNING_COLOR");
  156. String info = prop.getProperty("AnsiColorLogger.INFO_COLOR");
  157. String verbose = prop.getProperty("AnsiColorLogger.VERBOSE_COLOR");
  158. String debug = prop.getProperty("AnsiColorLogger.DEBUG_COLOR");
  159. if (err != null) {
  160. errColor = PREFIX + err + SUFFIX;
  161. }
  162. if (warn != null) {
  163. warnColor = PREFIX + warn + SUFFIX;
  164. }
  165. if (info != null) {
  166. infoColor = PREFIX + info + SUFFIX;
  167. }
  168. if (verbose != null) {
  169. verboseColor = PREFIX + verbose + SUFFIX;
  170. }
  171. if (debug != null) {
  172. debugColor = PREFIX + debug + SUFFIX;
  173. }
  174. } catch (IOException ioe) {
  175. //Ignore - we will use the defaults.
  176. } finally {
  177. if (in != null) {
  178. try {
  179. in.close();
  180. } catch (IOException e) {
  181. //Ignore - We do not want this to stop the build.
  182. }
  183. }
  184. }
  185. }
  186. /**
  187. * @see DefaultLogger#printMessage
  188. */
  189. protected final void printMessage(final String message,
  190. final PrintStream stream,
  191. final int priority) {
  192. if (message != null && stream != null) {
  193. if (!colorsSet) {
  194. setColors();
  195. colorsSet = true;
  196. }
  197. final StringBuffer msg = new StringBuffer(message);
  198. switch (priority) {
  199. case Project.MSG_ERR:
  200. msg.insert(0, errColor);
  201. msg.append(END_COLOR);
  202. break;
  203. case Project.MSG_WARN:
  204. msg.insert(0, warnColor);
  205. msg.append(END_COLOR);
  206. break;
  207. case Project.MSG_INFO:
  208. msg.insert(0, infoColor);
  209. msg.append(END_COLOR);
  210. break;
  211. case Project.MSG_VERBOSE:
  212. msg.insert(0, verboseColor);
  213. msg.append(END_COLOR);
  214. break;
  215. case Project.MSG_DEBUG:
  216. msg.insert(0, debugColor);
  217. msg.append(END_COLOR);
  218. break;
  219. }
  220. final String strmessage = msg.toString();
  221. stream.println(strmessage);
  222. }
  223. }
  224. }