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 org.apache.commons.logging.Log;
  19. import org.apache.commons.logging.LogConfigurationException;
  20. import org.apache.commons.logging.LogFactory;
  21. import org.apache.tools.ant.BuildListener;
  22. import org.apache.tools.ant.BuildLogger;
  23. import org.apache.tools.ant.BuildEvent;
  24. import org.apache.tools.ant.Project;
  25. import org.apache.tools.ant.Task;
  26. import org.apache.tools.ant.UnknownElement;
  27. import java.io.PrintStream;
  28. /**
  29. * Jakarta Commons Logging listener.
  30. * Note: do not use the SimpleLog as your logger implementation as it
  31. * causes an infinite loop since it writes to System.err, which Ant traps
  32. * and reroutes to the logger/listener layer.
  33. *
  34. * The following names are used for the log:
  35. * org.apache.tools.ant.Project.PROJECT_NAME - for project events
  36. * org.apache.tools.ant.Target.TARGET_NAME - for target events
  37. * TASK_CLASS_NAME.TARGET_NAME - for events in individual targets.
  38. *
  39. * In all target and project names we replace "." and " " with "-".
  40. *
  41. * TODO: we should use the advanced context logging features (and expose them
  42. * in c-l first :-)
  43. * TODO: this is _very_ inefficient. Switching the out and tracking the logs
  44. * can be optimized a lot - but may require few more changes to the core.
  45. *
  46. * @since Ant 1.5
  47. */
  48. public class CommonsLoggingListener implements BuildListener, BuildLogger {
  49. /** Indicates if the listener was initialized. */
  50. private boolean initialized = false;
  51. private LogFactory logFactory;
  52. /**
  53. * Construct the listener and make sure that a LogFactory
  54. * can be obtained.
  55. */
  56. public CommonsLoggingListener() {
  57. }
  58. private Log getLog(String cat, String suffix) {
  59. if (suffix != null) {
  60. suffix = suffix.replace('.', '-');
  61. suffix = suffix.replace(' ', '-');
  62. cat = cat + "." + suffix;
  63. }
  64. PrintStream tmpOut = System.out;
  65. PrintStream tmpErr = System.err;
  66. System.setOut(out);
  67. System.setErr(err);
  68. if (!initialized) {
  69. try {
  70. logFactory = LogFactory.getFactory();
  71. } catch (LogConfigurationException e) {
  72. e.printStackTrace(System.err);
  73. return null;
  74. }
  75. }
  76. initialized = true;
  77. Log log = logFactory.getInstance(cat);
  78. System.setOut(tmpOut);
  79. System.setErr(tmpErr);
  80. return log;
  81. }
  82. /**
  83. * @see BuildListener#buildStarted
  84. */
  85. public void buildStarted(BuildEvent event) {
  86. String categoryString = "org.apache.tools.ant.Project";
  87. Log log = getLog(categoryString, null);
  88. if (initialized) {
  89. realLog(log, "Build started.", Project.MSG_INFO, null);
  90. }
  91. }
  92. /**
  93. * @see BuildListener#buildFinished
  94. */
  95. public void buildFinished(BuildEvent event) {
  96. if (initialized) {
  97. String categoryString = "org.apache.tools.ant.Project";
  98. Log log = getLog(categoryString, event.getProject().getName());
  99. if (event.getException() == null) {
  100. realLog(log, "Build finished.", Project.MSG_INFO, null);
  101. } else {
  102. realLog(log, "Build finished with error.", Project.MSG_ERR,
  103. event.getException());
  104. }
  105. }
  106. }
  107. /**
  108. * @see BuildListener#targetStarted
  109. */
  110. public void targetStarted(BuildEvent event) {
  111. if (initialized) {
  112. Log log = getLog("org.apache.tools.ant.Target",
  113. event.getTarget().getName());
  114. // Since task log category includes target, we don't really
  115. // need this message
  116. realLog(log, "Start: " + event.getTarget().getName(),
  117. Project.MSG_DEBUG, null);
  118. }
  119. }
  120. /**
  121. * @see BuildListener#targetFinished
  122. */
  123. public void targetFinished(BuildEvent event) {
  124. if (initialized) {
  125. String targetName = event.getTarget().getName();
  126. Log log = getLog("org.apache.tools.ant.Target",
  127. event.getTarget().getName());
  128. if (event.getException() == null) {
  129. realLog(log, "Target end: " + targetName, Project.MSG_DEBUG, null);
  130. } else {
  131. realLog(log, "Target \"" + targetName
  132. + "\" finished with error.", Project.MSG_ERR,
  133. event.getException());
  134. }
  135. }
  136. }
  137. /**
  138. * @see BuildListener#taskStarted
  139. */
  140. public void taskStarted(BuildEvent event) {
  141. if (initialized) {
  142. Task task = event.getTask();
  143. Object real = task;
  144. if (task instanceof UnknownElement) {
  145. Object realObj = ((UnknownElement) task).getTask();
  146. if (realObj != null) {
  147. real = realObj;
  148. }
  149. }
  150. Log log = getLog(real.getClass().getName(), null);
  151. if (log.isTraceEnabled()) {
  152. realLog(log, "Task \"" + task.getTaskName() + "\" started ",
  153. Project.MSG_VERBOSE, null);
  154. }
  155. }
  156. }
  157. /**
  158. * @see BuildListener#taskFinished
  159. */
  160. public void taskFinished(BuildEvent event) {
  161. if (initialized) {
  162. Task task = event.getTask();
  163. Object real = task;
  164. if (task instanceof UnknownElement) {
  165. Object realObj = ((UnknownElement) task).getTask();
  166. if (realObj != null) {
  167. real = realObj;
  168. }
  169. }
  170. Log log = getLog(real.getClass().getName(), null);
  171. if (event.getException() == null) {
  172. if (log.isTraceEnabled()) {
  173. realLog(log, "Task \"" + task.getTaskName() + "\" finished.",
  174. Project.MSG_VERBOSE, null);
  175. }
  176. } else {
  177. realLog(log, "Task \"" + task.getTaskName()
  178. + "\" finished with error.", Project.MSG_ERR,
  179. event.getException());
  180. }
  181. }
  182. }
  183. /**
  184. * @see BuildListener#messageLogged
  185. */
  186. public void messageLogged(BuildEvent event) {
  187. if (initialized) {
  188. Object categoryObject = event.getTask();
  189. String categoryString = null;
  190. String categoryDetail = null;
  191. if (categoryObject == null) {
  192. categoryObject = event.getTarget();
  193. if (categoryObject == null) {
  194. categoryObject = event.getProject();
  195. categoryString = "org.apache.tools.ant.Project";
  196. categoryDetail = event.getProject().getName();
  197. } else {
  198. categoryString = "org.apache.tools.ant.Target";
  199. categoryDetail = event.getTarget().getName();
  200. }
  201. } else {
  202. // It's a task - append the target
  203. if (event.getTarget() != null) {
  204. categoryString = categoryObject.getClass().getName();
  205. categoryDetail = event.getTarget().getName();
  206. } else {
  207. categoryString = categoryObject.getClass().getName();
  208. }
  209. }
  210. Log log = getLog(categoryString, categoryDetail);
  211. int priority = event.getPriority();
  212. String message = event.getMessage();
  213. realLog(log, message, priority , null);
  214. }
  215. }
  216. private void realLog(Log log, String message, int priority, Throwable t) {
  217. PrintStream tmpOut = System.out;
  218. PrintStream tmpErr = System.err;
  219. System.setOut(out);
  220. System.setErr(err);
  221. switch (priority) {
  222. case Project.MSG_ERR:
  223. if (t == null) {
  224. log.error(message);
  225. } else {
  226. log.error(message, t);
  227. }
  228. break;
  229. case Project.MSG_WARN:
  230. if (t == null) {
  231. log.warn(message);
  232. } else {
  233. log.warn(message, t);
  234. }
  235. break;
  236. case Project.MSG_INFO:
  237. if (t == null) {
  238. log.info(message);
  239. } else {
  240. log.info(message, t);
  241. }
  242. break;
  243. case Project.MSG_VERBOSE:
  244. log.debug(message);
  245. break;
  246. case Project.MSG_DEBUG:
  247. log.debug(message);
  248. break;
  249. default:
  250. log.error(message);
  251. break;
  252. }
  253. System.setOut(tmpOut);
  254. System.setErr(tmpErr);
  255. }
  256. PrintStream out = System.out;
  257. PrintStream err = System.err;
  258. public void setMessageOutputLevel(int level) {
  259. // Use the logger config
  260. }
  261. public void setOutputPrintStream(PrintStream output) {
  262. this.out = output;
  263. }
  264. public void setEmacsMode(boolean emacsMode) {
  265. // Doesn't make sense for c-l. Use the logger config
  266. }
  267. public void setErrorPrintStream(PrintStream err) {
  268. this.err = err;
  269. }
  270. }