1. /*
  2. * Copyright 2000-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.ByteArrayOutputStream;
  19. import java.io.IOException;
  20. import java.io.OutputStream;
  21. import org.apache.tools.ant.Project;
  22. import org.apache.tools.ant.Task;
  23. /**
  24. * Logs each line written to this stream to the log system of ant.
  25. *
  26. * Tries to be smart about line separators.<br>
  27. * TODO: This class can be split to implement other line based processing
  28. * of data written to the stream.
  29. *
  30. * @since Ant 1.2
  31. */
  32. public class LogOutputStream extends OutputStream {
  33. /** Initial buffer size. */
  34. private static final int INTIAL_SIZE = 132;
  35. /** Carriage return */
  36. private static final int CR = 0x0d;
  37. /** Linefeed */
  38. private static final int LF = 0x0a;
  39. private ByteArrayOutputStream buffer
  40. = new ByteArrayOutputStream(INTIAL_SIZE);
  41. private boolean skip = false;
  42. private Task task;
  43. private int level = Project.MSG_INFO;
  44. /**
  45. * Creates a new instance of this class.
  46. *
  47. * @param task the task for whom to log
  48. * @param level loglevel used to log data written to this stream.
  49. */
  50. public LogOutputStream(Task task, int level) {
  51. this.task = task;
  52. this.level = level;
  53. }
  54. /**
  55. * Write the data to the buffer and flush the buffer, if a line
  56. * separator is detected.
  57. *
  58. * @param cc data to log (byte).
  59. */
  60. public void write(int cc) throws IOException {
  61. final byte c = (byte) cc;
  62. if ((c == '\n') || (c == '\r')) {
  63. if (!skip) {
  64. processBuffer();
  65. }
  66. } else {
  67. buffer.write(cc);
  68. }
  69. skip = (c == '\r');
  70. }
  71. /**
  72. * Flush this log stream
  73. */
  74. public void flush() {
  75. if (buffer.size() > 0) {
  76. processBuffer();
  77. }
  78. }
  79. /**
  80. * Converts the buffer to a string and sends it to <code>processLine</code>
  81. */
  82. protected void processBuffer() {
  83. processLine(buffer.toString());
  84. buffer.reset();
  85. }
  86. /**
  87. * Logs a line to the log system of ant.
  88. *
  89. * @param line the line to log.
  90. */
  91. protected void processLine(String line) {
  92. processLine(line, level);
  93. }
  94. /**
  95. * Logs a line to the log system of ant.
  96. *
  97. * @param line the line to log.
  98. */
  99. protected void processLine(String line, int level) {
  100. task.log(line, level);
  101. }
  102. /**
  103. * Writes all remaining
  104. */
  105. public void close() throws IOException {
  106. if (buffer.size() > 0) {
  107. processBuffer();
  108. }
  109. super.close();
  110. }
  111. public int getMessageLevel() {
  112. return level;
  113. }
  114. /**
  115. * Write a block of characters to the output stream
  116. *
  117. * @param b the array containing the data
  118. * @param off the offset into the array where data starts
  119. * @param len the length of block
  120. *
  121. * @throws IOException if the data cannot be written into the stream.
  122. */
  123. public void write(byte[] b, int off, int len) throws IOException {
  124. // find the line breaks and pass other chars through in blocks
  125. int offset = off;
  126. int blockStartOffset = offset;
  127. int remaining = len;
  128. while (remaining > 0) {
  129. while (remaining > 0 && b[offset] != LF && b[offset] != CR) {
  130. offset++;
  131. remaining--;
  132. }
  133. // either end of buffer or a line separator char
  134. int blockLength = offset - blockStartOffset;
  135. if (blockLength > 0) {
  136. buffer.write(b, blockStartOffset, blockLength);
  137. }
  138. while (remaining > 0 && (b[offset] == LF || b[offset] == CR)) {
  139. write(b[offset]);
  140. offset++;
  141. remaining--;
  142. }
  143. blockStartOffset = offset;
  144. }
  145. }
  146. }