1. /*
  2. * Copyright 2001-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.taskdefs;
  18. import java.io.PrintStream;
  19. import org.apache.tools.ant.BuildEvent;
  20. import org.apache.tools.ant.BuildLogger;
  21. import org.apache.tools.ant.DefaultLogger;
  22. import org.apache.tools.ant.Project;
  23. import org.apache.tools.ant.SubBuildListener;
  24. import org.apache.tools.ant.util.StringUtils;
  25. /**
  26. * This is a class that represents a recorder. This is the listener to the
  27. * build process.
  28. *
  29. * @version 0.5
  30. * @since Ant 1.4
  31. */
  32. public class RecorderEntry implements BuildLogger, SubBuildListener {
  33. //////////////////////////////////////////////////////////////////////
  34. // ATTRIBUTES
  35. /** The name of the file associated with this recorder entry. */
  36. private String filename = null;
  37. /** The state of the recorder (recorder on or off). */
  38. private boolean record = true;
  39. /** The current verbosity level to record at. */
  40. private int loglevel = Project.MSG_INFO;
  41. /** The output PrintStream to record to. */
  42. private PrintStream out = null;
  43. /** The start time of the last know target. */
  44. private long targetStartTime = 0L;
  45. /** Strip task banners if true. */
  46. private boolean emacsMode = false;
  47. /** project instance the recorder is associated with */
  48. private Project project;
  49. //////////////////////////////////////////////////////////////////////
  50. // CONSTRUCTORS / INITIALIZERS
  51. /**
  52. * @param name The name of this recorder (used as the filename).
  53. */
  54. protected RecorderEntry(String name) {
  55. targetStartTime = System.currentTimeMillis();
  56. filename = name;
  57. }
  58. //////////////////////////////////////////////////////////////////////
  59. // ACCESSOR METHODS
  60. /**
  61. * @return the name of the file the output is sent to.
  62. */
  63. public String getFilename() {
  64. return filename;
  65. }
  66. /**
  67. * Turns off or on this recorder.
  68. *
  69. * @param state true for on, false for off, null for no change.
  70. */
  71. public void setRecordState(Boolean state) {
  72. if (state != null) {
  73. record = state.booleanValue();
  74. }
  75. }
  76. public void buildStarted(BuildEvent event) {
  77. log("> BUILD STARTED", Project.MSG_DEBUG);
  78. }
  79. public void buildFinished(BuildEvent event) {
  80. log("< BUILD FINISHED", Project.MSG_DEBUG);
  81. Throwable error = event.getException();
  82. if (error == null) {
  83. out.println(StringUtils.LINE_SEP + "BUILD SUCCESSFUL");
  84. } else {
  85. out.println(StringUtils.LINE_SEP + "BUILD FAILED"
  86. + StringUtils.LINE_SEP);
  87. error.printStackTrace(out);
  88. }
  89. cleanup();
  90. }
  91. /**
  92. * Cleans up any resources held by this recorder entry at the end
  93. * of a subbuild if it has been created for the subbuild's project
  94. * instance.
  95. *
  96. * @param event the buildFinished event
  97. *
  98. * @since Ant 1.6.2
  99. */
  100. public void subBuildFinished(BuildEvent event) {
  101. if (event.getProject() == project) {
  102. cleanup();
  103. }
  104. }
  105. /**
  106. * Empty implementation to satisfy the BuildListener interface.
  107. *
  108. * @param event the buildStarted event
  109. *
  110. * @since Ant 1.6.2
  111. */
  112. public void subBuildStarted(BuildEvent event) {
  113. }
  114. public void targetStarted(BuildEvent event) {
  115. log(">> TARGET STARTED -- " + event.getTarget(), Project.MSG_DEBUG);
  116. log(StringUtils.LINE_SEP + event.getTarget().getName() + ":",
  117. Project.MSG_INFO);
  118. targetStartTime = System.currentTimeMillis();
  119. }
  120. public void targetFinished(BuildEvent event) {
  121. log("<< TARGET FINISHED -- " + event.getTarget(), Project.MSG_DEBUG);
  122. String time = formatTime(System.currentTimeMillis() - targetStartTime);
  123. log(event.getTarget() + ": duration " + time, Project.MSG_VERBOSE);
  124. out.flush();
  125. }
  126. public void taskStarted(BuildEvent event) {
  127. log(">>> TASK STARTED -- " + event.getTask(), Project.MSG_DEBUG);
  128. }
  129. public void taskFinished(BuildEvent event) {
  130. log("<<< TASK FINISHED -- " + event.getTask(), Project.MSG_DEBUG);
  131. out.flush();
  132. }
  133. public void messageLogged(BuildEvent event) {
  134. log("--- MESSAGE LOGGED", Project.MSG_DEBUG);
  135. StringBuffer buf = new StringBuffer();
  136. if (event.getTask() != null) {
  137. String name = event.getTask().getTaskName();
  138. if (!emacsMode) {
  139. String label = "[" + name + "] ";
  140. int size = DefaultLogger.LEFT_COLUMN_SIZE - label.length();
  141. for (int i = 0; i < size; i++) {
  142. buf.append(" ");
  143. }
  144. buf.append(label);
  145. }
  146. }
  147. buf.append(event.getMessage());
  148. log(buf.toString(), event.getPriority());
  149. }
  150. /**
  151. * The thing that actually sends the information to the output.
  152. *
  153. * @param mesg The message to log.
  154. * @param level The verbosity level of the message.
  155. */
  156. private void log(String mesg, int level) {
  157. if (record && (level <= loglevel)) {
  158. out.println(mesg);
  159. }
  160. }
  161. public void setMessageOutputLevel(int level) {
  162. if (level >= Project.MSG_ERR && level <= Project.MSG_DEBUG) {
  163. loglevel = level;
  164. }
  165. }
  166. public void setOutputPrintStream(PrintStream output) {
  167. out = output;
  168. }
  169. public void setEmacsMode(boolean emacsMode) {
  170. this.emacsMode = emacsMode;
  171. }
  172. public void setErrorPrintStream(PrintStream err) {
  173. out = err;
  174. }
  175. private static String formatTime(long millis) {
  176. long seconds = millis / 1000;
  177. long minutes = seconds / 60;
  178. if (minutes > 0) {
  179. return Long.toString(minutes) + " minute"
  180. + (minutes == 1 ? " " : "s ")
  181. + Long.toString(seconds % 60) + " second"
  182. + (seconds % 60 == 1 ? "" : "s");
  183. } else {
  184. return Long.toString(seconds) + " second"
  185. + (seconds % 60 == 1 ? "" : "s");
  186. }
  187. }
  188. /**
  189. * Set the project associated with this recorder entry.
  190. *
  191. * @param project the project instance
  192. *
  193. * @since 1.6.2
  194. */
  195. public void setProject(Project project) {
  196. this.project = project;
  197. if (project != null) {
  198. project.addBuildListener(this);
  199. }
  200. }
  201. /**
  202. * @since 1.6.2
  203. */
  204. public void cleanup() {
  205. out.flush();
  206. out.close();
  207. if (project != null) {
  208. project.removeBuildListener(this);
  209. }
  210. project = null;
  211. }
  212. }